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