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