0001: /**
0002: *
0003: * Licensed to the Apache Software Foundation (ASF) under one or more
0004: * contributor license agreements. See the NOTICE file distributed with
0005: * this work for additional information regarding copyright ownership.
0006: * The ASF licenses this file to You under the Apache License, Version 2.0
0007: * (the "License"); you may not use this file except in compliance with
0008: * the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing, software
0013: * distributed under the License is distributed on an "AS IS" BASIS,
0014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015: * See the License for the specific language governing permissions and
0016: * limitations under the License.
0017: */package org.apache.openejb.client;
0018:
0019: import java.io.BufferedInputStream;
0020: import java.io.File;
0021: import java.io.IOException;
0022: import java.io.InputStream;
0023: import java.net.HttpURLConnection;
0024: import java.net.JarURLConnection;
0025: import java.net.MalformedURLException;
0026: import java.net.URL;
0027: import java.net.URLConnection;
0028: import java.net.URLDecoder;
0029: import java.util.ArrayList;
0030: import java.util.Collections;
0031: import java.util.Enumeration;
0032: import java.util.HashMap;
0033: import java.util.Iterator;
0034: import java.util.List;
0035: import java.util.Map;
0036: import java.util.Properties;
0037: import java.util.Vector;
0038: import java.util.jar.JarEntry;
0039: import java.util.jar.JarFile;
0040:
0041: /**
0042: * Note: This class is a copy of the xbean-finder ResourceFinder class. Any changes should
0043: * be make to the xbean-finder source first and then copied to this class. Also, this class
0044: * should be kept in sync with the xbean-finder code.
0045: * @author David Blevins
0046: */
0047: public class ResourceFinder {
0048:
0049: private final URL[] urls;
0050: private final String path;
0051: private final ClassLoader classLoader;
0052: private final List<String> resourcesNotLoaded = new ArrayList<String>();
0053:
0054: public ResourceFinder(URL... urls) {
0055: this (null, Thread.currentThread().getContextClassLoader(), urls);
0056: }
0057:
0058: public ResourceFinder(String path) {
0059: this (path, Thread.currentThread().getContextClassLoader(), null);
0060: }
0061:
0062: public ResourceFinder(String path, URL... urls) {
0063: this (path, Thread.currentThread().getContextClassLoader(), urls);
0064: }
0065:
0066: public ResourceFinder(String path, ClassLoader classLoader) {
0067: this (path, classLoader, null);
0068: }
0069:
0070: public ResourceFinder(String path, ClassLoader classLoader,
0071: URL... urls) {
0072: if (path == null) {
0073: path = "";
0074: } else if (path.length() > 0 && !path.endsWith("/")) {
0075: path += "/";
0076: }
0077: this .path = path;
0078:
0079: if (classLoader == null) {
0080: classLoader = Thread.currentThread()
0081: .getContextClassLoader();
0082: }
0083: this .classLoader = classLoader;
0084:
0085: for (int i = 0; urls != null && i < urls.length; i++) {
0086: URL url = urls[i];
0087: if (url == null || isDirectory(url)
0088: || url.getProtocol().equals("jar")) {
0089: continue;
0090: }
0091: try {
0092: urls[i] = new URL("jar", "", -1, url.toString() + "!/");
0093: } catch (MalformedURLException e) {
0094: }
0095: }
0096: this .urls = (urls == null || urls.length == 0) ? null : urls;
0097: }
0098:
0099: private static boolean isDirectory(URL url) {
0100: String file = url.getFile();
0101: return (file.length() > 0 && file.charAt(file.length() - 1) == '/');
0102: }
0103:
0104: /**
0105: * Returns a list of resources that could not be loaded in the last invoked findAvailable* or
0106: * mapAvailable* methods.
0107: * <p/>
0108: * The list will only contain entries of resources that match the requirements
0109: * of the last invoked findAvailable* or mapAvailable* methods, but were unable to be
0110: * loaded and included in their results.
0111: * <p/>
0112: * The list returned is unmodifiable and the results of this method will change
0113: * after each invocation of a findAvailable* or mapAvailable* methods.
0114: * <p/>
0115: * This method is not thread safe.
0116: */
0117: public List<String> getResourcesNotLoaded() {
0118: return Collections.unmodifiableList(resourcesNotLoaded);
0119: }
0120:
0121: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0122: //
0123: // Find
0124: //
0125: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0126:
0127: public URL find(String uri) throws IOException {
0128: String fullUri = path + uri;
0129:
0130: URL resource = getResource(fullUri);
0131: if (resource == null) {
0132: throw new IOException("Could not find resource '" + fullUri
0133: + "'");
0134: }
0135:
0136: return resource;
0137: }
0138:
0139: public List<URL> findAll(String uri) throws IOException {
0140: String fullUri = path + uri;
0141:
0142: Enumeration<URL> resources = getResources(fullUri);
0143: List<URL> list = new ArrayList();
0144: while (resources.hasMoreElements()) {
0145: URL url = resources.nextElement();
0146: list.add(url);
0147: }
0148: return list;
0149: }
0150:
0151: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0152: //
0153: // Find String
0154: //
0155: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0156:
0157: /**
0158: * Reads the contents of the URL as a {@link String}'s and returns it.
0159: *
0160: * @param uri
0161: * @return a stringified content of a resource
0162: * @throws IOException if a resource pointed out by the uri param could not be find
0163: * @see ClassLoader#getResource(String)
0164: */
0165: public String findString(String uri) throws IOException {
0166: String fullUri = path + uri;
0167:
0168: URL resource = getResource(fullUri);
0169: if (resource == null) {
0170: throw new IOException("Could not find a resource in : "
0171: + fullUri);
0172: }
0173:
0174: return readContents(resource);
0175: }
0176:
0177: /**
0178: * Reads the contents of the found URLs as a list of {@link String}'s and returns them.
0179: *
0180: * @param uri
0181: * @return a list of the content of each resource URL found
0182: * @throws IOException if any of the found URLs are unable to be read.
0183: */
0184: public List<String> findAllStrings(String uri) throws IOException {
0185: String fulluri = path + uri;
0186:
0187: List<String> strings = new ArrayList<String>();
0188:
0189: Enumeration<URL> resources = getResources(fulluri);
0190: while (resources.hasMoreElements()) {
0191: URL url = resources.nextElement();
0192: String string = readContents(url);
0193: strings.add(string);
0194: }
0195: return strings;
0196: }
0197:
0198: /**
0199: * Reads the contents of the found URLs as a Strings and returns them.
0200: * Individual URLs that cannot be read are skipped and added to the
0201: * list of 'resourcesNotLoaded'
0202: *
0203: * @param uri
0204: * @return a list of the content of each resource URL found
0205: * @throws IOException if classLoader.getResources throws an exception
0206: */
0207: public List<String> findAvailableStrings(String uri)
0208: throws IOException {
0209: resourcesNotLoaded.clear();
0210: String fulluri = path + uri;
0211:
0212: List<String> strings = new ArrayList<String>();
0213:
0214: Enumeration<URL> resources = getResources(fulluri);
0215: while (resources.hasMoreElements()) {
0216: URL url = resources.nextElement();
0217: try {
0218: String string = readContents(url);
0219: strings.add(string);
0220: } catch (IOException notAvailable) {
0221: resourcesNotLoaded.add(url.toExternalForm());
0222: }
0223: }
0224: return strings;
0225: }
0226:
0227: /**
0228: * Reads the contents of all non-directory URLs immediately under the specified
0229: * location and returns them in a map keyed by the file name.
0230: * <p/>
0231: * Any URLs that cannot be read will cause an exception to be thrown.
0232: * <p/>
0233: * Example classpath:
0234: * <p/>
0235: * META-INF/serializables/one
0236: * META-INF/serializables/two
0237: * META-INF/serializables/three
0238: * META-INF/serializables/four/foo.txt
0239: * <p/>
0240: * ResourceFinder finder = new ResourceFinder("META-INF/");
0241: * Map map = finder.mapAvailableStrings("serializables");
0242: * map.contains("one"); // true
0243: * map.contains("two"); // true
0244: * map.contains("three"); // true
0245: * map.contains("four"); // false
0246: *
0247: * @param uri
0248: * @return a list of the content of each resource URL found
0249: * @throws IOException if any of the urls cannot be read
0250: */
0251: public Map<String, String> mapAllStrings(String uri)
0252: throws IOException {
0253: Map<String, String> strings = new HashMap<String, String>();
0254: Map<String, URL> resourcesMap = getResourcesMap(uri);
0255: for (Iterator iterator = resourcesMap.entrySet().iterator(); iterator
0256: .hasNext();) {
0257: Map.Entry entry = (Map.Entry) iterator.next();
0258: String name = (String) entry.getKey();
0259: URL url = (URL) entry.getValue();
0260: String value = readContents(url);
0261: strings.put(name, value);
0262: }
0263: return strings;
0264: }
0265:
0266: /**
0267: * Reads the contents of all non-directory URLs immediately under the specified
0268: * location and returns them in a map keyed by the file name.
0269: * <p/>
0270: * Individual URLs that cannot be read are skipped and added to the
0271: * list of 'resourcesNotLoaded'
0272: * <p/>
0273: * Example classpath:
0274: * <p/>
0275: * META-INF/serializables/one
0276: * META-INF/serializables/two # not readable
0277: * META-INF/serializables/three
0278: * META-INF/serializables/four/foo.txt
0279: * <p/>
0280: * ResourceFinder finder = new ResourceFinder("META-INF/");
0281: * Map map = finder.mapAvailableStrings("serializables");
0282: * map.contains("one"); // true
0283: * map.contains("two"); // false
0284: * map.contains("three"); // true
0285: * map.contains("four"); // false
0286: *
0287: * @param uri
0288: * @return a list of the content of each resource URL found
0289: * @throws IOException if classLoader.getResources throws an exception
0290: */
0291: public Map<String, String> mapAvailableStrings(String uri)
0292: throws IOException {
0293: resourcesNotLoaded.clear();
0294: Map<String, String> strings = new HashMap<String, String>();
0295: Map<String, URL> resourcesMap = getResourcesMap(uri);
0296: for (Iterator iterator = resourcesMap.entrySet().iterator(); iterator
0297: .hasNext();) {
0298: Map.Entry entry = (Map.Entry) iterator.next();
0299: String name = (String) entry.getKey();
0300: URL url = (URL) entry.getValue();
0301: try {
0302: String value = readContents(url);
0303: strings.put(name, value);
0304: } catch (IOException notAvailable) {
0305: resourcesNotLoaded.add(url.toExternalForm());
0306: }
0307: }
0308: return strings;
0309: }
0310:
0311: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0312: //
0313: // Find Class
0314: //
0315: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0316:
0317: /**
0318: * Executes {@link #findString(String)} assuming the contents URL found is the name of
0319: * a class that should be loaded and returned.
0320: *
0321: * @param uri
0322: * @return
0323: * @throws IOException
0324: * @throws ClassNotFoundException
0325: */
0326: public Class findClass(String uri) throws IOException,
0327: ClassNotFoundException {
0328: String className = findString(uri);
0329: return (Class) classLoader.loadClass(className);
0330: }
0331:
0332: /**
0333: * Executes findAllStrings assuming the strings are
0334: * the names of a classes that should be loaded and returned.
0335: * <p/>
0336: * Any URL or class that cannot be loaded will cause an exception to be thrown.
0337: *
0338: * @param uri
0339: * @return
0340: * @throws IOException
0341: * @throws ClassNotFoundException
0342: */
0343: public List<Class> findAllClasses(String uri) throws IOException,
0344: ClassNotFoundException {
0345: List<Class> classes = new ArrayList<Class>();
0346: List<String> strings = findAllStrings(uri);
0347: for (String className : strings) {
0348: Class clazz = classLoader.loadClass(className);
0349: classes.add(clazz);
0350: }
0351: return classes;
0352: }
0353:
0354: /**
0355: * Executes findAvailableStrings assuming the strings are
0356: * the names of a classes that should be loaded and returned.
0357: * <p/>
0358: * Any class that cannot be loaded will be skipped and placed in the
0359: * 'resourcesNotLoaded' collection.
0360: *
0361: * @param uri
0362: * @return
0363: * @throws IOException if classLoader.getResources throws an exception
0364: */
0365: public List<Class> findAvailableClasses(String uri)
0366: throws IOException {
0367: resourcesNotLoaded.clear();
0368: List<Class> classes = new ArrayList<Class>();
0369: List<String> strings = findAvailableStrings(uri);
0370: for (String className : strings) {
0371: try {
0372: Class clazz = classLoader.loadClass(className);
0373: classes.add(clazz);
0374: } catch (Exception notAvailable) {
0375: resourcesNotLoaded.add(className);
0376: }
0377: }
0378: return classes;
0379: }
0380:
0381: /**
0382: * Executes mapAllStrings assuming the value of each entry in the
0383: * map is the name of a class that should be loaded.
0384: * <p/>
0385: * Any class that cannot be loaded will be cause an exception to be thrown.
0386: * <p/>
0387: * Example classpath:
0388: * <p/>
0389: * META-INF/xmlparsers/xerces
0390: * META-INF/xmlparsers/crimson
0391: * <p/>
0392: * ResourceFinder finder = new ResourceFinder("META-INF/");
0393: * Map map = finder.mapAvailableStrings("xmlparsers");
0394: * map.contains("xerces"); // true
0395: * map.contains("crimson"); // true
0396: * Class xercesClass = map.get("xerces");
0397: * Class crimsonClass = map.get("crimson");
0398: *
0399: * @param uri
0400: * @return
0401: * @throws IOException
0402: * @throws ClassNotFoundException
0403: */
0404: public Map<String, Class> mapAllClasses(String uri)
0405: throws IOException, ClassNotFoundException {
0406: Map<String, Class> classes = new HashMap<String, Class>();
0407: Map<String, String> map = mapAllStrings(uri);
0408: for (Iterator iterator = map.entrySet().iterator(); iterator
0409: .hasNext();) {
0410: Map.Entry entry = (Map.Entry) iterator.next();
0411: String string = (String) entry.getKey();
0412: String className = (String) entry.getValue();
0413: Class clazz = classLoader.loadClass(className);
0414: classes.put(string, clazz);
0415: }
0416: return classes;
0417: }
0418:
0419: /**
0420: * Executes mapAvailableStrings assuming the value of each entry in the
0421: * map is the name of a class that should be loaded.
0422: * <p/>
0423: * Any class that cannot be loaded will be skipped and placed in the
0424: * 'resourcesNotLoaded' collection.
0425: * <p/>
0426: * Example classpath:
0427: * <p/>
0428: * META-INF/xmlparsers/xerces
0429: * META-INF/xmlparsers/crimson
0430: * <p/>
0431: * ResourceFinder finder = new ResourceFinder("META-INF/");
0432: * Map map = finder.mapAvailableStrings("xmlparsers");
0433: * map.contains("xerces"); // true
0434: * map.contains("crimson"); // true
0435: * Class xercesClass = map.get("xerces");
0436: * Class crimsonClass = map.get("crimson");
0437: *
0438: * @param uri
0439: * @return
0440: * @throws IOException if classLoader.getResources throws an exception
0441: */
0442: public Map<String, Class> mapAvailableClasses(String uri)
0443: throws IOException {
0444: resourcesNotLoaded.clear();
0445: Map<String, Class> classes = new HashMap<String, Class>();
0446: Map<String, String> map = mapAvailableStrings(uri);
0447: for (Iterator iterator = map.entrySet().iterator(); iterator
0448: .hasNext();) {
0449: Map.Entry entry = (Map.Entry) iterator.next();
0450: String string = (String) entry.getKey();
0451: String className = (String) entry.getValue();
0452: try {
0453: Class clazz = classLoader.loadClass(className);
0454: classes.put(string, clazz);
0455: } catch (Exception notAvailable) {
0456: resourcesNotLoaded.add(className);
0457: }
0458: }
0459: return classes;
0460: }
0461:
0462: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0463: //
0464: // Find Implementation
0465: //
0466: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0467:
0468: /**
0469: * Assumes the class specified points to a file in the classpath that contains
0470: * the name of a class that implements or is a subclass of the specfied class.
0471: * <p/>
0472: * Any class that cannot be loaded will be cause an exception to be thrown.
0473: * <p/>
0474: * Example classpath:
0475: * <p/>
0476: * META-INF/java.io.InputStream # contains the classname org.acme.AcmeInputStream
0477: * META-INF/java.io.OutputStream
0478: * <p/>
0479: * ResourceFinder finder = new ResourceFinder("META-INF/");
0480: * Class clazz = finder.findImplementation(java.io.InputStream.class);
0481: * clazz.getName(); // returns "org.acme.AcmeInputStream"
0482: *
0483: * @param interfase a superclass or interface
0484: * @return
0485: * @throws IOException if the URL cannot be read
0486: * @throws ClassNotFoundException if the class found is not loadable
0487: * @throws ClassCastException if the class found is not assignable to the specified superclass or interface
0488: */
0489: public Class findImplementation(Class interfase)
0490: throws IOException, ClassNotFoundException {
0491: String className = findString(interfase.getName());
0492: Class impl = classLoader.loadClass(className);
0493: if (!interfase.isAssignableFrom(impl)) {
0494: throw new ClassCastException("Class not of type: "
0495: + interfase.getName());
0496: }
0497: return impl;
0498: }
0499:
0500: /**
0501: * Assumes the class specified points to a file in the classpath that contains
0502: * the name of a class that implements or is a subclass of the specfied class.
0503: * <p/>
0504: * Any class that cannot be loaded or assigned to the specified interface will be cause
0505: * an exception to be thrown.
0506: * <p/>
0507: * Example classpath:
0508: * <p/>
0509: * META-INF/java.io.InputStream # contains the classname org.acme.AcmeInputStream
0510: * META-INF/java.io.InputStream # contains the classname org.widget.NeatoInputStream
0511: * META-INF/java.io.InputStream # contains the classname com.foo.BarInputStream
0512: * <p/>
0513: * ResourceFinder finder = new ResourceFinder("META-INF/");
0514: * List classes = finder.findAllImplementations(java.io.InputStream.class);
0515: * classes.contains("org.acme.AcmeInputStream"); // true
0516: * classes.contains("org.widget.NeatoInputStream"); // true
0517: * classes.contains("com.foo.BarInputStream"); // true
0518: *
0519: * @param interfase a superclass or interface
0520: * @return
0521: * @throws IOException if the URL cannot be read
0522: * @throws ClassNotFoundException if the class found is not loadable
0523: * @throws ClassCastException if the class found is not assignable to the specified superclass or interface
0524: */
0525: public List<Class> findAllImplementations(Class interfase)
0526: throws IOException, ClassNotFoundException {
0527: List<Class> implementations = new ArrayList<Class>();
0528: List<String> strings = findAllStrings(interfase.getName());
0529: for (String className : strings) {
0530: Class impl = classLoader.loadClass(className);
0531: if (!interfase.isAssignableFrom(impl)) {
0532: throw new ClassCastException("Class not of type: "
0533: + interfase.getName());
0534: }
0535: implementations.add(impl);
0536: }
0537: return implementations;
0538: }
0539:
0540: /**
0541: * Assumes the class specified points to a file in the classpath that contains
0542: * the name of a class that implements or is a subclass of the specfied class.
0543: * <p/>
0544: * Any class that cannot be loaded or are not assignable to the specified class will be
0545: * skipped and placed in the 'resourcesNotLoaded' collection.
0546: * <p/>
0547: * Example classpath:
0548: * <p/>
0549: * META-INF/java.io.InputStream # contains the classname org.acme.AcmeInputStream
0550: * META-INF/java.io.InputStream # contains the classname org.widget.NeatoInputStream
0551: * META-INF/java.io.InputStream # contains the classname com.foo.BarInputStream
0552: * <p/>
0553: * ResourceFinder finder = new ResourceFinder("META-INF/");
0554: * List classes = finder.findAllImplementations(java.io.InputStream.class);
0555: * classes.contains("org.acme.AcmeInputStream"); // true
0556: * classes.contains("org.widget.NeatoInputStream"); // true
0557: * classes.contains("com.foo.BarInputStream"); // true
0558: *
0559: * @param interfase a superclass or interface
0560: * @return
0561: * @throws IOException if classLoader.getResources throws an exception
0562: */
0563: public List<Class> findAvailableImplementations(Class interfase)
0564: throws IOException {
0565: resourcesNotLoaded.clear();
0566: List<Class> implementations = new ArrayList<Class>();
0567: List<String> strings = findAvailableStrings(interfase.getName());
0568: for (String className : strings) {
0569: try {
0570: Class impl = classLoader.loadClass(className);
0571: if (interfase.isAssignableFrom(impl)) {
0572: implementations.add(impl);
0573: } else {
0574: resourcesNotLoaded.add(className);
0575: }
0576: } catch (Exception notAvailable) {
0577: resourcesNotLoaded.add(className);
0578: }
0579: }
0580: return implementations;
0581: }
0582:
0583: /**
0584: * Assumes the class specified points to a directory in the classpath that holds files
0585: * containing the name of a class that implements or is a subclass of the specfied class.
0586: * <p/>
0587: * Any class that cannot be loaded or assigned to the specified interface will be cause
0588: * an exception to be thrown.
0589: * <p/>
0590: * Example classpath:
0591: * <p/>
0592: * META-INF/java.net.URLStreamHandler/jar
0593: * META-INF/java.net.URLStreamHandler/file
0594: * META-INF/java.net.URLStreamHandler/http
0595: * <p/>
0596: * ResourceFinder finder = new ResourceFinder("META-INF/");
0597: * Map map = finder.mapAllImplementations(java.net.URLStreamHandler.class);
0598: * Class jarUrlHandler = map.get("jar");
0599: * Class fileUrlHandler = map.get("file");
0600: * Class httpUrlHandler = map.get("http");
0601: *
0602: * @param interfase a superclass or interface
0603: * @return
0604: * @throws IOException if the URL cannot be read
0605: * @throws ClassNotFoundException if the class found is not loadable
0606: * @throws ClassCastException if the class found is not assignable to the specified superclass or interface
0607: */
0608: public Map<String, Class> mapAllImplementations(Class interfase)
0609: throws IOException, ClassNotFoundException {
0610: Map<String, Class> implementations = new HashMap<String, Class>();
0611: Map<String, String> map = mapAllStrings(interfase.getName());
0612: for (Iterator iterator = map.entrySet().iterator(); iterator
0613: .hasNext();) {
0614: Map.Entry entry = (Map.Entry) iterator.next();
0615: String string = (String) entry.getKey();
0616: String className = (String) entry.getValue();
0617: Class impl = classLoader.loadClass(className);
0618: if (!interfase.isAssignableFrom(impl)) {
0619: throw new ClassCastException("Class not of type: "
0620: + interfase.getName());
0621: }
0622: implementations.put(string, impl);
0623: }
0624: return implementations;
0625: }
0626:
0627: /**
0628: * Assumes the class specified points to a directory in the classpath that holds files
0629: * containing the name of a class that implements or is a subclass of the specfied class.
0630: * <p/>
0631: * Any class that cannot be loaded or are not assignable to the specified class will be
0632: * skipped and placed in the 'resourcesNotLoaded' collection.
0633: * <p/>
0634: * Example classpath:
0635: * <p/>
0636: * META-INF/java.net.URLStreamHandler/jar
0637: * META-INF/java.net.URLStreamHandler/file
0638: * META-INF/java.net.URLStreamHandler/http
0639: * <p/>
0640: * ResourceFinder finder = new ResourceFinder("META-INF/");
0641: * Map map = finder.mapAllImplementations(java.net.URLStreamHandler.class);
0642: * Class jarUrlHandler = map.get("jar");
0643: * Class fileUrlHandler = map.get("file");
0644: * Class httpUrlHandler = map.get("http");
0645: *
0646: * @param interfase a superclass or interface
0647: * @return
0648: * @throws IOException if classLoader.getResources throws an exception
0649: */
0650: public Map<String, Class> mapAvailableImplementations(
0651: Class interfase) throws IOException {
0652: resourcesNotLoaded.clear();
0653: Map<String, Class> implementations = new HashMap<String, Class>();
0654: Map<String, String> map = mapAvailableStrings(interfase
0655: .getName());
0656: for (Iterator iterator = map.entrySet().iterator(); iterator
0657: .hasNext();) {
0658: Map.Entry entry = (Map.Entry) iterator.next();
0659: String string = (String) entry.getKey();
0660: String className = (String) entry.getValue();
0661: try {
0662: Class impl = classLoader.loadClass(className);
0663: if (interfase.isAssignableFrom(impl)) {
0664: implementations.put(string, impl);
0665: } else {
0666: resourcesNotLoaded.add(className);
0667: }
0668: } catch (Exception notAvailable) {
0669: resourcesNotLoaded.add(className);
0670: }
0671: }
0672: return implementations;
0673: }
0674:
0675: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0676: //
0677: // Find Properties
0678: //
0679: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0680:
0681: /**
0682: * Finds the corresponding resource and reads it in as a properties file
0683: * <p/>
0684: * Example classpath:
0685: * <p/>
0686: * META-INF/widget.properties
0687: * <p/>
0688: * ResourceFinder finder = new ResourceFinder("META-INF/");
0689: * Properties widgetProps = finder.findProperties("widget.properties");
0690: *
0691: * @param uri
0692: * @return
0693: * @throws IOException if the URL cannot be read or is not in properties file format
0694: */
0695: public Properties findProperties(String uri) throws IOException {
0696: String fulluri = path + uri;
0697:
0698: URL resource = getResource(fulluri);
0699: if (resource == null) {
0700: throw new IOException("Could not find command in : "
0701: + fulluri);
0702: }
0703:
0704: return loadProperties(resource);
0705: }
0706:
0707: /**
0708: * Finds the corresponding resources and reads them in as a properties files
0709: * <p/>
0710: * Any URL that cannot be read in as a properties file will cause an exception to be thrown.
0711: * <p/>
0712: * Example classpath:
0713: * <p/>
0714: * META-INF/app.properties
0715: * META-INF/app.properties
0716: * META-INF/app.properties
0717: * <p/>
0718: * ResourceFinder finder = new ResourceFinder("META-INF/");
0719: * List<Properties> appProps = finder.findAllProperties("app.properties");
0720: *
0721: * @param uri
0722: * @return
0723: * @throws IOException if the URL cannot be read or is not in properties file format
0724: */
0725: public List<Properties> findAllProperties(String uri)
0726: throws IOException {
0727: String fulluri = path + uri;
0728:
0729: List<Properties> properties = new ArrayList<Properties>();
0730:
0731: Enumeration<URL> resources = getResources(fulluri);
0732: while (resources.hasMoreElements()) {
0733: URL url = resources.nextElement();
0734: Properties props = loadProperties(url);
0735: properties.add(props);
0736: }
0737: return properties;
0738: }
0739:
0740: /**
0741: * Finds the corresponding resources and reads them in as a properties files
0742: * <p/>
0743: * Any URL that cannot be read in as a properties file will be added to the
0744: * 'resourcesNotLoaded' collection.
0745: * <p/>
0746: * Example classpath:
0747: * <p/>
0748: * META-INF/app.properties
0749: * META-INF/app.properties
0750: * META-INF/app.properties
0751: * <p/>
0752: * ResourceFinder finder = new ResourceFinder("META-INF/");
0753: * List<Properties> appProps = finder.findAvailableProperties("app.properties");
0754: *
0755: * @param uri
0756: * @return
0757: * @throws IOException if classLoader.getResources throws an exception
0758: */
0759: public List<Properties> findAvailableProperties(String uri)
0760: throws IOException {
0761: resourcesNotLoaded.clear();
0762: String fulluri = path + uri;
0763:
0764: List<Properties> properties = new ArrayList<Properties>();
0765:
0766: Enumeration<URL> resources = getResources(fulluri);
0767: while (resources.hasMoreElements()) {
0768: URL url = resources.nextElement();
0769: try {
0770: Properties props = loadProperties(url);
0771: properties.add(props);
0772: } catch (Exception notAvailable) {
0773: resourcesNotLoaded.add(url.toExternalForm());
0774: }
0775: }
0776: return properties;
0777: }
0778:
0779: /**
0780: * Finds the corresponding resources and reads them in as a properties files
0781: * <p/>
0782: * Any URL that cannot be read in as a properties file will cause an exception to be thrown.
0783: * <p/>
0784: * Example classpath:
0785: * <p/>
0786: * META-INF/jdbcDrivers/oracle.properties
0787: * META-INF/jdbcDrivers/mysql.props
0788: * META-INF/jdbcDrivers/derby
0789: * <p/>
0790: * ResourceFinder finder = new ResourceFinder("META-INF/");
0791: * List<Properties> driversList = finder.findAvailableProperties("jdbcDrivers");
0792: * Properties oracleProps = driversList.get("oracle.properties");
0793: * Properties mysqlProps = driversList.get("mysql.props");
0794: * Properties derbyProps = driversList.get("derby");
0795: *
0796: * @param uri
0797: * @return
0798: * @throws IOException if the URL cannot be read or is not in properties file format
0799: */
0800: public Map<String, Properties> mapAllProperties(String uri)
0801: throws IOException {
0802: Map<String, Properties> propertiesMap = new HashMap<String, Properties>();
0803: Map<String, URL> map = getResourcesMap(uri);
0804: for (Iterator iterator = map.entrySet().iterator(); iterator
0805: .hasNext();) {
0806: Map.Entry entry = (Map.Entry) iterator.next();
0807: String string = (String) entry.getKey();
0808: URL url = (URL) entry.getValue();
0809: Properties properties = loadProperties(url);
0810: propertiesMap.put(string, properties);
0811: }
0812: return propertiesMap;
0813: }
0814:
0815: /**
0816: * Finds the corresponding resources and reads them in as a properties files
0817: * <p/>
0818: * Any URL that cannot be read in as a properties file will be added to the
0819: * 'resourcesNotLoaded' collection.
0820: * <p/>
0821: * Example classpath:
0822: * <p/>
0823: * META-INF/jdbcDrivers/oracle.properties
0824: * META-INF/jdbcDrivers/mysql.props
0825: * META-INF/jdbcDrivers/derby
0826: * <p/>
0827: * ResourceFinder finder = new ResourceFinder("META-INF/");
0828: * List<Properties> driversList = finder.findAvailableProperties("jdbcDrivers");
0829: * Properties oracleProps = driversList.get("oracle.properties");
0830: * Properties mysqlProps = driversList.get("mysql.props");
0831: * Properties derbyProps = driversList.get("derby");
0832: *
0833: * @param uri
0834: * @return
0835: * @throws IOException if classLoader.getResources throws an exception
0836: */
0837: public Map<String, Properties> mapAvailableProperties(String uri)
0838: throws IOException {
0839: resourcesNotLoaded.clear();
0840: Map<String, Properties> propertiesMap = new HashMap<String, Properties>();
0841: Map<String, URL> map = getResourcesMap(uri);
0842: for (Iterator iterator = map.entrySet().iterator(); iterator
0843: .hasNext();) {
0844: Map.Entry entry = (Map.Entry) iterator.next();
0845: String string = (String) entry.getKey();
0846: URL url = (URL) entry.getValue();
0847: try {
0848: Properties properties = loadProperties(url);
0849: propertiesMap.put(string, properties);
0850: } catch (Exception notAvailable) {
0851: resourcesNotLoaded.add(url.toExternalForm());
0852: }
0853: }
0854: return propertiesMap;
0855: }
0856:
0857: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0858: //
0859: // Map Resources
0860: //
0861: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0862:
0863: public Map<String, URL> getResourcesMap(String uri)
0864: throws IOException {
0865: String basePath = path + uri;
0866:
0867: Map<String, URL> resources = new HashMap<String, URL>();
0868: if (!basePath.endsWith("/")) {
0869: basePath += "/";
0870: }
0871: Enumeration<URL> urls = getResources(basePath);
0872:
0873: while (urls.hasMoreElements()) {
0874: URL location = urls.nextElement();
0875:
0876: try {
0877: if (location.getProtocol().equals("jar")) {
0878:
0879: readJarEntries(location, basePath, resources);
0880:
0881: } else if (location.getProtocol().equals("file")) {
0882:
0883: readDirectoryEntries(location, resources);
0884:
0885: }
0886: } catch (Exception e) {
0887: }
0888: }
0889:
0890: return resources;
0891: }
0892:
0893: private static void readDirectoryEntries(URL location,
0894: Map<String, URL> resources) throws MalformedURLException {
0895: File dir = new File(URLDecoder.decode(location.getPath()));
0896: if (dir.isDirectory()) {
0897: File[] files = dir.listFiles();
0898: for (File file : files) {
0899: if (!file.isDirectory()) {
0900: String name = file.getName();
0901: URL url = file.toURL();
0902: resources.put(name, url);
0903: }
0904: }
0905: }
0906: }
0907:
0908: private static void readJarEntries(URL location, String basePath,
0909: Map<String, URL> resources) throws IOException {
0910: JarURLConnection conn = (JarURLConnection) location
0911: .openConnection();
0912: JarFile jarfile = null;
0913: jarfile = conn.getJarFile();
0914:
0915: Enumeration<JarEntry> entries = jarfile.entries();
0916: while (entries != null && entries.hasMoreElements()) {
0917: JarEntry entry = entries.nextElement();
0918: String name = entry.getName();
0919:
0920: if (entry.isDirectory() || !name.startsWith(basePath)
0921: || name.length() == basePath.length()) {
0922: continue;
0923: }
0924:
0925: name = name.substring(basePath.length());
0926:
0927: if (name.contains("/")) {
0928: continue;
0929: }
0930:
0931: URL resource = new URL(location, name);
0932: resources.put(name, resource);
0933: }
0934: }
0935:
0936: private Properties loadProperties(URL resource) throws IOException {
0937: InputStream in = resource.openStream();
0938:
0939: BufferedInputStream reader = null;
0940: try {
0941: reader = new BufferedInputStream(in);
0942: Properties properties = new Properties();
0943: properties.load(reader);
0944:
0945: return properties;
0946: } finally {
0947: try {
0948: in.close();
0949: reader.close();
0950: } catch (Exception e) {
0951: }
0952: }
0953: }
0954:
0955: private String readContents(URL resource) throws IOException {
0956: InputStream in = resource.openStream();
0957: BufferedInputStream reader = null;
0958: StringBuffer sb = new StringBuffer();
0959:
0960: try {
0961: reader = new BufferedInputStream(in);
0962:
0963: int b = reader.read();
0964: while (b != -1) {
0965: sb.append((char) b);
0966: b = reader.read();
0967: }
0968:
0969: return sb.toString().trim();
0970: } finally {
0971: try {
0972: in.close();
0973: reader.close();
0974: } catch (Exception e) {
0975: }
0976: }
0977: }
0978:
0979: private URL getResource(String fullUri) {
0980: if (urls == null) {
0981: return classLoader.getResource(fullUri);
0982: }
0983: return findResource(fullUri, urls);
0984: }
0985:
0986: private Enumeration<URL> getResources(String fulluri)
0987: throws IOException {
0988: if (urls == null) {
0989: return classLoader.getResources(fulluri);
0990: }
0991: Vector<URL> resources = new Vector();
0992: for (URL url : urls) {
0993: URL resource = findResource(fulluri, url);
0994: if (resource != null) {
0995: resources.add(resource);
0996: }
0997: }
0998: return resources.elements();
0999: }
1000:
1001: private URL findResource(String resourceName, URL... search) {
1002: for (int i = 0; i < search.length; i++) {
1003: URL currentUrl = search[i];
1004: if (currentUrl == null) {
1005: continue;
1006: }
1007: JarFile jarFile = null;
1008: try {
1009: String protocol = currentUrl.getProtocol();
1010: if (protocol.equals("jar")) {
1011: /*
1012: * If the connection for currentUrl or resURL is
1013: * used, getJarFile() will throw an exception if the
1014: * entry doesn't exist.
1015: */
1016: URL jarURL = ((JarURLConnection) currentUrl
1017: .openConnection()).getJarFileURL();
1018: try {
1019: JarURLConnection juc = (JarURLConnection) new URL(
1020: "jar", "", jarURL.toExternalForm()
1021: + "!/").openConnection();
1022: jarFile = juc.getJarFile();
1023: } catch (IOException e) {
1024: // Don't look for this jar file again
1025: search[i] = null;
1026: throw e;
1027: }
1028:
1029: String entryName;
1030: if (currentUrl.getFile().endsWith("!/")) {
1031: entryName = resourceName;
1032: } else {
1033: String file = currentUrl.getFile();
1034: int sepIdx = file.lastIndexOf("!/");
1035: if (sepIdx == -1) {
1036: // Invalid URL, don't look here again
1037: search[i] = null;
1038: continue;
1039: }
1040: sepIdx += 2;
1041: StringBuffer sb = new StringBuffer(file
1042: .length()
1043: - sepIdx + resourceName.length());
1044: sb.append(file.substring(sepIdx));
1045: sb.append(resourceName);
1046: entryName = sb.toString();
1047: }
1048: if (entryName.equals("META-INF/")
1049: && jarFile.getEntry("META-INF/MANIFEST.MF") != null) {
1050: return targetURL(currentUrl,
1051: "META-INF/MANIFEST.MF");
1052: }
1053: if (jarFile.getEntry(entryName) != null) {
1054: return targetURL(currentUrl, resourceName);
1055: }
1056: } else if (protocol.equals("file")) {
1057: String baseFile = currentUrl.getFile();
1058: String host = currentUrl.getHost();
1059: int hostLength = 0;
1060: if (host != null) {
1061: hostLength = host.length();
1062: }
1063: StringBuffer buf = new StringBuffer(2 + hostLength
1064: + baseFile.length() + resourceName.length());
1065:
1066: if (hostLength > 0) {
1067: buf.append("//").append(host);
1068: }
1069: // baseFile always ends with '/'
1070: buf.append(baseFile);
1071: String fixedResName = resourceName;
1072: // Do not create a UNC path, i.e. \\host
1073: while (fixedResName.startsWith("/")
1074: || fixedResName.startsWith("\\")) {
1075: fixedResName = fixedResName.substring(1);
1076: }
1077: buf.append(fixedResName);
1078: String filename = buf.toString();
1079: File file = new File(filename);
1080: File file2 = new File(URLDecoder.decode(filename));
1081: if (file.exists() || file2.exists()) {
1082: return targetURL(currentUrl, fixedResName);
1083: }
1084: } else {
1085: URL resourceURL = targetURL(currentUrl,
1086: resourceName);
1087: URLConnection urlConnection = resourceURL
1088: .openConnection();
1089:
1090: try {
1091: urlConnection.getInputStream().close();
1092: } catch (SecurityException e) {
1093: return null;
1094: }
1095: // HTTP can return a stream on a non-existent file
1096: // So check for the return code;
1097: if (!resourceURL.getProtocol().equals("http")) {
1098: return resourceURL;
1099: }
1100:
1101: int code = ((HttpURLConnection) urlConnection)
1102: .getResponseCode();
1103: if (code >= 200 && code < 300) {
1104: return resourceURL;
1105: }
1106: }
1107: } catch (MalformedURLException e) {
1108: // Keep iterating through the URL list
1109: } catch (IOException e) {
1110: } catch (SecurityException e) {
1111: }
1112: }
1113: return null;
1114: }
1115:
1116: private URL targetURL(URL base, String name)
1117: throws MalformedURLException {
1118: StringBuffer sb = new StringBuffer(base.getFile().length()
1119: + name.length());
1120: sb.append(base.getFile());
1121: sb.append(name);
1122: String file = sb.toString();
1123: return new URL(base.getProtocol(), base.getHost(), base
1124: .getPort(), file, null);
1125: }
1126: }
|