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