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.IOException;
18 import java.net.URL;
19 import java.net.URLClassLoader;
20 import java.security.CodeSource;
21 import java.security.PermissionCollection;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Enumeration;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.StringTokenizer;
28
29 import org.eclipse.jetty.server.handler.ContextHandler;
30 import org.eclipse.jetty.util.LazyList;
31 import org.eclipse.jetty.util.StringUtil;
32 import org.eclipse.jetty.util.log.Log;
33 import org.eclipse.jetty.util.resource.Resource;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class WebAppClassLoader extends URLClassLoader
56 {
57 private String _name;
58 private WebAppContext _context;
59 private ClassLoader _parent;
60 private HashSet<String> _extensions;
61
62
63
64
65 public WebAppClassLoader(WebAppContext context)
66 throws IOException
67 {
68 this(null,context);
69 }
70
71
72
73
74 public WebAppClassLoader(ClassLoader parent, WebAppContext context)
75 throws IOException
76 {
77 super(new URL[]{},parent!=null?parent
78 :(Thread.currentThread().getContextClassLoader()!=null?Thread.currentThread().getContextClassLoader()
79 :(WebAppClassLoader.class.getClassLoader()!=null?WebAppClassLoader.class.getClassLoader()
80 :ClassLoader.getSystemClassLoader())));
81 _parent=getParent();
82 _context=context;
83 if (_parent==null)
84 throw new IllegalArgumentException("no parent classloader!");
85
86 _extensions = new HashSet<String>();
87 _extensions.add(".jar");
88 _extensions.add(".zip");
89
90 String extensions = System.getProperty(WebAppClassLoader.class.getName() + ".extensions");
91 if(extensions!=null)
92 {
93 StringTokenizer tokenizer = new StringTokenizer(extensions, ",;");
94 while(tokenizer.hasMoreTokens())
95 _extensions.add(tokenizer.nextToken().trim());
96 }
97
98 if (context.getExtraClasspath()!=null)
99 addClassPath(context.getExtraClasspath());
100 }
101
102
103
104
105
106 public String getName()
107 {
108 return _name;
109 }
110
111
112
113
114
115 public void setName(String name)
116 {
117 _name=name;
118 }
119
120
121
122 public ContextHandler getContext()
123 {
124 return _context;
125 }
126
127
128
129
130
131
132
133 public void addClassPath(String classPath)
134 throws IOException
135 {
136 if (classPath == null)
137 return;
138
139 StringTokenizer tokenizer= new StringTokenizer(classPath, ",;");
140 while (tokenizer.hasMoreTokens())
141 {
142 Resource resource= _context.newResource(tokenizer.nextToken());
143 if (Log.isDebugEnabled())
144 Log.debug("Path resource=" + resource);
145
146
147 File file= resource.getFile();
148 if (file != null)
149 {
150 URL url= resource.getURL();
151 addURL(url);
152 }
153 else
154 {
155
156 if (!resource.isDirectory() && file == null)
157 {
158 throw new IllegalArgumentException("!file: "+resource);
159 }
160 else
161 {
162 URL url= resource.getURL();
163 addURL(url);
164 }
165 }
166 }
167 }
168
169
170
171
172
173 private boolean isFileSupported(String file)
174 {
175 int dot = file.lastIndexOf('.');
176 return dot!=-1 && _extensions.contains(file.substring(dot));
177 }
178
179
180
181
182
183
184 public void addJars(Resource lib)
185 {
186 if (lib.exists() && lib.isDirectory())
187 {
188 String[] files=lib.list();
189 for (int f=0;files!=null && f<files.length;f++)
190 {
191 try {
192 Resource fn=lib.addPath(files[f]);
193 String fnlc=fn.getName().toLowerCase();
194 if (isFileSupported(fnlc))
195 {
196 String jar=fn.toString();
197 jar=StringUtil.replace(jar, ",", "%2C");
198 jar=StringUtil.replace(jar, ";", "%3B");
199 addClassPath(jar);
200 }
201 }
202 catch (Exception ex)
203 {
204 Log.warn(Log.EXCEPTION,ex);
205 }
206 }
207 }
208 }
209
210 public void destroy()
211 {
212 this._parent=null;
213 }
214
215
216
217 public PermissionCollection getPermissions(CodeSource cs)
218 {
219
220 PermissionCollection permissions=_context.getPermissions();
221 PermissionCollection pc= (permissions == null) ? super.getPermissions(cs) : permissions;
222 return pc;
223 }
224
225
226 public Enumeration<URL> getResources(String name) throws IOException
227 {
228 boolean system_class=_context.isSystemClass(name);
229 boolean server_class=_context.isServerClass(name);
230
231
232 List<URL> from_parent = toList(server_class?null:_parent.getResources(name));
233 List<URL> from_webapp = toList((system_class&&!from_parent.isEmpty())?null:this.findResources(name));
234
235 if (_context.isParentLoaderPriority())
236 {
237 from_parent.addAll(from_webapp);
238 return Collections.enumeration(from_parent);
239 }
240 from_webapp.addAll(from_parent);
241 return Collections.enumeration(from_webapp);
242 }
243
244 private List<URL> toList(Enumeration<URL> e)
245 {
246 List<URL> list = new ArrayList<URL>();
247 while (e!=null && e.hasMoreElements())
248 list.add(e.nextElement());
249 return list;
250 }
251
252
253 public URL getResource(String name)
254 {
255 URL url= null;
256 boolean tried_parent= false;
257 boolean system_class=_context.isSystemClass(name);
258 boolean server_class=_context.isServerClass(name);
259
260 if (system_class && server_class)
261 return null;
262
263 if (_parent!=null &&(_context.isParentLoaderPriority() || system_class ) && !server_class)
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 && !server_class )
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 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) && !server_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 }