001: package liquibase;
002:
003: import java.io.IOException;
004: import java.io.InputStream;
005: import java.net.URL;
006: import java.util.*;
007:
008: /**
009: * A FileOpener that will search in a List of other FileOpeners until it finds
010: * one that has a resource of the appropriate name and path.
011: *
012: * @author <a href="mailto:csuml@yahoo.co.uk>Paul Keeble</a>
013: */
014: public class CompositeFileOpener implements FileOpener {
015: List<FileOpener> openers;
016:
017: /**
018: * Creates a Composite Opener with the list specified. The List will
019: * be searched in order from beginning to end.
020: *
021: * @param openers The list of Openers to use
022: */
023: public CompositeFileOpener(List<FileOpener> openers) {
024: this .openers = openers;
025: }
026:
027: /**
028: * Creates a CompositeFileOpener with 2 entries.
029: *
030: * @param openers The list of Openers to use
031: */
032: public CompositeFileOpener(FileOpener... openers) {
033: this .openers = Arrays.asList(openers);
034: }
035:
036: /**
037: * Searches through all of the FileOpeners in order for the file.
038: * <p/>
039: * If none of the FileOpeners was able to produce a stream to the file
040: * then null is returned.
041: */
042: public InputStream getResourceAsStream(String file)
043: throws IOException {
044: for (FileOpener o : openers) {
045: InputStream is = o.getResourceAsStream(file);
046: if (is != null)
047: return is;
048: }
049: return null;
050: }
051:
052: /**
053: * Searches all of the FileOpeners for a directory named packageName. If no
054: * results are found within any of the directories then an empty
055: * Enumeration is returned.
056: */
057: public Enumeration<URL> getResources(String packageName)
058: throws IOException {
059: for (FileOpener o : openers) {
060: Enumeration<URL> e = o.getResources(packageName);
061: if (e.hasMoreElements())
062: return e;
063: }
064: return new Vector<URL>().elements();
065: }
066:
067: public ClassLoader toClassLoader() {
068: List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
069: for (FileOpener fo : openers) {
070: classLoaders.add(fo.toClassLoader());
071: }
072:
073: return new CompositeClassLoader(classLoaders
074: .toArray(new ClassLoader[classLoaders.size()]));
075: }
076:
077: //based on code from http://fisheye.codehaus.org/browse/xstream/trunk/xstream/src/java/com/thoughtworks/xstream/core/util/CompositeClassLoader.java?r=root
078: private static class CompositeClassLoader extends ClassLoader {
079:
080: private final List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
081:
082: public CompositeClassLoader(ClassLoader... classLoaders) {
083: this .classLoaders.addAll(Arrays.asList(classLoaders));
084: }
085:
086: public Class loadClass(String name)
087: throws ClassNotFoundException {
088: for (Object classLoader1 : classLoaders) {
089: ClassLoader classLoader = (ClassLoader) classLoader1;
090: try {
091: return classLoader.loadClass(name);
092: } catch (ClassNotFoundException notFound) {
093: // ok.. try another one
094: }
095: }
096:
097: // One last try - the context class loader associated with the current thread. Often used in j2ee servers.
098: // Note: The contextClassLoader cannot be added to the classLoaders list up front as the thread that constructs
099: // liquibase is potentially different to thread that uses it.
100: ClassLoader contextClassLoader = Thread.currentThread()
101: .getContextClassLoader();
102: if (contextClassLoader != null) {
103: return contextClassLoader.loadClass(name);
104: } else {
105: throw new ClassNotFoundException(name);
106: }
107:
108: }
109:
110: }
111: }
|