1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.annotations;
20
21 import java.net.URI;
22 import java.util.ArrayList;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.ServiceLoader;
26 import java.util.Set;
27
28 import javax.servlet.ServletContainerInitializer;
29 import javax.servlet.ServletContext;
30 import javax.servlet.ServletException;
31 import javax.servlet.annotation.HandlesTypes;
32
33
34 import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
35 import org.eclipse.jetty.plus.annotation.ContainerInitializer;
36 import org.eclipse.jetty.util.MultiMap;
37 import org.eclipse.jetty.util.log.Log;
38 import org.eclipse.jetty.util.log.Logger;
39 import org.eclipse.jetty.util.resource.Resource;
40 import org.eclipse.jetty.webapp.Configuration;
41 import org.eclipse.jetty.webapp.AbstractConfiguration;
42 import org.eclipse.jetty.webapp.Descriptor;
43 import org.eclipse.jetty.webapp.DiscoveredAnnotation;
44 import org.eclipse.jetty.webapp.FragmentDescriptor;
45 import org.eclipse.jetty.webapp.MetaDataComplete;
46 import org.eclipse.jetty.webapp.WebAppContext;
47 import org.eclipse.jetty.webapp.WebDescriptor;
48
49
50
51
52
53
54 public class AnnotationConfiguration extends AbstractConfiguration
55 {
56 private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class);
57 public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
58 public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers";
59
60
61 protected List<DiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
62 protected ClassInheritanceHandler _classInheritanceHandler;
63 protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();
64
65
66 public void preConfigure(final WebAppContext context) throws Exception
67 {
68 }
69
70
71
72
73
74
75 @Override
76 public void configure(WebAppContext context) throws Exception
77 {
78 boolean metadataComplete = context.getMetaData().isMetaDataComplete();
79 context.addDecorator(new AnnotationDecorator(context));
80
81
82
83 AnnotationParser parser = null;
84 if (!metadataComplete)
85 {
86
87 if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered())
88 {
89 _discoverableAnnotationHandlers.add(new WebServletAnnotationHandler(context));
90 _discoverableAnnotationHandlers.add(new WebFilterAnnotationHandler(context));
91 _discoverableAnnotationHandlers.add(new WebListenerAnnotationHandler(context));
92 }
93 }
94 else
95 if (LOG.isDebugEnabled()) LOG.debug("Metadata-complete==true, not processing discoverable servlet annotations for context "+context);
96
97
98
99
100
101 createServletContainerInitializerAnnotationHandlers(context, getNonExcludedInitializers(context));
102
103 if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
104 {
105 parser = createAnnotationParser();
106 if (LOG.isDebugEnabled()) LOG.debug("Scanning all classses for annotations: webxmlVersion="+context.getServletContext().getEffectiveMajorVersion()+" configurationDiscovered="+context.isConfigurationDiscovered());
107 parseContainerPath(context, parser);
108
109
110
111
112
113 parseWebInfClasses(context, parser);
114 parseWebInfLib (context, parser);
115
116 for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
117 context.getMetaData().addDiscoveredAnnotations(((AbstractDiscoverableAnnotationHandler)h).getAnnotationList());
118 }
119 }
120
121
122
123
124
125
126 @Override
127 public void postConfigure(WebAppContext context) throws Exception
128 {
129 MultiMap map = (MultiMap)context.getAttribute(CLASS_INHERITANCE_MAP);
130 if (map != null)
131 map.clear();
132
133 context.removeAttribute(CLASS_INHERITANCE_MAP);
134
135 List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS);
136 if (initializers != null)
137 initializers.clear();
138 if (_discoverableAnnotationHandlers != null)
139 _discoverableAnnotationHandlers.clear();
140
141 _classInheritanceHandler = null;
142 if (_containerInitializerAnnotationHandlers != null)
143 _containerInitializerAnnotationHandlers.clear();
144
145 super.postConfigure(context);
146 }
147
148
149
150
151
152 protected AnnotationParser createAnnotationParser()
153 {
154 return new AnnotationParser();
155 }
156
157
158
159
160 @Override
161 public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
162 {
163 context.addDecorator(new AnnotationDecorator(context));
164 }
165
166
167
168
169
170
171
172
173 public void createServletContainerInitializerAnnotationHandlers (WebAppContext context, List<ServletContainerInitializer> scis)
174 throws Exception
175 {
176
177 if (scis == null || scis.isEmpty())
178 return;
179
180
181 List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
182 context.setAttribute(CONTAINER_INITIALIZERS, initializers);
183
184 for (ServletContainerInitializer service : scis)
185 {
186 HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class);
187 ContainerInitializer initializer = new ContainerInitializer();
188 initializer.setTarget(service);
189 initializers.add(initializer);
190 if (annotation != null)
191 {
192
193 Class[] classes = annotation.value();
194 if (classes != null)
195 {
196 initializer.setInterestedTypes(classes);
197
198
199
200 if (context.getAttribute(CLASS_INHERITANCE_MAP) == null)
201 {
202 MultiMap map = new MultiMap();
203 context.setAttribute(CLASS_INHERITANCE_MAP, map);
204 _classInheritanceHandler = new ClassInheritanceHandler(map);
205 }
206
207 for (Class c: classes)
208 {
209
210
211 if (c.isAnnotation())
212 {
213 if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for "+c.getName());
214
215 _containerInitializerAnnotationHandlers.add(new ContainerInitializerAnnotationHandler(initializer, c));
216 }
217 }
218 }
219 else
220 if (LOG.isDebugEnabled()) LOG.debug("No classes in HandlesTypes on initializer "+service.getClass());
221 }
222 else
223 if (LOG.isDebugEnabled()) LOG.debug("No annotation on initializer "+service.getClass());
224 }
225
226
227
228 ServletContainerInitializerListener listener = new ServletContainerInitializerListener();
229 listener.setWebAppContext(context);
230 context.addEventListener(listener);
231 }
232
233
234
235
236
237
238
239
240
241
242 public boolean isFromExcludedJar (WebAppContext context, ServletContainerInitializer service)
243 throws Exception
244 {
245 List<Resource> orderedJars = context.getMetaData().getOrderedWebInfJars();
246
247
248 if (context.getMetaData().getOrdering() == null)
249 return false;
250
251
252 if (orderedJars.isEmpty())
253 return true;
254
255 String loadingJarName = Thread.currentThread().getContextClassLoader().getResource(service.getClass().getName().replace('.','/')+".class").toString();
256
257 int i = loadingJarName.indexOf(".jar");
258 if (i < 0)
259 return false;
260
261 loadingJarName = loadingJarName.substring(0,i+4);
262 loadingJarName = (loadingJarName.startsWith("jar:")?loadingJarName.substring(4):loadingJarName);
263 URI loadingJarURI = Resource.newResource(loadingJarName).getURI();
264 boolean found = false;
265 Iterator<Resource> itor = orderedJars.iterator();
266 while (!found && itor.hasNext())
267 {
268 Resource r = itor.next();
269 found = r.getURI().equals(loadingJarURI);
270 }
271
272 return !found;
273 }
274
275
276
277
278
279
280
281
282 public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppContext context)
283 throws Exception
284 {
285 List<ServletContainerInitializer> nonExcludedInitializers = new ArrayList<ServletContainerInitializer>();
286
287
288 ServiceLoader<ServletContainerInitializer> loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class, context.getClassLoader());
289
290 if (loadedInitializers != null)
291 {
292 for (ServletContainerInitializer service : loadedInitializers)
293 {
294 if (!isFromExcludedJar(context, service))
295 nonExcludedInitializers.add(service);
296 }
297 }
298 return nonExcludedInitializers;
299 }
300
301
302
303
304
305
306
307
308
309
310
311 public void parseContainerPath (final WebAppContext context, final AnnotationParser parser)
312 throws Exception
313 {
314
315 LOG.debug("Scanning container jars");
316
317
318 parser.clearHandlers();
319 for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
320 {
321 if (h instanceof AbstractDiscoverableAnnotationHandler)
322 ((AbstractDiscoverableAnnotationHandler)h).setResource(null);
323 }
324 parser.registerHandlers(_discoverableAnnotationHandlers);
325 parser.registerHandler(_classInheritanceHandler);
326 parser.registerHandlers(_containerInitializerAnnotationHandlers);
327
328
329 ArrayList<URI> containerUris = new ArrayList<URI>();
330 for (Resource r : context.getMetaData().getOrderedContainerJars())
331 {
332 URI uri = r.getURI();
333 containerUris.add(uri);
334 }
335
336 parser.parse (containerUris.toArray(new URI[containerUris.size()]),
337 new ClassNameResolver ()
338 {
339 public boolean isExcluded (String name)
340 {
341 if (context.isSystemClass(name)) return false;
342 if (context.isServerClass(name)) return true;
343 return false;
344 }
345
346 public boolean shouldOverride (String name)
347 {
348
349 if (context.isParentLoaderPriority())
350 return true;
351 return false;
352 }
353 });
354
355
356 }
357
358
359
360
361
362
363
364
365
366 public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser)
367 throws Exception
368 {
369 List<FragmentDescriptor> frags = context.getMetaData().getFragments();
370
371
372
373
374 ArrayList<URI> webInfUris = new ArrayList<URI>();
375
376 List<Resource> jars = context.getMetaData().getOrderedWebInfJars();
377
378
379 if (jars == null || jars.isEmpty())
380 jars = context.getMetaData().getWebInfJars();
381
382 for (Resource r : jars)
383 {
384
385 parser.clearHandlers();
386 URI uri = r.getURI();
387 FragmentDescriptor f = getFragmentFromJar(r, frags);
388
389
390
391
392
393 if (f == null || !isMetaDataComplete(f) || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
394 {
395
396 parser.registerHandler(_classInheritanceHandler);
397
398
399 parser.registerHandlers(_containerInitializerAnnotationHandlers);
400
401
402 if (f == null || !isMetaDataComplete(f))
403 {
404 for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
405 {
406 if (h instanceof AbstractDiscoverableAnnotationHandler)
407 ((AbstractDiscoverableAnnotationHandler)h).setResource(r);
408 }
409 parser.registerHandlers(_discoverableAnnotationHandlers);
410 }
411
412 parser.parse(uri,
413 new ClassNameResolver()
414 {
415 public boolean isExcluded (String name)
416 {
417 if (context.isSystemClass(name)) return true;
418 if (context.isServerClass(name)) return false;
419 return false;
420 }
421
422 public boolean shouldOverride (String name)
423 {
424
425 if (context.isParentLoaderPriority())
426 return false;
427 return true;
428 }
429 });
430 }
431 }
432 }
433
434
435
436
437
438
439
440
441 public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
442 throws Exception
443 {
444 LOG.debug("Scanning classes in WEB-INF/classes");
445 if (context.getWebInf() != null)
446 {
447 Resource classesDir = context.getWebInf().addPath("classes/");
448 if (classesDir.exists())
449 {
450 parser.clearHandlers();
451 for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
452 {
453 if (h instanceof AbstractDiscoverableAnnotationHandler)
454 ((AbstractDiscoverableAnnotationHandler)h).setResource(null);
455 }
456 parser.registerHandlers(_discoverableAnnotationHandlers);
457 parser.registerHandler(_classInheritanceHandler);
458 parser.registerHandlers(_containerInitializerAnnotationHandlers);
459
460 parser.parse(classesDir,
461 new ClassNameResolver()
462 {
463 public boolean isExcluded (String name)
464 {
465 if (context.isSystemClass(name)) return true;
466 if (context.isServerClass(name)) return false;
467 return false;
468 }
469
470 public boolean shouldOverride (String name)
471 {
472
473 if (context.isParentLoaderPriority())
474 return false;
475 return true;
476 }
477 });
478 }
479 }
480 }
481
482
483
484
485
486
487
488
489
490
491
492 public FragmentDescriptor getFragmentFromJar (Resource jar, List<FragmentDescriptor> frags)
493 throws Exception
494 {
495
496 FragmentDescriptor d = null;
497 for (FragmentDescriptor frag: frags)
498 {
499 Resource fragResource = frag.getResource();
500 if (Resource.isContainedIn(fragResource,jar))
501 {
502 d = frag;
503 break;
504 }
505 }
506 return d;
507 }
508
509 public boolean isMetaDataComplete (WebDescriptor d)
510 {
511 return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
512 }
513 }