1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.properties.utils;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.net.URL;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Enumeration;
25 import java.util.List;
26 import java.util.NoSuchElementException;
27
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31
32
33
34 public final class ProjectClassLoader extends AbstractProjectClassLoader
35 {
36
37
38
39
40
41
42
43
44
45 private final List<File> rootDirectories;
46
47
48
49
50
51
52
53
54
55
56
57 private ProjectClassLoader(final ClassLoader parent,
58 final List<File> rootDirectories)
59 {
60 super(parent);
61 this.rootDirectories = Collections.unmodifiableList(rootDirectories);
62 }
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 private static List<File> initDirectories(final Logger log,
79 final Collection<String> directoryNames)
80 {
81 final List<File> directories = new ArrayList<File>(directoryNames.size());
82 for (final String directoryName : directoryNames)
83 {
84 final File directory = new File(directoryName);
85 if (directory.canRead()
86 && (directory.isDirectory() || directory.isFile()
87 && isArchive(directoryName)))
88 {
89 directories.add(directory);
90 }
91 else
92 {
93 if (log.isDebugEnabled())
94 {
95 final String message =
96 "Cannot access '" + directoryName
97 + "' as directory or Java archive."
98 + " Ignoring as classpath root.";
99 log.debug(message);
100 }
101 }
102 }
103 return directories;
104 }
105
106
107
108
109
110
111
112
113
114
115 private static boolean isArchive(final String root)
116 throws NullPointerException
117 {
118 return root.endsWith(".jar") || root.endsWith(".zip");
119 }
120
121
122
123
124
125
126
127
128
129
130 public static ProjectClassLoader create(final List<File> rootDirectories)
131 {
132 return create(Thread.currentThread().getContextClassLoader(),
133 rootDirectories);
134 }
135
136
137
138
139
140
141
142
143
144 public static ProjectClassLoader createFromNames(
145 final Collection<String> rootDirectoryNames)
146 {
147 return create(initDirectories(
148 LoggerFactory.getLogger(ProjectClassLoader.class), rootDirectoryNames));
149 }
150
151
152
153
154
155
156
157
158
159 public static ProjectClassLoader createFromNames(final ClassLoader parent,
160 final Collection<String> rootDirectoryNames)
161 {
162 return new ProjectClassLoader(parent, (List<File>) initDirectories(
163 LoggerFactory.getLogger(ProjectClassLoader.class), rootDirectoryNames));
164 }
165
166
167
168
169
170
171
172
173 public static ProjectClassLoader create(final ClassLoader parent,
174 final List<File> rootDirectories)
175 {
176 return new ProjectClassLoader(parent, rootDirectories);
177 }
178
179
180
181
182
183 @Override
184 protected URL findResource(final String name)
185 {
186 for (File directoryOrArchive : rootDirectories)
187 {
188 try
189 {
190 if (directoryOrArchive.isDirectory())
191 {
192 final File resourceFile = new File(directoryOrArchive, name);
193 if (resourceFile.canRead())
194 {
195 return resourceFile.toURI().toURL();
196 }
197 }
198 else
199 {
200 String resourceName = name;
201 final int index = name.lastIndexOf('.');
202 if (index != -1)
203 {
204 resourceName = name.substring(0, index);
205 }
206 resourceName = resourceName.replace('/', '.');
207 return loadResourceFromLibrary(resourceName, name, directoryOrArchive);
208 }
209 }
210 catch (final IOException e)
211 {
212
213 }
214 }
215 return super.findResource(name);
216 }
217
218 @Override
219 protected Enumeration<URL> findResources(final String name)
220 {
221 return new Enumeration<URL>()
222 {
223 private URL element = findResource(name);
224
225 public boolean hasMoreElements()
226 {
227 return this.element != null;
228 }
229
230 public URL nextElement()
231 {
232 if (this.element != null)
233 {
234 final URL element = this.element;
235 this.element = null;
236 return element;
237 }
238 throw new NoSuchElementException();
239 }
240 };
241 }
242
243
244
245
246 @Override
247 protected Class<?> findClass(final String name) throws ClassNotFoundException
248 {
249 for (File directoryOrArchive : rootDirectories)
250 {
251 try
252 {
253 final String fileName = name.replace('.', '/') + ".class";
254 if (directoryOrArchive.isDirectory())
255 {
256 final File classFile = new File(directoryOrArchive, fileName);
257 if (classFile.canRead())
258 {
259 return loadClassFile(name, classFile);
260 }
261 }
262 else
263 {
264 return loadClassFromLibrary(name, fileName, directoryOrArchive);
265 }
266 }
267 catch (final ClassNotFoundException e)
268 {
269
270 }
271 }
272 return super.findClass(name);
273 }
274
275
276
277 }