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