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