View Javadoc

1   /*
2    * Created on May 27, 2005
3    *
4    * The top level ClassLoader for TheLittleContainer.
5    */
6   package net.sf.tlc.loader;
7   
8   import java.io.BufferedInputStream;
9   import java.io.ByteArrayOutputStream;
10  import java.io.File;
11  import java.io.FileFilter;
12  import java.io.FileInputStream;
13  import java.io.IOException;
14  import java.net.MalformedURLException;
15  import java.net.URL;
16  import java.net.URLClassLoader;
17  import java.util.ArrayList;
18  import java.util.Iterator;
19  import java.util.logging.Level;
20  import java.util.logging.Logger;
21  
22  import net.sf.tlc.util.ClassPathUtils;
23  
24  /***
25   * The top level ClassLoader for TheLittleContainer. TlcClassLoader is basically
26   * just a thin-wrapper around an internal URLClassLoader that does the actual
27   * work of loading classes.
28   * 
29   * @author aisrael
30   */
31  public class TlcClassLoader extends URLClassLoader {
32      
33      private final Logger logger = Logger.getLogger(TlcClassLoader.class.getName());
34  
35      private final File targetDir;
36      
37      private final ArrayList loadedClassFiles = new ArrayList();
38  
39      /***
40       * @param targetDir
41       *            File
42       */
43      public TlcClassLoader(final File targetDir) {
44          super(new URL[0]);
45          this.targetDir = targetDir;
46          if (null != targetDir) {
47              if (targetDir.isDirectory()) {
48                  findMoreTargets(targetDir);
49              } else {
50                  throw new IllegalArgumentException("targetDir must be a directory!");
51              }
52          } else {
53              throw new IllegalArgumentException("targetDir is null!");
54          }
55      }
56  
57      /***
58       * @param targetPath
59       *            String
60       */
61      public TlcClassLoader(final String targetPath) {
62          this(new File(targetPath));
63      }
64  
65      /***
66       * TODO change the description of JarFileFilter
67       * 
68       * @author aisrael
69       */
70      class JarFileFilter implements FileFilter {
71  
72          /***
73           * (non-Javadoc)
74           * 
75           * @see java.io.FileFilter#accept(java.io.File)
76           */
77          public boolean accept(final File file) {
78              return file.isFile() && file.canRead() && file.getName().endsWith(".jar");
79          }
80  
81      }
82  
83      private JarFileFilter jarFileFilter = new JarFileFilter();
84  
85      /***
86       * @param dir
87       *            File
88       */
89      private void findMoreTargets(final File dir) {
90          final ArrayList urls = new ArrayList();
91          final File[] jars = dir.listFiles(jarFileFilter);
92          for (int i = 0; i < jars.length; ++i) {
93              try {
94                  addURL(new URL("file://" + jars[i].getAbsolutePath()));
95              } catch (MalformedURLException e) {
96                  logger.log(Level.SEVERE, "Unexpected MalformedURLException", e);
97              }
98          }
99          for (final Iterator i = urls.iterator(); i.hasNext();) {
100             System.out.println(i.next());
101         }
102     }
103 
104     /***
105      * (non-Javadoc)
106      * 
107      * @see java.lang.ClassLoader#loadClass(java.lang.String)
108      */
109     public final Class loadClass(final String className) throws ClassNotFoundException {
110         final FileFilter filter = new FileFilter() {
111             private final String s = targetDir.getAbsolutePath() + "/" + className + ".class";
112             /***
113              * (non-Javadoc)
114              * 
115              * @see java.io.FileFilter#accept(java.io.File)
116              */
117             public boolean accept(final File file) {               
118                 return file.getAbsolutePath().equals(s);
119             }
120         };
121         final File[] found = targetDir.listFiles(filter);
122         if (found.length == 1 && !loadedClassFiles.contains(found[0])) {
123             loadClassFromFile(found[0]);
124         }
125         return super.loadClass(className);
126     }
127 
128     /***
129      * @param file
130      *            File
131      */
132     private void loadClassFromFile(final File file) {
133         FileInputStream fis = null;
134         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
135         try {
136             fis = new FileInputStream(file);
137             final BufferedInputStream bis = new BufferedInputStream(fis);
138             int avail = bis.available();
139             while (avail > 0) {
140                 final byte[] bytes = new byte[avail];
141                 bis.read(bytes, 0, avail);
142                 baos.write(bytes);
143                 avail = bis.available();
144             }
145             loadedClassFiles.add(file);
146         } catch (IOException e) {
147             logger.log(Level.SEVERE, "IOException", e);
148         } finally {
149             if (null != fis) {
150                 try {
151                     fis.close();
152                 } catch (IOException e) {
153                     logger.log(Level.SEVERE, "IOException", e);
154                 }
155             }
156         }
157         defineClass(ClassPathUtils.toClassName(targetDir.getAbsolutePath(), file.getAbsolutePath()), baos
158                 .toByteArray(), 0, baos.size());
159     }
160 }