1
2
3
4
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 }