1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.eclipse.jetty.osgi.boot.internal.webapp;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.lang.reflect.Field;
20 import java.net.URL;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.StringTokenizer;
28 import java.util.jar.JarFile;
29
30 import javax.servlet.http.HttpServlet;
31
32 import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper;
33 import org.eclipse.jetty.util.log.Log;
34 import org.eclipse.jetty.util.log.Logger;
35 import org.eclipse.jetty.util.resource.Resource;
36 import org.eclipse.jetty.webapp.WebAppClassLoader;
37 import org.eclipse.jetty.webapp.WebAppContext;
38 import org.osgi.framework.Bundle;
39 import org.osgi.framework.BundleReference;
40
41
42
43
44
45 public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleReference
46 {
47
48 private Logger __logger = Log.getLogger(OSGiWebappClassLoader.class.getName().toString());
49
50
51
52
53
54 public static Set<String> JAR_WITH_SUCH_CLASS_MUST_BE_EXCLUDED = new HashSet<String>();
55
56 public static void addClassThatIdentifiesAJarThatMustBeRejected(Class<?> zclass)
57 {
58 JAR_WITH_SUCH_CLASS_MUST_BE_EXCLUDED.add(zclass.getName().replace('.','/') + ".class");
59 }
60
61 public static void addClassThatIdentifiesAJarThatMustBeRejected(String zclassName)
62 {
63 JAR_WITH_SUCH_CLASS_MUST_BE_EXCLUDED.add(zclassName.replace('.','/') + ".class");
64 }
65
66 static
67 {
68 addClassThatIdentifiesAJarThatMustBeRejected(HttpServlet.class);
69 }
70
71 private ClassLoader _osgiBundleClassLoader;
72 private Bundle _contributor;
73 private boolean _lookInOsgiFirst = true;
74 private Set<String> _libsAlreadyInManifest = new HashSet<String>();
75
76
77
78
79
80
81
82 public OSGiWebappClassLoader(ClassLoader parent, WebAppContext context, Bundle contributor,
83 BundleClassLoaderHelper bundleClassLoaderHelper) throws IOException
84 {
85 super(parent,context);
86 _contributor = contributor;
87 _osgiBundleClassLoader = bundleClassLoaderHelper.getBundleClassLoader(contributor);
88 }
89
90
91
92
93
94
95
96 public Bundle getBundle()
97 {
98 return _contributor;
99 }
100
101
102
103
104
105
106
107 private void computeLibsAlreadyInOSGiClassLoader()
108 {
109
110 }
111
112 @Override
113 public Enumeration<URL> getResources(String name) throws IOException
114 {
115 Enumeration<URL> osgiUrls = _osgiBundleClassLoader.getResources(name);
116 Enumeration<URL> urls = super.getResources(name);
117 if (_lookInOsgiFirst)
118 {
119 return Collections.enumeration(toList(osgiUrls, urls));
120 }
121 else
122 {
123 return Collections.enumeration(toList(urls, osgiUrls));
124 }
125 }
126
127 @Override
128 public URL getResource(String name)
129 {
130 if (_lookInOsgiFirst)
131 {
132 URL url = _osgiBundleClassLoader.getResource(name);
133 return url != null ? url : super.getResource(name);
134 }
135 else
136 {
137 URL url = super.getResource(name);
138 return url != null ? url : _osgiBundleClassLoader.getResource(name);
139 }
140 }
141
142 private List<URL> toList(Enumeration<URL> e, Enumeration<URL> e2)
143 {
144 List<URL> list = new ArrayList<URL>();
145 while (e!=null && e.hasMoreElements())
146 list.add(e.nextElement());
147 while (e2!=null && e2.hasMoreElements())
148 list.add(e2.nextElement());
149 return list;
150 }
151
152
153
154
155 protected Class<?> findClass(String name) throws ClassNotFoundException
156 {
157 try
158 {
159 return _lookInOsgiFirst?_osgiBundleClassLoader.loadClass(name):super.findClass(name);
160 }
161 catch (ClassNotFoundException cne)
162 {
163 try
164 {
165 return _lookInOsgiFirst?super.findClass(name):_osgiBundleClassLoader.loadClass(name);
166 }
167 catch (ClassNotFoundException cne2)
168 {
169 throw cne;
170 }
171 }
172 }
173
174
175
176
177
178 @Override
179 public void addClassPath(String classPath) throws IOException
180 {
181
182 StringTokenizer tokenizer = new StringTokenizer(classPath,",;");
183 while (tokenizer.hasMoreTokens())
184 {
185 String path = tokenizer.nextToken();
186 Resource resource = getContext().newResource(path);
187
188
189 File file = resource.getFile();
190 if (file != null && isAcceptableLibrary(file,JAR_WITH_SUCH_CLASS_MUST_BE_EXCLUDED))
191 {
192 super.addClassPath(path);
193 }
194 else
195 {
196 __logger.info("Did not add " + path + " to the classloader of the webapp " + getContext());
197 }
198 }
199
200 }
201
202
203
204
205
206 private boolean isAcceptableLibrary(File file, Set<String> pathToClassFiles)
207 {
208 try
209 {
210 if (file.isDirectory())
211 {
212 for (String criteria : pathToClassFiles)
213 {
214 if (new File(file,criteria).exists())
215 {
216 return false;
217 }
218 }
219 }
220 else
221 {
222 JarFile jar = null;
223 try
224 {
225 jar = new JarFile(file);
226 for (String criteria : pathToClassFiles)
227 {
228 if (jar.getEntry(criteria) != null)
229 {
230 return false;
231 }
232 }
233 }
234 finally
235 {
236 if (jar != null)
237 try
238 {
239 jar.close();
240 }
241 catch (IOException ioe)
242 {
243 }
244 }
245 }
246 }
247 catch (IOException e)
248 {
249
250 e.printStackTrace();
251 }
252 return true;
253 }
254
255 private static Field _contextField;
256
257
258
259
260
261
262
263
264 public void setWebappContext(WebAppContext webappContext)
265 {
266 try
267 {
268 if (_contextField == null)
269 {
270 _contextField = WebAppClassLoader.class.getDeclaredField("_context");
271 _contextField.setAccessible(true);
272 }
273 _contextField.set(this,webappContext);
274 if (webappContext.getExtraClasspath() != null)
275 {
276 addClassPath(webappContext.getExtraClasspath());
277 }
278 }
279 catch (Throwable t)
280 {
281
282 t.printStackTrace();
283 }
284 }
285 }