001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.xbean.finder.archive; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.net.JarURLConnection; 022import java.net.URL; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.List; 026 027/** 028 * Supports JarArchive and FileArchive URLs 029 * 030 * @version $Rev$ $Date$ 031 */ 032public class ClasspathArchive extends CompositeArchive { 033 034 private final List<URL> urls = new ArrayList<URL>(); 035 private final ClassLoader loader; 036 037 public ClasspathArchive(ClassLoader loader, URL... urls) { 038 this(loader, Arrays.asList(urls)); 039 } 040 041 public ClasspathArchive(ClassLoader loader, Iterable<URL> urls) { 042 super(archives(loader, urls)); 043 this.loader = loader; 044 045 } 046 047 public static List<Archive> archives(ClassLoader loader, Iterable<URL> urls) { 048 List<Archive> archives = new ArrayList<Archive>(); 049 050 for (URL location : urls) { 051 try { 052 archives.add(archive(loader, location)); 053 } catch (Exception e) { 054 // TODO This is what we did before, so not too urgent to change, but not ideal 055 e.printStackTrace(); 056 } 057 } 058 059 return archives; 060 } 061 062 public static Archive archive(ClassLoader loader, URL location) { 063 064 if (location.getProtocol().equals("jar")) { 065 066 return new JarArchive(loader, location); 067 068 } else if (location.getProtocol().equals("file")) { 069 070 try { 071 072 // See if it's actually a jar 073 074 URL jarUrl = new URL("jar", "", location.toExternalForm() + "!/"); 075 JarURLConnection juc = (JarURLConnection) jarUrl.openConnection(); 076 juc.getJarFile(); 077 078 return new JarArchive(loader, jarUrl); 079 080 } catch (IOException e) { 081 082 return new FileArchive(loader, location); 083 084 } 085 } 086 087 throw new UnsupportedOperationException("unsupported archive type: " + location); 088 } 089 090 public static List<Archive> archives(ClassLoader loader, URL... urls) { 091 return archives(loader, Arrays.asList(urls)); 092 } 093 094 @Override 095 public InputStream getBytecode(String className) throws IOException, ClassNotFoundException { 096 int pos = className.indexOf("<"); 097 if (pos > -1) { 098 className = className.substring(0, pos); 099 } 100 pos = className.indexOf(">"); 101 if (pos > -1) { 102 className = className.substring(0, pos); 103 } 104 if (!className.endsWith(".class")) { 105 className = className.replace('.', '/') + ".class"; 106 } 107 108 URL resource = loader.getResource(className); 109 if (resource != null) return resource.openStream(); 110 111 throw new ClassNotFoundException(className); 112 } 113 114 @Override 115 public Class<?> loadClass(String className) throws ClassNotFoundException { 116 return loader.loadClass(className); 117 } 118}