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