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