1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.maven.plugin;
20
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.lang.reflect.Method;
25 import java.net.MalformedURLException;
26 import java.util.ArrayList;
27 import java.util.EventListener;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.TreeSet;
33
34 import org.eclipse.jetty.annotations.AnnotationConfiguration;
35 import org.eclipse.jetty.plus.webapp.EnvConfiguration;
36 import org.eclipse.jetty.plus.webapp.PlusConfiguration;
37 import org.eclipse.jetty.quickstart.PreconfigureDescriptorProcessor;
38 import org.eclipse.jetty.quickstart.QuickStartDescriptorGenerator;
39 import org.eclipse.jetty.servlet.FilterHolder;
40 import org.eclipse.jetty.servlet.FilterMapping;
41 import org.eclipse.jetty.servlet.ServletHolder;
42 import org.eclipse.jetty.servlet.ServletMapping;
43 import org.eclipse.jetty.util.StringUtil;
44 import org.eclipse.jetty.util.URIUtil;
45 import org.eclipse.jetty.util.log.Log;
46 import org.eclipse.jetty.util.log.Logger;
47 import org.eclipse.jetty.util.resource.Resource;
48 import org.eclipse.jetty.util.resource.ResourceCollection;
49 import org.eclipse.jetty.webapp.Configuration;
50 import org.eclipse.jetty.webapp.FragmentConfiguration;
51 import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
52 import org.eclipse.jetty.webapp.MetaInfConfiguration;
53 import org.eclipse.jetty.webapp.WebAppContext;
54 import org.eclipse.jetty.webapp.WebInfConfiguration;
55 import org.eclipse.jetty.webapp.WebXmlConfiguration;
56
57
58
59
60
61
62
63
64
65
66 public class JettyWebAppContext extends WebAppContext
67 {
68 private static final Logger LOG = Log.getLogger(JettyWebAppContext.class);
69
70
71
72 private static final String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN = ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$|.*javax.servlet.jsp.jstl-[^/]*\\.jar|.*taglibs-standard-impl-.*\\.jar";
73 private static final String WEB_INF_CLASSES_PREFIX = "/WEB-INF/classes";
74 private static final String WEB_INF_LIB_PREFIX = "/WEB-INF/lib";
75
76
77 public static final String[] DEFAULT_CONFIGURATION_CLASSES = {
78 "org.eclipse.jetty.maven.plugin.MavenWebInfConfiguration",
79 "org.eclipse.jetty.webapp.WebXmlConfiguration",
80 "org.eclipse.jetty.webapp.MetaInfConfiguration",
81 "org.eclipse.jetty.webapp.FragmentConfiguration",
82 "org.eclipse.jetty.plus.webapp.EnvConfiguration",
83 "org.eclipse.jetty.plus.webapp.PlusConfiguration",
84 "org.eclipse.jetty.annotations.AnnotationConfiguration",
85 "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"
86 };
87
88
89 private final String[] QUICKSTART_CONFIGURATION_CLASSES = {
90 "org.eclipse.jetty.maven.plugin.MavenQuickStartConfiguration",
91 "org.eclipse.jetty.plus.webapp.EnvConfiguration",
92 "org.eclipse.jetty.plus.webapp.PlusConfiguration",
93 "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"
94 };
95
96 private File _classes = null;
97 private File _testClasses = null;
98 private final List<File> _webInfClasses = new ArrayList<File>();
99 private final List<File> _webInfJars = new ArrayList<File>();
100 private final Map<String, File> _webInfJarMap = new HashMap<String, File>();
101 private List<File> _classpathFiles;
102 private String _jettyEnvXml;
103 private List<Overlay> _overlays;
104 private Resource _quickStartWebXml;
105
106
107
108
109
110
111
112
113 private String _containerIncludeJarPattern = null;
114
115
116
117
118
119 private String _webInfIncludeJarPattern = null;
120
121
122
123
124
125
126
127
128 private boolean _baseAppFirst = true;
129
130
131
132 private boolean _isGenerateQuickStart;
133 private PreconfigureDescriptorProcessor _preconfigProcessor;
134
135
136
137
138 public JettyWebAppContext ()
139 throws Exception
140 {
141 super();
142
143 super.setCopyWebInf(false);
144 }
145
146
147 public void setContainerIncludeJarPattern(String pattern)
148 {
149 _containerIncludeJarPattern = pattern;
150 }
151
152
153 public String getContainerIncludeJarPattern()
154 {
155 return _containerIncludeJarPattern;
156 }
157
158
159 public String getWebInfIncludeJarPattern()
160 {
161 return _webInfIncludeJarPattern;
162 }
163
164
165 public void setWebInfIncludeJarPattern(String pattern)
166 {
167 _webInfIncludeJarPattern = pattern;
168 }
169
170
171 public List<File> getClassPathFiles()
172 {
173 return this._classpathFiles;
174 }
175
176
177 public void setJettyEnvXml (String jettyEnvXml)
178 {
179 this._jettyEnvXml = jettyEnvXml;
180 }
181
182
183 public String getJettyEnvXml()
184 {
185 return this._jettyEnvXml;
186 }
187
188
189 public void setClasses(File dir)
190 {
191 _classes = dir;
192 }
193
194
195 public File getClasses()
196 {
197 return _classes;
198 }
199
200
201 public void setWebInfLib (List<File> jars)
202 {
203 _webInfJars.addAll(jars);
204 }
205
206
207 public void setTestClasses (File dir)
208 {
209 _testClasses = dir;
210 }
211
212
213 public File getTestClasses ()
214 {
215 return _testClasses;
216 }
217
218
219
220
221
222
223
224
225 public void setOverlays (List<Overlay> overlays)
226 {
227 _overlays = overlays;
228 }
229
230
231 public List<Overlay> getOverlays()
232 {
233 return _overlays;
234 }
235
236
237 public void setBaseAppFirst(boolean value)
238 {
239 _baseAppFirst = value;
240 }
241
242
243 public boolean getBaseAppFirst()
244 {
245 return _baseAppFirst;
246 }
247
248
249 public void setQuickStartWebDescriptor (String quickStartWebXml) throws Exception
250 {
251 setQuickStartWebDescriptor(Resource.newResource(quickStartWebXml));
252 }
253
254
255 protected void setQuickStartWebDescriptor (Resource quickStartWebXml)
256 {
257 _quickStartWebXml = quickStartWebXml;
258 }
259
260
261 public Resource getQuickStartWebDescriptor ()
262 {
263 return _quickStartWebXml;
264 }
265
266
267
268
269
270
271
272 public void setResourceBases(String[] resourceBases)
273 {
274 List<String> resources = new ArrayList<String>();
275 for (String rl:resourceBases)
276 {
277 String[] rs = StringUtil.csvSplit(rl);
278 for (String r:rs)
279 resources.add(r);
280 }
281
282 setBaseResource(new ResourceCollection(resources.toArray(new String[resources.size()])));
283 }
284
285
286 public List<File> getWebInfLib()
287 {
288 return _webInfJars;
289 }
290
291
292 public void setGenerateQuickStart (boolean quickStart)
293 {
294 _isGenerateQuickStart = quickStart;
295 }
296
297
298 public boolean isGenerateQuickStart()
299 {
300 return _isGenerateQuickStart;
301 }
302
303
304
305
306 @Override
307 protected void startWebapp() throws Exception
308 {
309 if (isGenerateQuickStart())
310 {
311 if (getQuickStartWebDescriptor() == null)
312 throw new IllegalStateException ("No location to generate quickstart descriptor");
313
314 QuickStartDescriptorGenerator generator = new QuickStartDescriptorGenerator(this, _preconfigProcessor.getXML());
315 try (FileOutputStream fos = new FileOutputStream(getQuickStartWebDescriptor().getFile()))
316 {
317 generator.generateQuickStartWebXml(fos);
318 }
319 }
320 else
321 {
322 if (LOG.isDebugEnabled()) { LOG.debug("Calling full start on webapp");}
323 super.startWebapp();
324 }
325 }
326
327
328 @Override
329 protected void stopWebapp() throws Exception
330 {
331 if (isGenerateQuickStart())
332 return;
333
334 if (LOG.isDebugEnabled()) { LOG.debug("Calling stop of fully started webapp");}
335 super.stopWebapp();
336 }
337
338
339 @Override
340 public void doStart () throws Exception
341 {
342
343 if (!isGenerateQuickStart() && getQuickStartWebDescriptor() != null)
344 {
345 setConfigurationClasses(QUICKSTART_CONFIGURATION_CLASSES);
346 }
347 else
348 {
349 if (isGenerateQuickStart())
350 {
351 _preconfigProcessor = new PreconfigureDescriptorProcessor();
352 getMetaData().addDescriptorProcessor(_preconfigProcessor);
353 }
354 }
355
356
357
358
359
360 String tmp = _containerIncludeJarPattern;
361 if (tmp==null || "".equals(tmp))
362 tmp = (String)getAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN);
363
364 tmp = addPattern(tmp, DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN);
365 setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, tmp);
366
367
368
369
370 if (_webInfIncludeJarPattern != null)
371 setAttribute(WebInfConfiguration.WEBINF_JAR_PATTERN, _webInfIncludeJarPattern);
372
373
374 if (_testClasses != null)
375 _webInfClasses.add(_testClasses);
376 if (_classes != null)
377 _webInfClasses.add(_classes);
378
379
380 _classpathFiles = new ArrayList<File>();
381 _classpathFiles.addAll(_webInfClasses);
382 _classpathFiles.addAll(_webInfJars);
383
384
385 _webInfJarMap.clear();
386 for (File file : _webInfJars)
387 {
388
389 String fileName = file.getName();
390 if (fileName.endsWith(".jar"))
391 _webInfJarMap.put(fileName, file);
392 }
393
394
395 initCDI();
396
397
398 super.doStart();
399 }
400
401
402 @Override
403 protected void loadConfigurations() throws Exception
404 {
405 super.loadConfigurations();
406
407
408 for (Configuration c:getConfigurations())
409 {
410 if (c instanceof EnvConfiguration && getJettyEnvXml() != null)
411 ((EnvConfiguration)c).setJettyEnvXml(Resource.toURL(new File(getJettyEnvXml())));
412 else if (c instanceof MavenQuickStartConfiguration && getQuickStartWebDescriptor() != null)
413 ((MavenQuickStartConfiguration)c).setQuickStartWebXml(getQuickStartWebDescriptor());
414 }
415 }
416
417
418
419 public void doStop () throws Exception
420 {
421 if (_classpathFiles != null)
422 _classpathFiles.clear();
423 _classpathFiles = null;
424
425 _classes = null;
426 _testClasses = null;
427
428 if (_webInfJarMap != null)
429 _webInfJarMap.clear();
430
431 _webInfClasses.clear();
432 _webInfJars.clear();
433
434
435
436
437
438 Thread.currentThread().sleep(500L);
439
440 super.doStop();
441
442
443
444 setEventListeners(new EventListener[0]);
445 getServletHandler().setFilters(new FilterHolder[0]);
446 getServletHandler().setFilterMappings(new FilterMapping[0]);
447 getServletHandler().setServlets(new ServletHolder[0]);
448 getServletHandler().setServletMappings(new ServletMapping[0]);
449 }
450
451
452
453 @Override
454 public Resource getResource(String uriInContext) throws MalformedURLException
455 {
456 Resource resource = null;
457
458 resource = super.getResource(uriInContext);
459
460
461 if ((resource == null || !resource.exists()) && uriInContext != null && _classes != null)
462 {
463 String uri = URIUtil.canonicalPath(uriInContext);
464 if (uri == null)
465 return null;
466
467 try
468 {
469
470 if (uri.startsWith(WEB_INF_CLASSES_PREFIX))
471 {
472 if (uri.equalsIgnoreCase(WEB_INF_CLASSES_PREFIX) || uri.equalsIgnoreCase(WEB_INF_CLASSES_PREFIX+"/"))
473 {
474
475
476 if (_classes != null)
477 return Resource.newResource(_classes);
478 else if (_testClasses != null)
479 return Resource.newResource(_testClasses);
480 }
481 else
482 {
483
484 Resource res = null;
485 int i=0;
486 while (res == null && (i < _webInfClasses.size()))
487 {
488 String newPath = uri.replace(WEB_INF_CLASSES_PREFIX, _webInfClasses.get(i).getPath());
489 res = Resource.newResource(newPath);
490 if (!res.exists())
491 {
492 res = null;
493 i++;
494 }
495 }
496 return res;
497 }
498 }
499 else if (uri.startsWith(WEB_INF_LIB_PREFIX))
500 {
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529 @Override
530 public Set<String> getResourcePaths(String path)
531 {
532
533 Set<String> paths = super.getResourcePaths(path);
534
535 if (path != null)
536 {
537 TreeSet<String> allPaths = new TreeSet<String>();
538 allPaths.addAll(paths);
539
540
541 if (path.startsWith(WEB_INF_LIB_PREFIX))
542 {
543 for (String fileName : _webInfJarMap.keySet())
544 {
545
546 allPaths.add(WEB_INF_LIB_PREFIX + "/" + fileName);
547 }
548 }
549 else if (path.startsWith(WEB_INF_CLASSES_PREFIX))
550 {
551 int i=0;
552
553 while (i < _webInfClasses.size())
554 {
555 String newPath = path.replace(WEB_INF_CLASSES_PREFIX, _webInfClasses.get(i).getPath());
556 allPaths.addAll(super.getResourcePaths(newPath));
557 i++;
558 }
559 }
560 return allPaths;
561 }
562 return paths;
563 }
564
565
566 public String addPattern (String s, String pattern)
567 {
568 if (s == null)
569 s = "";
570 else
571 s = s.trim();
572
573 if (!s.contains(pattern))
574 {
575 if (s.length() != 0)
576 s = s + "|";
577 s = s + pattern;
578 }
579
580 return s;
581 }
582
583
584
585 public void initCDI()
586 {
587 Class cdiInitializer = null;
588 try
589 {
590 cdiInitializer = Thread.currentThread().getContextClassLoader().loadClass("org.eclipse.jetty.cdi.servlet.JettyWeldInitializer");
591 Method initWebAppMethod = cdiInitializer.getMethod("initWebApp", new Class[]{WebAppContext.class});
592 initWebAppMethod.invoke(null, new Object[]{this});
593 }
594 catch (ClassNotFoundException e)
595 {
596 LOG.debug("o.e.j.cdi.servlet.JettyWeldInitializer not found, no cdi integration available");
597 }
598 catch (NoSuchMethodException e)
599 {
600 LOG.warn("o.e.j.cdi.servlet.JettyWeldInitializer.initWebApp() not found, no cdi integration available");
601 }
602 catch (Exception e)
603 {
604 LOG.warn("Problem initializing cdi", e);
605 }
606 }
607 }