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