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