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