1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.webapp;
15
16 import java.io.File;
17 import java.io.FileOutputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.URL;
21 import java.net.URLClassLoader;
22 import java.security.CodeSource;
23 import java.security.PermissionCollection;
24 import java.util.HashSet;
25 import java.util.StringTokenizer;
26
27 import org.eclipse.jetty.server.handler.ContextHandler;
28 import org.eclipse.jetty.util.IO;
29 import org.eclipse.jetty.util.LazyList;
30 import org.eclipse.jetty.util.StringUtil;
31 import org.eclipse.jetty.util.log.Log;
32 import org.eclipse.jetty.util.resource.Resource;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class WebAppClassLoader extends URLClassLoader
55 {
56 private String _name;
57 private WebAppContext _context;
58 private ClassLoader _parent;
59 private HashSet<String> _extensions;
60
61
62
63
64 public WebAppClassLoader(WebAppContext context)
65 throws IOException
66 {
67 this(null,context);
68 }
69
70
71
72
73 public WebAppClassLoader(ClassLoader parent, WebAppContext context)
74 throws IOException
75 {
76 super(new URL[]{},parent!=null?parent
77 :(Thread.currentThread().getContextClassLoader()!=null?Thread.currentThread().getContextClassLoader()
78 :(WebAppClassLoader.class.getClassLoader()!=null?WebAppClassLoader.class.getClassLoader()
79 :ClassLoader.getSystemClassLoader())));
80 _parent=getParent();
81 _context=context;
82 if (_parent==null)
83 throw new IllegalArgumentException("no parent classloader!");
84
85 _extensions = new HashSet<String>();
86 _extensions.add(".jar");
87 _extensions.add(".zip");
88
89 String extensions = System.getProperty(WebAppClassLoader.class.getName() + ".extensions");
90 if(extensions!=null)
91 {
92 StringTokenizer tokenizer = new StringTokenizer(extensions, ",;");
93 while(tokenizer.hasMoreTokens())
94 _extensions.add(tokenizer.nextToken().trim());
95 }
96
97 if (context.getExtraClasspath()!=null)
98 addClassPath(context.getExtraClasspath());
99 }
100
101
102
103
104
105 public String getName()
106 {
107 return _name;
108 }
109
110
111
112
113
114 public void setName(String name)
115 {
116 _name=name;
117 }
118
119
120
121 public ContextHandler getContext()
122 {
123 return _context;
124 }
125
126
127
128
129
130
131
132 public void addClassPath(String classPath)
133 throws IOException
134 {
135 if (classPath == null)
136 return;
137
138 StringTokenizer tokenizer= new StringTokenizer(classPath, ",;");
139 while (tokenizer.hasMoreTokens())
140 {
141 Resource resource= _context.newResource(tokenizer.nextToken());
142 if (Log.isDebugEnabled())
143 Log.debug("Path resource=" + resource);
144
145
146 File file= resource.getFile();
147 if (file != null)
148 {
149 URL url= resource.getURL();
150 addURL(url);
151 }
152 else
153 {
154
155 if (!resource.isDirectory() && file == null)
156 {
157 InputStream in= resource.getInputStream();
158 File tmp_dir=_context.getTempDirectory();
159 if (tmp_dir==null)
160 {
161 tmp_dir = File.createTempFile("jetty.cl.lib",null);
162 tmp_dir.mkdir();
163 tmp_dir.deleteOnExit();
164 }
165 File lib= new File(tmp_dir, "lib");
166 if (!lib.exists())
167 {
168 lib.mkdir();
169 lib.deleteOnExit();
170 }
171 File jar= File.createTempFile("Jetty-", ".jar", lib);
172
173 jar.deleteOnExit();
174 if (Log.isDebugEnabled())
175 Log.debug("Extract " + resource + " to " + jar);
176 FileOutputStream out = null;
177 try
178 {
179 out= new FileOutputStream(jar);
180 IO.copy(in, out);
181 }
182 finally
183 {
184 IO.close(out);
185 }
186
187 URL url= jar.toURL();
188 addURL(url);
189 }
190 else
191 {
192 URL url= resource.getURL();
193 addURL(url);
194 }
195 }
196 }
197 }
198
199
200
201
202
203 private boolean isFileSupported(String file)
204 {
205 int dot = file.lastIndexOf('.');
206 return dot!=-1 && _extensions.contains(file.substring(dot));
207 }
208
209
210
211
212
213
214
215
216
217 public void addJars(Resource lib)
218 {
219 if (lib.exists() && lib.isDirectory())
220 {
221 String[] files=lib.list();
222 for (int f=0;files!=null && f<files.length;f++)
223 {
224 try {
225 Resource fn=lib.addPath(files[f]);
226 String fnlc=fn.getName().toLowerCase();
227 if (isFileSupported(fnlc))
228 {
229 String jar=fn.toString();
230 jar=StringUtil.replace(jar, ",", "%2C");
231 jar=StringUtil.replace(jar, ";", "%3B");
232 addClassPath(jar);
233 }
234 }
235 catch (Exception ex)
236 {
237 Log.warn(Log.EXCEPTION,ex);
238 }
239 }
240 }
241 }
242
243 public void destroy()
244 {
245 this._parent=null;
246 }
247
248
249
250 public PermissionCollection getPermissions(CodeSource cs)
251 {
252
253 PermissionCollection permissions=_context.getPermissions();
254 PermissionCollection pc= (permissions == null) ? super.getPermissions(cs) : permissions;
255 return pc;
256 }
257
258
259 public synchronized URL getResource(String name)
260 {
261 URL url= null;
262 boolean tried_parent= false;
263 if (_context.isParentLoaderPriority() || _context.isSystemClass(name))
264 {
265 tried_parent= true;
266
267 if (_parent!=null)
268 url= _parent.getResource(name);
269 }
270
271 if (url == null)
272 {
273 url= this.findResource(name);
274
275 if (url == null && name.startsWith("/"))
276 {
277 if (Log.isDebugEnabled())
278 Log.debug("HACK leading / off " + name);
279 url= this.findResource(name.substring(1));
280 }
281 }
282
283 if (url == null && !tried_parent && !_context.isServerClass(name) )
284 {
285 if (_parent!=null)
286 url= _parent.getResource(name);
287 }
288
289 if (url != null)
290 if (Log.isDebugEnabled())
291 Log.debug("getResource("+name+")=" + url);
292
293 return url;
294 }
295
296
297 @Override
298 public synchronized Class<?> loadClass(String name) throws ClassNotFoundException
299 {
300 return loadClass(name, false);
301 }
302
303
304 @Override
305 protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
306 {
307 Class<?> c= findLoadedClass(name);
308 ClassNotFoundException ex= null;
309 boolean tried_parent= false;
310
311 boolean system_class=_context.isSystemClass(name);
312 boolean server_class=_context.isServerClass(name);
313
314 if (system_class && server_class)
315 {
316 return null;
317 }
318
319 if (c == null && _parent!=null && (_context.isParentLoaderPriority() || system_class) )
320 {
321 tried_parent= true;
322 try
323 {
324 c= _parent.loadClass(name);
325 if (Log.isDebugEnabled())
326 Log.debug("loaded " + c);
327 }
328 catch (ClassNotFoundException e)
329 {
330 ex= e;
331 }
332 }
333
334 if (c == null)
335 {
336 try
337 {
338 c= this.findClass(name);
339 }
340 catch (ClassNotFoundException e)
341 {
342 ex= e;
343 }
344 }
345
346 if (c == null && _parent!=null && !tried_parent && !server_class )
347 c= _parent.loadClass(name);
348
349 if (c == null)
350 throw ex;
351
352 if (resolve)
353 resolveClass(c);
354
355 if (Log.isDebugEnabled())
356 Log.debug("loaded " + c+ " from "+c.getClassLoader());
357
358 return c;
359 }
360
361
362 public String toString()
363 {
364 if (Log.isDebugEnabled())
365 return "ContextLoader@" + _name + "(" + LazyList.array2List(getURLs()) + ") / " + _parent;
366 return "ContextLoader@" + _name;
367 }
368
369 }