1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.ant;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.net.URL;
25 import java.net.URLClassLoader;
26 import java.security.CodeSource;
27 import java.security.PermissionCollection;
28 import java.util.ArrayList;
29 import java.util.Enumeration;
30 import java.util.EventListener;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Set;
35 import java.util.jar.Manifest;
36
37 import javax.servlet.Servlet;
38
39 import org.apache.tools.ant.AntClassLoader;
40 import org.apache.tools.ant.BuildException;
41 import org.apache.tools.ant.Project;
42 import org.apache.tools.ant.types.FileSet;
43 import org.eclipse.jetty.annotations.AnnotationConfiguration;
44 import org.eclipse.jetty.ant.types.Attribute;
45 import org.eclipse.jetty.ant.types.Attributes;
46 import org.eclipse.jetty.ant.types.FileMatchingConfiguration;
47 import org.eclipse.jetty.ant.utils.TaskLog;
48 import org.eclipse.jetty.plus.webapp.EnvConfiguration;
49 import org.eclipse.jetty.plus.webapp.PlusConfiguration;
50 import org.eclipse.jetty.servlet.FilterHolder;
51 import org.eclipse.jetty.servlet.FilterMapping;
52 import org.eclipse.jetty.servlet.Holder;
53 import org.eclipse.jetty.servlet.ServletHandler;
54 import org.eclipse.jetty.servlet.ServletHolder;
55 import org.eclipse.jetty.servlet.ServletMapping;
56 import org.eclipse.jetty.util.log.Log;
57 import org.eclipse.jetty.util.log.Logger;
58 import org.eclipse.jetty.util.resource.Resource;
59 import org.eclipse.jetty.webapp.Configuration;
60 import org.eclipse.jetty.webapp.FragmentConfiguration;
61 import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
62 import org.eclipse.jetty.webapp.MetaInfConfiguration;
63 import org.eclipse.jetty.webapp.WebAppClassLoader;
64 import org.eclipse.jetty.webapp.WebAppContext;
65 import org.eclipse.jetty.webapp.WebInfConfiguration;
66 import org.eclipse.jetty.webapp.WebXmlConfiguration;
67 import org.eclipse.jetty.xml.XmlConfiguration;
68
69
70
71
72 public class AntWebAppContext extends WebAppContext
73 {
74 private static final Logger LOG = Log.getLogger(WebAppContext.class);
75
76 public final AntWebInfConfiguration antWebInfConfiguration = new AntWebInfConfiguration();
77 public final WebXmlConfiguration webXmlConfiguration = new WebXmlConfiguration();
78 public final MetaInfConfiguration metaInfConfiguration = new MetaInfConfiguration();
79 public final FragmentConfiguration fragmentConfiguration = new FragmentConfiguration();
80 public final EnvConfiguration envConfiguration = new EnvConfiguration();
81 public final PlusConfiguration plusConfiguration = new PlusConfiguration();
82 public final AnnotationConfiguration annotationConfiguration = new AnnotationConfiguration();
83 public final JettyWebXmlConfiguration jettyWebXmlConfiguration = new JettyWebXmlConfiguration();
84
85
86 public final Configuration[] DEFAULT_CONFIGURATIONS =
87 {
88 antWebInfConfiguration,
89 webXmlConfiguration,
90 metaInfConfiguration,
91 fragmentConfiguration,
92 envConfiguration,
93 plusConfiguration,
94 annotationConfiguration,
95 jettyWebXmlConfiguration
96 };
97
98
99 public final static String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN =
100 ".*/.*jsp-api-[^/]*\\.jar$|.*/.*jsp-[^/]*\\.jar$|.*/.*taglibs[^/]*\\.jar$|.*/.*jstl[^/]*\\.jar$|.*/.*jsf-impl-[^/]*\\.jar$|.*/.*javax.faces-[^/]*\\.jar$|.*/.*myfaces-impl-[^/]*\\.jar$";
101
102
103
104 private File jettyEnvXml;
105
106
107 private List libraries = new ArrayList();
108
109
110 private List classes = new ArrayList();
111
112
113 private File contextXml;
114
115
116 private FileSet scanTargets;
117
118
119 private Attributes attributes;
120
121 private Project project;
122
123 private List<File> scanFiles;
124
125
126
127
128 private FileMatchingConfiguration extraScanTargetsConfiguration;
129
130
131 private FileMatchingConfiguration librariesConfiguration;
132
133
134 public static void dump(ClassLoader loader)
135 {
136 while (loader != null)
137 {
138 System.err.println(loader);
139 if (loader instanceof URLClassLoader)
140 {
141 URL[] urls = ((URLClassLoader)loader).getURLs();
142 if (urls != null)
143 {
144 for (URL u:urls)
145 System.err.println("\t"+u+"\n");
146 }
147 }
148 loader = loader.getParent();
149 }
150 }
151
152
153
154
155
156
157
158
159 public static class AntURLClassLoader extends URLClassLoader
160 {
161 private AntClassLoader antLoader;
162
163 public AntURLClassLoader(AntClassLoader antLoader)
164 {
165 super(new URL[] {}, antLoader);
166 this.antLoader = antLoader;
167 }
168
169 @Override
170 public InputStream getResourceAsStream(String name)
171 {
172 return super.getResourceAsStream(name);
173 }
174
175 @Override
176 public void close() throws IOException
177 {
178 super.close();
179 }
180
181 @Override
182 protected void addURL(URL url)
183 {
184 super.addURL(url);
185 }
186
187 @Override
188 public URL[] getURLs()
189 {
190 Set<URL> urls = new HashSet<URL>();
191
192
193 String[] paths = antLoader.getClasspath().split(new String(new char[]{File.pathSeparatorChar}));
194 if (paths != null)
195 {
196 for (String p:paths)
197 {
198 File f = new File(p);
199 try
200 {
201 urls.add(f.toURI().toURL());
202 }
203 catch (Exception e)
204 {
205 LOG.ignore(e);
206 }
207 }
208 }
209
210
211 URL[] ourURLS = super.getURLs();
212 if (ourURLS != null)
213 {
214 for (URL u:ourURLS)
215 urls.add(u);
216 }
217
218 return urls.toArray(new URL[urls.size()]);
219 }
220
221 @Override
222 protected Class<?> findClass(String name) throws ClassNotFoundException
223 {
224 return super.findClass(name);
225 }
226
227 @Override
228 protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException
229 {
230 return super.definePackage(name, man, url);
231 }
232
233 @Override
234 public URL findResource(String name)
235 {
236 return super.findResource(name);
237 }
238
239 @Override
240 public Enumeration<URL> findResources(String name) throws IOException
241 {
242 return super.findResources(name);
243 }
244
245 @Override
246 protected PermissionCollection getPermissions(CodeSource codesource)
247 {
248 return super.getPermissions(codesource);
249 }
250
251 @Override
252 public Class<?> loadClass(String name) throws ClassNotFoundException
253 {
254 return super.loadClass(name);
255 }
256
257 @Override
258 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
259 {
260 return super.loadClass(name, resolve);
261 }
262
263 @Override
264 protected Object getClassLoadingLock(String className)
265 {
266 return super.getClassLoadingLock(className);
267 }
268
269 @Override
270 public URL getResource(String name)
271 {
272 return super.getResource(name);
273 }
274
275 @Override
276 public Enumeration<URL> getResources(String name) throws IOException
277 {
278 return super.getResources(name);
279 }
280
281 @Override
282 protected Package definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion,
283 String implVendor, URL sealBase) throws IllegalArgumentException
284 {
285 return super.definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
286 }
287
288 @Override
289 protected Package getPackage(String name)
290 {
291 return super.getPackage(name);
292 }
293
294 @Override
295 protected Package[] getPackages()
296 {
297 return super.getPackages();
298 }
299
300 @Override
301 protected String findLibrary(String libname)
302 {
303 return super.findLibrary(libname);
304 }
305
306 @Override
307 public void setDefaultAssertionStatus(boolean enabled)
308 {
309 super.setDefaultAssertionStatus(enabled);
310 }
311
312 @Override
313 public void setPackageAssertionStatus(String packageName, boolean enabled)
314 {
315 super.setPackageAssertionStatus(packageName, enabled);
316 }
317
318 @Override
319 public void setClassAssertionStatus(String className, boolean enabled)
320 {
321 super.setClassAssertionStatus(className, enabled);
322 }
323
324 @Override
325 public void clearAssertionStatus()
326 {
327 super.clearAssertionStatus();
328 }
329 }
330
331
332
333
334
335
336
337 public static class AntServletHolder extends ServletHolder
338 {
339
340 public AntServletHolder()
341 {
342 super();
343 }
344
345
346 public AntServletHolder(Class<? extends Servlet> servlet)
347 {
348 super(servlet);
349 }
350
351
352 public AntServletHolder(Servlet servlet)
353 {
354 super(servlet);
355 }
356
357
358 public AntServletHolder(String name, Class<? extends Servlet> servlet)
359 {
360 super(name, servlet);
361 }
362
363
364 public AntServletHolder(String name, Servlet servlet)
365 {
366 super(name, servlet);
367 }
368
369 protected String getSystemClassPath (ClassLoader loader) throws Exception
370 {
371 StringBuilder classpath=new StringBuilder();
372 while (loader != null)
373 {
374 if (loader instanceof URLClassLoader)
375 {
376 URL[] urls = ((URLClassLoader)loader).getURLs();
377 if (urls != null)
378 {
379 for (int i=0;i<urls.length;i++)
380 {
381 Resource resource = Resource.newResource(urls[i]);
382 File file=resource.getFile();
383 if (file!=null && file.exists())
384 {
385 if (classpath.length()>0)
386 classpath.append(File.pathSeparatorChar);
387 classpath.append(file.getAbsolutePath());
388 }
389 }
390 }
391 }
392 else if (loader instanceof AntClassLoader)
393 {
394 classpath.append(((AntClassLoader)loader).getClasspath());
395 }
396
397 loader = loader.getParent();
398 }
399
400 return classpath.toString();
401 }
402
403 }
404
405
406
407
408
409
410
411
412 public static class AntServletHandler extends ServletHandler
413 {
414
415 @Override
416 public ServletHolder newServletHolder(Holder.Source source)
417 {
418 return new AntServletHolder();
419 }
420
421 }
422
423
424
425
426
427
428
429
430
431 public AntWebAppContext(Project project) throws Exception
432 {
433 super();
434 this.project = project;
435 setConfigurations(DEFAULT_CONFIGURATIONS);
436 setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN);
437 setParentLoaderPriority(true);
438 }
439
440
441
442
443
444
445 public void addAttributes(Attributes atts)
446 {
447 if (this.attributes != null)
448 {
449 throw new BuildException("Only one <attributes> tag is allowed!");
450 }
451
452 this.attributes = atts;
453 }
454
455
456 public void addLib(FileSet lib)
457 {
458 libraries.add(lib);
459 }
460
461
462 public void addClasses(FileSet classes)
463 {
464 this.classes.add(classes);
465 }
466
467
468
469 @Override
470 protected ServletHandler newServletHandler()
471 {
472 return new AntServletHandler();
473 }
474
475
476 public void setJettyEnvXml(File jettyEnvXml)
477 {
478 this.jettyEnvXml = jettyEnvXml;
479 TaskLog.log("jetty-env.xml file: = " + (jettyEnvXml == null ? null : jettyEnvXml.getAbsolutePath()));
480 }
481
482 public File getJettyEnvXml ()
483 {
484 return this.jettyEnvXml;
485 }
486
487
488
489
490 public List getLibraries()
491 {
492 return librariesConfiguration.getBaseDirectories();
493 }
494
495
496 public void addScanTargets(FileSet scanTargets)
497 {
498 if (this.scanTargets != null)
499 {
500 throw new BuildException("Only one <scanTargets> tag is allowed!");
501 }
502
503 this.scanTargets = scanTargets;
504 }
505
506 public List getScanTargetFiles ()
507 {
508 if (this.scanTargets == null)
509 return null;
510
511
512 FileMatchingConfiguration configuration = new FileMatchingConfiguration();
513 configuration.addDirectoryScanner(scanTargets.getDirectoryScanner(project));
514 return configuration.getBaseDirectories();
515 }
516
517 public List<File> getScanFiles()
518 {
519 if (scanFiles == null)
520 scanFiles = initScanFiles();
521 return scanFiles;
522 }
523
524
525 public boolean isScanned (File file)
526 {
527 List<File> files = getScanFiles();
528 if (files == null || files.isEmpty())
529 return false;
530 return files.contains(file);
531 }
532
533
534 public List<File> initScanFiles ()
535 {
536 List<File> scanList = new ArrayList<File>();
537
538 if (getDescriptor() != null)
539 {
540 try (Resource r = Resource.newResource(getDescriptor());)
541 {
542 scanList.add(r.getFile());
543 }
544 catch (IOException e)
545 {
546 throw new BuildException(e);
547 }
548 }
549
550 if (getJettyEnvXml() != null)
551 {
552 try (Resource r = Resource.newResource(getJettyEnvXml());)
553 {
554 scanList.add(r.getFile());
555 }
556 catch (IOException e)
557 {
558 throw new BuildException("Problem configuring scanner for jetty-env.xml", e);
559 }
560 }
561
562 if (getDefaultsDescriptor() != null)
563 {
564 try (Resource r = Resource.newResource(getDefaultsDescriptor());)
565 {
566 if (!WebAppContext.WEB_DEFAULTS_XML.equals(getDefaultsDescriptor()))
567 {
568 scanList.add(r.getFile());
569 }
570 }
571 catch (IOException e)
572 {
573 throw new BuildException("Problem configuring scanner for webdefaults.xml", e);
574 }
575 }
576
577 if (getOverrideDescriptor() != null)
578 {
579 try
580 {
581 Resource r = Resource.newResource(getOverrideDescriptor());
582 scanList.add(r.getFile());
583 }
584 catch (IOException e)
585 {
586 throw new BuildException("Problem configuring scanner for webdefaults.xml", e);
587 }
588 }
589
590
591 List<File> cpFiles = getClassPathFiles();
592 if (cpFiles != null)
593 scanList.addAll(cpFiles);
594
595
596 @SuppressWarnings("unchecked")
597 List<File> scanFiles = (List<File>)getScanTargetFiles();
598 if (scanFiles != null)
599 scanList.addAll(scanFiles);
600
601 return scanList;
602 }
603
604
605
606 @Override
607 public void setWar(String path)
608 {
609 super.setWar(path);
610
611 try
612 {
613 Resource war = Resource.newResource(path);
614 if (war.exists() && war.isDirectory() && getDescriptor() == null)
615 {
616 Resource webXml = war.addPath("WEB-INF/web.xml");
617 setDescriptor(webXml.toString());
618 }
619 }
620 catch (IOException e)
621 {
622 throw new BuildException(e);
623 }
624 }
625
626
627
628
629
630 public void doStart()
631 {
632 try
633 {
634 TaskLog.logWithTimestamp("Starting web application "+this.getDescriptor());
635 if (jettyEnvXml != null && jettyEnvXml.exists())
636 envConfiguration.setJettyEnvXml(Resource.toURL(jettyEnvXml));
637
638 ClassLoader parentLoader = this.getClass().getClassLoader();
639 if (parentLoader instanceof AntClassLoader)
640 parentLoader = new AntURLClassLoader((AntClassLoader)parentLoader);
641
642 setClassLoader(new WebAppClassLoader(parentLoader, this));
643 if (attributes != null && attributes.getAttributes() != null)
644 {
645 for (Attribute a:attributes.getAttributes())
646 setAttribute(a.getName(), a.getValue());
647 }
648
649
650 if (contextXml != null)
651 {
652 XmlConfiguration xmlConfiguration = new XmlConfiguration(Resource.toURL(contextXml));
653 TaskLog.log("Applying context xml file "+contextXml);
654 xmlConfiguration.configure(this);
655 }
656
657 super.doStart();
658 }
659 catch (Exception e)
660 {
661 TaskLog.log(e.toString());
662 }
663 }
664
665 public void doStop()
666 {
667 try
668 {
669 scanFiles = null;
670 TaskLog.logWithTimestamp("Stopping web application "+this);
671 Thread.currentThread().sleep(500L);
672 super.doStop();
673
674
675 setEventListeners(new EventListener[0]);
676 getServletHandler().setFilters(new FilterHolder[0]);
677 getServletHandler().setFilterMappings(new FilterMapping[0]);
678 getServletHandler().setServlets(new ServletHolder[0]);
679 getServletHandler().setServletMappings(new ServletMapping[0]);
680 }
681 catch (InterruptedException e)
682 {
683 TaskLog.log(e.toString());
684 }
685 catch (Exception e)
686 {
687 TaskLog.log(e.toString());
688 }
689 }
690
691
692
693
694
695
696 public List<File> getClassPathFiles()
697 {
698 List<File> classPathFiles = new ArrayList<File>();
699 Iterator classesIterator = classes.iterator();
700 while (classesIterator.hasNext())
701 {
702 FileSet clazz = (FileSet) classesIterator.next();
703 classPathFiles.add(clazz.getDirectoryScanner(project).getBasedir());
704 }
705
706 Iterator iterator = libraries.iterator();
707 while (iterator.hasNext())
708 {
709 FileSet library = (FileSet) iterator.next();
710 String[] includedFiles = library.getDirectoryScanner(project).getIncludedFiles();
711 File baseDir = library.getDirectoryScanner(project).getBasedir();
712
713 for (int i = 0; i < includedFiles.length; i++)
714 {
715 classPathFiles.add(new File(baseDir, includedFiles[i]));
716 }
717 }
718
719
720 return classPathFiles;
721 }
722
723
724
725
726
727
728
729 public FileMatchingConfiguration getLibrariesConfiguration()
730 {
731 FileMatchingConfiguration config = new FileMatchingConfiguration();
732
733 Iterator classesIterator = classes.iterator();
734 while (classesIterator.hasNext())
735 {
736 FileSet clazz = (FileSet) classesIterator.next();
737 config.addDirectoryScanner(clazz.getDirectoryScanner(project));
738 }
739
740 Iterator librariesIterator = libraries.iterator();
741 while (librariesIterator.hasNext())
742 {
743 FileSet library = (FileSet) librariesIterator.next();
744 config.addDirectoryScanner(library.getDirectoryScanner(project));
745 }
746
747 return config;
748 }
749
750
751 public File getContextXml()
752 {
753 return contextXml;
754 }
755
756
757 public void setContextXml(File contextXml)
758 {
759 this.contextXml = contextXml;
760 }
761
762 }