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