Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Bartel2010-07-16 07:15:13 +0000
committerJan Bartel2010-07-16 07:15:13 +0000
commit314f94decc0e814baf31f500502020e05fcb73a2 (patch)
treec2cd339dc135614dcc16c0e5a19d81352ff3ee02 /jetty-webapp
parent8210d068c43058097970fae131643df6b9d9dbdf (diff)
downloadorg.eclipse.jetty.project-314f94decc0e814baf31f500502020e05fcb73a2.tar.gz
org.eclipse.jetty.project-314f94decc0e814baf31f500502020e05fcb73a2.tar.xz
org.eclipse.jetty.project-314f94decc0e814baf31f500502020e05fcb73a2.zip
320073 Reconcile jetty-8 and jetty-7 webapp configuration mechanisms
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2145 7e9141cc-0065-0410-87d8-b60c137991c4
Diffstat (limited to 'jetty-webapp')
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DefaultsDescriptor.java29
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java290
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DescriptorProcessor.java24
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java68
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java45
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java162
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/IterativeDescriptorProcessor.java84
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java2
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java911
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/OverrideDescriptor.java29
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java1335
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/TagLibConfiguration.java3
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java13
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java2
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java88
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlProcessor.java1060
-rw-r--r--jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java939
17 files changed, 3945 insertions, 1139 deletions
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DefaultsDescriptor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DefaultsDescriptor.java
new file mode 100644
index 0000000000..e7331f6972
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DefaultsDescriptor.java
@@ -0,0 +1,29 @@
+// ========================================================================
+// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import org.eclipse.jetty.util.resource.Resource;
+
+/**
+ * DefaultsDescriptor
+ *
+ *
+ */
+public class DefaultsDescriptor extends Descriptor
+{
+ public DefaultsDescriptor(Resource xml, MetaData processor)
+ {
+ super(xml, processor);
+ }
+}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java
new file mode 100644
index 0000000000..e6aca3c819
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java
@@ -0,0 +1,290 @@
+// ========================================================================
+// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.Servlet;
+
+import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.xml.XmlParser;
+
+
+
+/**
+ * Descriptor
+ *
+ * A web descriptor (web.xml/web-defaults.xml/web-overrides.xml).
+ */
+public class Descriptor
+{
+ protected static XmlParser _parser;
+ public enum MetaDataComplete {NotSet, True, False};
+ protected Resource _xml;
+ protected XmlParser.Node _root;
+ protected MetaDataComplete _metaDataComplete;
+ protected int _majorVersion = 3; //default to container version
+ protected int _minorVersion = 0;
+ protected ArrayList<String> _classNames = new ArrayList<String>();
+ protected boolean _distributable;
+ protected boolean _validating;
+ protected MetaData _metaData;
+ protected boolean _isOrdered = false;
+ protected List<String> _ordering = new ArrayList<String>();
+
+
+
+
+ public static XmlParser newParser()
+ throws ClassNotFoundException
+ {
+ XmlParser xmlParser=new XmlParser();
+ //set up cache of DTDs and schemas locally
+ URL dtd22=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_2.dtd",true);
+ URL dtd23=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_3.dtd",true);
+ URL j2ee14xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/j2ee_1_4.xsd",true);
+ URL webapp24xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_4.xsd",true);
+ URL webapp25xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_5.xsd",true);
+ URL webapp30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_3_0.xsd",true);
+ URL webcommon30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-common_3_0.xsd",true);
+ URL webfragment30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-fragment_3_0.xsd",true);
+ URL schemadtd=Loader.getResource(Servlet.class,"javax/servlet/resources/XMLSchema.dtd",true);
+ URL xmlxsd=Loader.getResource(Servlet.class,"javax/servlet/resources/xml.xsd",true);
+ URL webservice11xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/j2ee_web_services_client_1_1.xsd",true);
+ URL webservice12xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/javaee_web_services_client_1_2.xsd",true);
+ URL datatypesdtd=Loader.getResource(Servlet.class,"javax/servlet/resources/datatypes.dtd",true);
+
+ URL jsp20xsd = null;
+ URL jsp21xsd = null;
+
+ try
+ {
+ Class jsp_page = Loader.loadClass(WebXmlConfiguration.class, "javax.servlet.jsp.JspPage");
+ jsp20xsd = jsp_page.getResource("/javax/servlet/resources/jsp_2_0.xsd");
+ jsp21xsd = jsp_page.getResource("/javax/servlet/resources/jsp_2_1.xsd");
+ }
+ catch (Exception e)
+ {
+ Log.ignore(e);
+ }
+ finally
+ {
+ if (jsp20xsd == null) jsp20xsd = Loader.getResource(Servlet.class, "javax/servlet/resources/jsp_2_0.xsd", true);
+ if (jsp21xsd == null) jsp21xsd = Loader.getResource(Servlet.class, "javax/servlet/resources/jsp_2_1.xsd", true);
+ }
+
+ redirect(xmlParser,"web-app_2_2.dtd",dtd22);
+ redirect(xmlParser,"-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",dtd22);
+ redirect(xmlParser,"web.dtd",dtd23);
+ redirect(xmlParser,"web-app_2_3.dtd",dtd23);
+ redirect(xmlParser,"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",dtd23);
+ redirect(xmlParser,"XMLSchema.dtd",schemadtd);
+ redirect(xmlParser,"http://www.w3.org/2001/XMLSchema.dtd",schemadtd);
+ redirect(xmlParser,"-//W3C//DTD XMLSCHEMA 200102//EN",schemadtd);
+ redirect(xmlParser,"jsp_2_0.xsd",jsp20xsd);
+ redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/jsp_2_0.xsd",jsp20xsd);
+ redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/jsp_2_1.xsd",jsp21xsd);
+ redirect(xmlParser,"j2ee_1_4.xsd",j2ee14xsd);
+ redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/j2ee_1_4.xsd",j2ee14xsd);
+ redirect(xmlParser,"web-app_2_4.xsd",webapp24xsd);
+ redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd",webapp24xsd);
+ redirect(xmlParser,"web-app_2_5.xsd",webapp25xsd);
+ redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd",webapp25xsd);
+ redirect(xmlParser,"web-app_3_0.xsd",webapp30xsd);
+ redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd",webapp30xsd);
+ redirect(xmlParser,"web-common_3_0.xsd",webcommon30xsd);
+ redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-common_3_0.xsd",webcommon30xsd);
+ redirect(xmlParser,"web-fragment_3_0.xsd",webfragment30xsd);
+ redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd",webfragment30xsd);
+ redirect(xmlParser,"xml.xsd",xmlxsd);
+ redirect(xmlParser,"http://www.w3.org/2001/xml.xsd",xmlxsd);
+ redirect(xmlParser,"datatypes.dtd",datatypesdtd);
+ redirect(xmlParser,"http://www.w3.org/2001/datatypes.dtd",datatypesdtd);
+ redirect(xmlParser,"j2ee_web_services_client_1_1.xsd",webservice11xsd);
+ redirect(xmlParser,"http://www.ibm.com/webservices/xsd/j2ee_web_services_client_1_1.xsd",webservice11xsd);
+ redirect(xmlParser,"javaee_web_services_client_1_2.xsd",webservice12xsd);
+ redirect(xmlParser,"http://www.ibm.com/webservices/xsd/javaee_web_services_client_1_2.xsd",webservice12xsd);
+ return xmlParser;
+ }
+
+
+ protected static void redirect(XmlParser parser, String resource, URL source)
+ {
+ if (source != null) parser.redirectEntity(resource, source);
+ }
+
+
+
+ public Descriptor (Resource xml, MetaData md)
+ {
+ _xml = xml;
+ _metaData = md;
+ }
+
+ public void parse ()
+ throws Exception
+ {
+ if (_parser == null)
+ _parser = newParser();
+
+ if (_root == null)
+ {
+ //boolean oldValidating = _processor.getParser().getValidating();
+ //_processor.getParser().setValidating(_validating);
+ _root = _parser.parse(_xml.getURL().toString());
+ processVersion();
+ processOrdering();
+ //_processor.getParser().setValidating(oldValidating);
+ }
+ }
+
+ public MetaDataComplete getMetaDataComplete()
+ {
+ return _metaDataComplete;
+ }
+
+
+ public XmlParser.Node getRoot ()
+ {
+ return _root;
+ }
+
+ public int getMajorVersion ()
+ {
+ return _majorVersion;
+ }
+
+ public int getMinorVersion()
+ {
+ return _minorVersion;
+ }
+
+ public Resource getResource ()
+ {
+ return _xml;
+ }
+
+ public MetaData getMetaData()
+ {
+ return _metaData;
+ }
+
+ public void processVersion ()
+ {
+ String version = _root.getAttribute("version", "DTD");
+ if ("DTD".equals(version))
+ {
+ _majorVersion = 2;
+ _minorVersion = 3;
+ String dtd = _parser.getDTD();
+ if (dtd != null && dtd.indexOf("web-app_2_2") >= 0)
+ {
+ _majorVersion = 2;
+ _minorVersion = 2;
+ }
+ }
+ else
+ {
+ int dot = version.indexOf(".");
+ if (dot > 0)
+ {
+ _majorVersion = Integer.parseInt(version.substring(0,dot));
+ _minorVersion = Integer.parseInt(version.substring(dot+1));
+ }
+ }
+
+ if (_majorVersion < 2 && _minorVersion < 5)
+ _metaDataComplete = MetaDataComplete.True; // does not apply before 2.5
+ else
+ {
+ String s = (String)_root.getAttribute("metadata-complete");
+ if (s == null)
+ _metaDataComplete = MetaDataComplete.NotSet;
+ else
+ _metaDataComplete = Boolean.valueOf(s).booleanValue()?MetaDataComplete.True:MetaDataComplete.False;
+ }
+
+ Log.debug(_xml.toString()+": Calculated metadatacomplete = " + _metaDataComplete + " with version=" + version);
+ }
+
+ public void processOrdering ()
+ {
+ //Process the web.xml's optional <absolute-ordering> element
+ XmlParser.Node ordering = _root.get("absolute-ordering");
+ if (ordering == null)
+ return;
+
+ _isOrdered = true;
+ //If an absolute-ordering was already set, then ignore it in favour of this new one
+ // _processor.setOrdering(new AbsoluteOrdering());
+
+ Iterator iter = ordering.iterator();
+ XmlParser.Node node = null;
+ while (iter.hasNext())
+ {
+ Object o = iter.next();
+ if (!(o instanceof XmlParser.Node)) continue;
+ node = (XmlParser.Node) o;
+
+ if (node.getTag().equalsIgnoreCase("others"))
+ //((AbsoluteOrdering)_processor.getOrdering()).addOthers();
+ _ordering.add("others");
+ else if (node.getTag().equalsIgnoreCase("name"))
+ //((AbsoluteOrdering)_processor.getOrdering()).add(node.toString(false,true));
+ _ordering.add(node.toString(false,true));
+ }
+ }
+
+ public void addClassName (String className)
+ {
+ if (!_classNames.contains(className))
+ _classNames.add(className);
+ }
+
+ public ArrayList<String> getClassNames ()
+ {
+ return _classNames;
+ }
+
+ public void setDistributable (boolean distributable)
+ {
+ _distributable = distributable;
+ }
+
+ public boolean isDistributable()
+ {
+ return _distributable;
+ }
+
+ public void setValidating (boolean validating)
+ {
+ _validating = validating;
+ }
+
+
+ public boolean isOrdered()
+ {
+ return _isOrdered;
+ }
+
+ public List<String> getOrdering()
+ {
+ return _ordering;
+ }
+}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DescriptorProcessor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DescriptorProcessor.java
new file mode 100644
index 0000000000..88a0e143d5
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DescriptorProcessor.java
@@ -0,0 +1,24 @@
+// ========================================================================
+// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+/**
+ * DescriptorProcessor
+ *
+ *
+ */
+public interface DescriptorProcessor
+{
+ public void process (Descriptor descriptor) throws Exception;
+}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java
new file mode 100644
index 0000000000..2e1a1535b1
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java
@@ -0,0 +1,68 @@
+// ========================================================================
+// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.log.Log;
+
+/**
+ * DiscoveredAnnotation
+ *
+ * Represents an annotation that has been discovered
+ * by scanning source code of WEB-INF/classes and WEB-INF/lib jars.
+ *
+ */
+public abstract class DiscoveredAnnotation
+{
+ protected WebAppContext _context;
+ protected String _className;
+ protected Class _clazz;
+
+ public abstract void apply();
+
+ public DiscoveredAnnotation (WebAppContext context, String className)
+ {
+ _context = context;
+ _className = className;
+ }
+
+
+ public Class getTargetClass()
+ {
+ if (_clazz != null)
+ return _clazz;
+
+ loadClass();
+
+ return _clazz;
+ }
+
+ private void loadClass ()
+ {
+ if (_clazz != null)
+ return;
+
+ if (_className == null)
+ return;
+
+ try
+ {
+ _clazz = Loader.loadClass(null, _className);
+ }
+ catch (Exception e)
+ {
+ Log.warn(e);
+ }
+ }
+}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java
index 47a2d9f81c..4828738c94 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java
@@ -21,7 +21,7 @@ import org.eclipse.jetty.util.resource.Resource;
/**
* FragmentConfiguration
*
- * This configuration supports some Servlet 3.0 features in jetty-7.
+ *
*
* Process web-fragments in jars
*/
@@ -33,20 +33,14 @@ public class FragmentConfiguration implements Configuration
{
if (!context.isConfigurationDiscovered())
return;
+
+ MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
+ if (metaData == null)
+ throw new IllegalStateException("No metadata");
+
+ //find all web-fragment.xmls
+ findWebFragments(context, metaData);
- WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
- if (processor == null)
- {
- processor = new WebXmlProcessor (context);
- context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
- }
-
-
- //parse web-fragment.xmls
- parseWebFragments(context, processor);
-
- //TODO for jetty-8/servletspec 3 we will need to merge the parsed web fragments into the
- //effective pom in this preConfigure step
}
public void configure(WebAppContext context) throws Exception
@@ -54,16 +48,12 @@ public class FragmentConfiguration implements Configuration
if (!context.isConfigurationDiscovered())
return;
- //TODO for jetty-8/servletspec3 the fragments will not be separately processed here, but
- //will be done by webXmlConfiguration when it processes the effective merged web.xml
- WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
- if (processor == null)
- {
- processor = new WebXmlProcessor (context);
- context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
- }
-
- processor.processFragments();
+ MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
+ if (metaData == null)
+ throw new IllegalStateException("No metadata");
+
+ //order the fragments
+ metaData.orderFragments();
}
public void deconfigure(WebAppContext context) throws Exception
@@ -78,20 +68,19 @@ public class FragmentConfiguration implements Configuration
/* ------------------------------------------------------------------------------- */
/**
- * Look for any web.xml fragments in META-INF of jars in WEB-INF/lib
+ * Look for any web-fragment.xml fragments in META-INF of jars in WEB-INF/lib
*
* @throws Exception
*/
- public void parseWebFragments (final WebAppContext context, final WebXmlProcessor processor) throws Exception
+ public void findWebFragments (final WebAppContext context, final MetaData metaData) throws Exception
{
List<Resource> frags = (List<Resource>)context.getAttribute(FRAGMENT_RESOURCES);
if (frags!=null)
{
for (Resource frag : frags)
{
- processor.parseFragment(Resource.newResource("jar:"+frag.getURL()+"!/META-INF/web-fragment.xml"));
+ metaData.addFragment(frag, Resource.newResource("jar:"+frag.getURL()+"!/META-INF/web-fragment.xml"));
}
}
}
-
}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java
new file mode 100644
index 0000000000..75c36de57a
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java
@@ -0,0 +1,162 @@
+// ========================================================================
+// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.xml.XmlParser;
+
+
+/**
+ * Fragment
+ *
+ * A web-fragment.xml descriptor.
+ */
+public class FragmentDescriptor extends Descriptor
+{
+ public static final String NAMELESS = "@@-NAMELESS-@@"; //prefix for nameless Fragments
+ public enum OtherType {None, Before, After};
+
+ protected int _counter = 0;
+ protected OtherType _otherType = OtherType.None;
+
+
+ protected List<String> _befores = new ArrayList<String>();
+ protected List<String> _afters = new ArrayList<String>();
+ protected String _name;
+
+
+ public FragmentDescriptor (Resource xml, MetaData processor)
+ throws Exception
+ {
+ super (xml, processor);
+ }
+
+ public String getName ()
+ {
+ return _name;
+ }
+
+ public void parse ()
+ throws Exception
+ {
+ super.parse();
+ processName();
+ }
+
+ public void processName ()
+ {
+ XmlParser.Node root = getRoot();
+ XmlParser.Node nameNode = root.get("name");
+ _name = NAMELESS+(_counter++);
+ if (nameNode != null)
+ {
+ String tmp = nameNode.toString(false,true);
+ if (tmp!=null && tmp.length()>0)
+ _name = tmp;
+ }
+ }
+ public void processOrdering ()
+ {
+ //Process a fragment jar's web-fragment.xml<ordering> elements
+ XmlParser.Node root = getRoot();
+
+ XmlParser.Node ordering = root.get("ordering");
+ if (ordering == null)
+ return; //No ordering for this fragment
+
+ _isOrdered = true;
+
+ processBefores(ordering);
+ processAfters(ordering);
+ }
+
+
+ public void processBefores (XmlParser.Node ordering)
+ {
+ //Process the <before> elements, looking for an <others/> clause and all of the <name> clauses
+ XmlParser.Node before = ordering.get("before");
+ if (before == null)
+ return;
+
+ Iterator iter = before.iterator();
+ XmlParser.Node node = null;
+ while (iter.hasNext())
+ {
+ Object o = iter.next();
+ if (!(o instanceof XmlParser.Node)) continue;
+ node = (XmlParser.Node) o;
+ if (node.getTag().equalsIgnoreCase("others"))
+ {
+ if (_otherType != OtherType.None)
+ throw new IllegalStateException("Duplicate <other> clause detected in "+_xml.getURI());
+
+ _otherType = OtherType.Before;
+ }
+ else if (node.getTag().equalsIgnoreCase("name"))
+ _befores.add(node.toString(false,true));
+ }
+ }
+
+ public void processAfters (XmlParser.Node ordering)
+ {
+ //Process the <after> elements, look for an <others/> clause and all of the <name/> clauses
+ XmlParser.Node after = ordering.get("after");
+ if (after == null)
+ return;
+
+ Iterator iter = after.iterator();
+ XmlParser.Node node = null;
+ while (iter.hasNext())
+ {
+ Object o = iter.next();
+ if (!(o instanceof XmlParser.Node)) continue;
+ node = (XmlParser.Node) o;
+ if (node.getTag().equalsIgnoreCase("others"))
+ {
+ if (_otherType != OtherType.After)
+ throw new IllegalStateException("Duplicate <other> clause detected in "+_xml.getURI());
+
+ _otherType = OtherType.After;
+
+ }
+ else if (node.getTag().equalsIgnoreCase("name"))
+ _afters.add(node.toString(false,true));
+ }
+ }
+
+ public List<String> getBefores()
+ {
+ return Collections.unmodifiableList(_befores);
+ }
+
+ public List<String> getAfters()
+ {
+ return Collections.unmodifiableList(_afters);
+ }
+
+ public OtherType getOtherType ()
+ {
+ return _otherType;
+ }
+
+ public List<String> getOrdering()
+ {
+ return null; //only used for absolute-ordering in Descriptor
+ }
+} \ No newline at end of file
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/IterativeDescriptorProcessor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/IterativeDescriptorProcessor.java
new file mode 100644
index 0000000000..fd1507649e
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/IterativeDescriptorProcessor.java
@@ -0,0 +1,84 @@
+// ========================================================================
+// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jetty.xml.XmlParser;
+
+/**
+ * IterativeDescriptorProcessor
+ *
+ *
+ */
+public abstract class IterativeDescriptorProcessor implements DescriptorProcessor
+{
+ public static final Class[] __signature = new Class[]{Descriptor.class, XmlParser.Node.class};
+ protected Map<String, Method> _visitors = new HashMap<String, Method>();
+ public abstract void start(Descriptor descriptor);
+ public abstract void end(Descriptor descriptor);
+
+ /**
+ * Register a method to be called back when visiting the node with the given name.
+ * The method must exist on a subclass of this class, and must have the signature:
+ * public void method (Descriptor descriptor, XmlParser.Node node)
+ * @param nodeName
+ * @param m
+ */
+ public void registerVisitor(String nodeName, Method m)
+ {
+ _visitors.put(nodeName, m);
+ }
+
+
+ /**
+ * @see org.eclipse.jetty.webapp.DescriptorProcessor#process(org.eclipse.jetty.webapp.Descriptor)
+ */
+ public void process(Descriptor descriptor)
+ throws Exception
+ {
+ if (descriptor == null)
+ return;
+
+ start(descriptor);
+
+ XmlParser.Node root = descriptor.getRoot();
+ Iterator iter = root.iterator();
+ XmlParser.Node node = null;
+ while (iter.hasNext())
+ {
+ Object o = iter.next();
+ if (!(o instanceof XmlParser.Node)) continue;
+ node = (XmlParser.Node) o;
+ visit(descriptor, node);
+ }
+
+ end(descriptor);
+ }
+
+
+ protected void visit (final Descriptor descriptor, final XmlParser.Node node)
+ throws Exception
+ {
+ String name = node.getTag();
+ Method m = _visitors.get(name);
+ if (m != null)
+ m.invoke(this, new Object[]{descriptor, node});
+ }
+}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java
index 27aa287e17..10bcfad5a9 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java
@@ -25,7 +25,7 @@ import org.eclipse.jetty.xml.XmlConfiguration;
*
* JettyWebConfiguration.
*
- * Looks for Xmlconfiguration files in WEB-INF. Searches in order for the first of jetty6-web.xml, jetty-web.xml or web-jetty.xml
+ * Looks for Xmlconfiguration files in WEB-INF. Searches in order for the first of jettyX-web.xml, jetty-web.xml or web-jetty.xml
*
*
*
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java
new file mode 100644
index 0000000000..b240b190d7
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java
@@ -0,0 +1,911 @@
+// ========================================================================
+// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import org.eclipse.jetty.util.resource.Resource;
+
+
+
+
+
+/**
+ * MetaData
+ *
+ *
+ */
+public class MetaData
+{
+ public static final String METADATA = "org.eclipse.jetty.metaData";
+ public static final String METADATA_COMPLETE = "org.eclipse.jetty.metadataComplete";
+ public static final String WEBXML_MAJOR_VERSION = "org.eclipse.jetty.webXmlMajorVersion";
+ public static final String WEBXML_MINOR_VERSION = "org.eclipse.jetty.webXmlMinorVersion";
+ public static final String WEBXML_CLASSNAMES = "org.eclipse.jetty.webXmlClassNames";
+ public static final String ORDERED_LIBS = "javax.servlet.context.orderedLibs";
+
+ public enum Origin {NotSet, WebXml, WebDefaults, WebOverride, WebFragment, Annotation};
+
+ protected WebAppContext _context;
+ protected Map<String, OriginInfo> _origins = new HashMap<String,OriginInfo>();
+ protected Descriptor _webDefaultsRoot;
+ protected Descriptor _webXmlRoot;
+ protected Descriptor _webOverrideRoot;
+ protected List<DiscoveredAnnotation> _annotations = new ArrayList<DiscoveredAnnotation>();
+ protected List<DescriptorProcessor> _descriptorProcessors = new ArrayList<DescriptorProcessor>();
+ protected List<FragmentDescriptor> _webFragmentRoots = new ArrayList<FragmentDescriptor>();
+ protected Map<String,FragmentDescriptor> _webFragmentNameMap = new HashMap<String,FragmentDescriptor>();
+ protected Map<Resource, FragmentDescriptor> _webFragmentResourceMap = new HashMap<Resource, FragmentDescriptor>();
+ protected Map<Resource, List<DiscoveredAnnotation>> _webFragmentAnnotations = new HashMap<Resource, List<DiscoveredAnnotation>>();
+ protected List<Resource> _orderedResources;
+ protected Ordering _ordering;//can be set to RelativeOrdering by web-default.xml, web.xml, web-override.xml
+ protected StandardDescriptorProcessor _standardDescriptorProcessor;
+
+
+ public static class OriginInfo
+ {
+ protected String name;
+ protected Origin origin;
+ protected Descriptor descriptor;
+
+ public OriginInfo (String n, Descriptor d)
+ {
+ name = n;
+ descriptor = d;
+ if (d == null)
+ throw new IllegalArgumentException("No descriptor");
+ if (d instanceof FragmentDescriptor)
+ origin = Origin.WebFragment;
+ if (d instanceof OverrideDescriptor)
+ origin = Origin.WebOverride;
+ if (d instanceof DefaultsDescriptor)
+ origin = Origin.WebDefaults;
+ origin = Origin.WebXml;
+ }
+
+ public OriginInfo (String n)
+ {
+ name = n;
+ origin = Origin.Annotation;
+ }
+
+ public OriginInfo(String n, Origin o)
+ {
+ name = n;
+ origin = o;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public Origin getOriginType()
+ {
+ return origin;
+ }
+
+ public Descriptor getDescriptor()
+ {
+ return descriptor;
+ }
+ }
+
+ /**
+ * Ordering
+ *
+ *
+ */
+ public interface Ordering
+ {
+ public List<Resource> order(List<Resource> fragments);
+ public boolean isAbsolute ();
+ public boolean hasOther();
+ }
+
+ /**
+ * AbsoluteOrdering
+ *
+ * An <absolute-order> element in web.xml
+ */
+ public class AbsoluteOrdering implements Ordering
+ {
+ public static final String OTHER = "@@-OTHER-@@";
+ protected List<String> _order = new ArrayList<String>();
+ protected boolean _hasOther = false;
+
+ /**
+ * Order the list of jars in WEB-INF/lib according to the ordering declarations in the descriptors
+ * @see org.eclipse.jetty.webapp.MetaData.Ordering#order(java.util.List)
+ */
+ public List<Resource> order(List<Resource> jars)
+ {
+ List<Resource> orderedList = new ArrayList<Resource>();
+ List<Resource> tmp = new ArrayList<Resource>(jars);
+
+ //1. put everything into the list of named others, and take the named ones out of there,
+ //assuming we will want to use the <other> clause
+ Map<String,FragmentDescriptor> others = new HashMap(getNamedFragments());
+
+ //2. for each name, take out of the list of others, add to tail of list
+ int index = -1;
+ for (String item:_order)
+ {
+ if (!item.equals(OTHER))
+ {
+ FragmentDescriptor f = others.remove(item);
+ if (f != null)
+ {
+ Resource jar = getJarForFragment(item);
+ orderedList.add(jar); //take from others and put into final list in order, ignoring duplicate names
+ //remove resource from list for resource matching name of descriptor
+ tmp.remove(jar);
+ }
+ }
+ else
+ index = orderedList.size(); //remember the index at which we want to add in all the others
+ }
+
+ //3. if <other> was specified, insert rest of the fragments
+ if (_hasOther)
+ {
+ orderedList.addAll((index < 0? 0: index), tmp);
+ }
+
+ return orderedList;
+ }
+
+ public boolean isAbsolute()
+ {
+ return true;
+ }
+
+ public void add (String name)
+ {
+ _order.add(name);
+ }
+
+ public void addOthers ()
+ {
+ if (_hasOther)
+ throw new IllegalStateException ("Duplicate <other> element in absolute ordering");
+
+ _hasOther = true;
+ _order.add(OTHER);
+ }
+
+ public boolean hasOther ()
+ {
+ return _hasOther;
+ }
+ }
+
+
+ /**
+ * RelativeOrdering
+ *
+ * A set of <order> elements in web-fragment.xmls.
+ */
+ public class RelativeOrdering implements Ordering
+ {
+ protected LinkedList<Resource> _beforeOthers = new LinkedList<Resource>();
+ protected LinkedList<Resource> _afterOthers = new LinkedList<Resource>();
+ protected LinkedList<Resource> _noOthers = new LinkedList<Resource>();
+
+ /**
+ * Order the list of jars according to the ordering declared
+ * in the various web-fragment.xml files.
+ * @see org.eclipse.jetty.webapp.MetaData.Ordering#order(java.util.List)
+ */
+ public List<Resource> order(List<Resource> jars)
+ {
+ //for each jar, put it into the ordering according to the fragment ordering
+ for (Resource jar:jars)
+ {
+ //check if the jar has a fragment descriptor
+ FragmentDescriptor descriptor = _webFragmentResourceMap.get(jar);
+ if (descriptor != null)
+ {
+ switch (descriptor.getOtherType())
+ {
+ case None:
+ {
+ ((RelativeOrdering)_ordering).addNoOthers(jar);
+ break;
+ }
+ case Before:
+ {
+ ((RelativeOrdering)_ordering).addBeforeOthers(jar);
+ break;
+ }
+ case After:
+ {
+ ((RelativeOrdering)_ordering).addAfterOthers(jar);
+ break;
+ }
+ }
+ }
+ else
+ {
+ //jar fragment has no descriptor, but there is a relative ordering in place, so it must be part of the others
+ ((RelativeOrdering)_ordering).addNoOthers(jar);
+ }
+ }
+
+ //now apply the ordering
+ List<Resource> orderedList = new ArrayList<Resource>();
+ int maxIterations = 2;
+ boolean done = false;
+ do
+ {
+ //1. order the before-others according to any explicit before/after relationships
+ boolean changesBefore = orderList(_beforeOthers);
+
+ //2. order the after-others according to any explicit before/after relationships
+ boolean changesAfter = orderList(_afterOthers);
+
+ //3. order the no-others according to their explicit before/after relationships
+ boolean changesNone = orderList(_noOthers);
+
+ //we're finished on a clean pass through with no ordering changes
+ done = (!changesBefore && !changesAfter && !changesNone);
+ }
+ while (!done && (--maxIterations >0));
+
+ //4. merge before-others + no-others +after-others
+ if (!done)
+ throw new IllegalStateException("Circular references for fragments");
+
+ for (Resource r: _beforeOthers)
+ orderedList.add(r);
+ for (Resource r: _noOthers)
+ orderedList.add(r);
+ for(Resource r: _afterOthers)
+ orderedList.add(r);
+
+ return orderedList;
+ }
+
+ public boolean isAbsolute ()
+ {
+ return false;
+ }
+
+ public boolean hasOther ()
+ {
+ return !_beforeOthers.isEmpty() || !_afterOthers.isEmpty();
+ }
+
+ public void addBeforeOthers (Resource r)
+ {
+ _beforeOthers.addLast(r);
+ }
+
+ public void addAfterOthers (Resource r)
+ {
+ _afterOthers.addLast(r);
+ }
+
+ public void addNoOthers (Resource r)
+ {
+ _noOthers.addLast(r);
+ }
+
+ protected boolean orderList (LinkedList<Resource> list)
+ {
+ //Take a copy of the list so we can iterate over it and at the same time do random insertions
+ boolean changes = false;
+ List<Resource> iterable = new ArrayList(list);
+ Iterator<Resource> itor = iterable.iterator();
+
+ while (itor.hasNext())
+ {
+ Resource r = itor.next();
+ FragmentDescriptor f = getFragment(r);
+ if (f == null)
+ {
+ //no fragment for this resource so cannot have any ordering directives
+ continue;
+ }
+
+ //Handle any explicit <before> relationships for the fragment we're considering
+ List<String> befores = f.getBefores();
+ if (befores != null && !befores.isEmpty())
+ {
+ for (String b: befores)
+ {
+ //Fragment we're considering must be before b
+ //Check that we are already before it, if not, move us so that we are.
+ //If the name does not exist in our list, then get it out of the no-other list
+ if (!isBefore(list, f.getName(), b))
+ {
+ //b is not already before name, move it so that it is
+ int idx1 = getIndexOf(list, f.getName());
+ int idx2 = getIndexOf(list, b);
+
+ //if b is not in the same list
+ if (idx2 < 0)
+ {
+ changes = true;
+ // must be in the noOthers list or it would have been an error
+ Resource bResource = getJarForFragment(b);
+ if (bResource != null)
+ {
+ //If its in the no-others list, insert into this list so that we are before it
+ if (_noOthers.remove(bResource))
+ {
+ insert(list, idx1+1, b);
+
+ }
+ }
+ }
+ else
+ {
+ //b is in the same list but b is before name, so swap it around
+ list.remove(idx1);
+ insert(list, idx2, f.getName());
+ changes = true;
+ }
+ }
+ }
+ }
+
+ //Handle any explicit <after> relationships
+ List<String> afters = f.getAfters();
+ if (afters != null && !afters.isEmpty())
+ {
+ for (String a: afters)
+ {
+ //Check that fragment we're considering is after a, moving it if possible if its not
+ if (!isAfter(list, f.getName(), a))
+ {
+ //name is not after a, move it
+ int idx1 = getIndexOf(list, f.getName());
+ int idx2 = getIndexOf(list, a);
+
+ //if a is not in the same list as name
+ if (idx2 < 0)
+ {
+ changes = true;
+ //take it out of the noOthers list and put it in the right place in this list
+ Resource aResource = getJarForFragment(a);
+ if (aResource != null)
+ {
+ if (_noOthers.remove(aResource))
+ {
+ insert(list,idx1, aResource);
+ }
+ }
+ }
+ else
+ {
+ //a is in the same list as name, but in the wrong place, so move it
+ list.remove(idx2);
+ insert(list,idx1, a);
+ changes = true;
+ }
+ }
+ //Name we're considering must be after this name
+ //Check we're already after it, if not, move us so that we are.
+ //If the name does not exist in our list, then get it out of the no-other list
+ }
+ }
+ }
+
+ return changes;
+ }
+
+ /**
+ * Is fragment with name a before fragment with name b?
+ * @param list
+ * @param fragNameA
+ * @param fragNameB
+ * @return
+ */
+ protected boolean isBefore (List<Resource> list, String fragNameA, String fragNameB)
+ {
+ //check if a and b are already in the same list, and b is already
+ //before a
+ int idxa = getIndexOf(list, fragNameA);
+ int idxb = getIndexOf(list, fragNameB);
+
+
+ if (idxb >=0 && idxb < idxa)
+ {
+ //a and b are in the same list but a is not before b
+ return false;
+ }
+
+ if (idxb < 0)
+ {
+ //a and b are not in the same list, but it is still possible that a is before
+ //b, depending on which list we're examining
+ if (list == _beforeOthers)
+ {
+ //The list we're looking at is the beforeOthers.If b is in the _afterOthers or the _noOthers, then by
+ //definition a is before it
+ return true;
+ }
+ else if (list == _afterOthers)
+ {
+ //The list we're looking at is the afterOthers, then a will be the tail of
+ //the final list. If b is in the beforeOthers list, then b will be before a and an error.
+ if (_beforeOthers.contains(fragNameB))
+ throw new IllegalStateException("Incorrect relationship: "+fragNameA+" before "+fragNameB);
+ else
+ return false; //b could be moved to the list
+ }
+ }
+
+ //a and b are in the same list and a is already before b
+ return true;
+ }
+
+
+ /**
+ * Is fragment name "a" after fragment name "b"?
+ * @param list
+ * @param fragNameA
+ * @param fragNameB
+ * @return
+ */
+ protected boolean isAfter(List<Resource> list, String fragNameA, String fragNameB)
+ {
+ int idxa = getIndexOf(list, fragNameA);
+ int idxb = getIndexOf(list, fragNameB);
+
+ if (idxb >=0 && idxa < idxb)
+ {
+ //a and b are both in the same list, but a is before b
+ return false;
+ }
+
+ if (idxb < 0)
+ {
+ //a and b are in different lists. a could still be after b depending on which list it is in.
+
+ if (list == _afterOthers)
+ {
+ //The list we're looking at is the afterOthers. If b is in the beforeOthers or noOthers then
+ //by definition a is after b because a is in the afterOthers list.
+ return true;
+ }
+ else if (list == _beforeOthers)
+ {
+ //The list we're looking at is beforeOthers, and contains a and will be before
+ //everything else in the final ist. If b is in the afterOthers list, then a cannot be before b.
+ if (_afterOthers.contains(fragNameB))
+ throw new IllegalStateException("Incorrect relationship: "+fragNameB+" after "+fragNameA);
+ else
+ return false; //b could be moved from noOthers list
+ }
+ }
+
+ return true; //a and b in the same list, a is after b
+ }
+
+ /**
+ * Insert the resource matching the fragName into the list of resources
+ * at the location indicated by index.
+ *
+ * @param list
+ * @param index
+ * @param fragName
+ */
+ protected void insert(List<Resource> list, int index, String fragName)
+ {
+ Resource jar = getJarForFragment(fragName);
+ if (jar == null)
+ throw new IllegalStateException("No jar for insertion");
+
+ insert(list, index, jar);
+ }
+
+ protected void insert(List<Resource> list, int index, Resource resource)
+ {
+ if (list == null)
+ throw new IllegalStateException("List is null for insertion");
+
+ //add it at the end
+ if (index > list.size())
+ list.add(resource);
+ else
+ list.add(index, resource);
+ }
+
+ protected void remove (List<Resource> resources, Resource r)
+ {
+ if (resources == null)
+ return;
+ resources.remove(r);
+ }
+
+ protected int getIndexOf(List<Resource> resources, String fragmentName)
+ {
+ FragmentDescriptor fd = getFragment(fragmentName);
+ if (fd == null)
+ return -1;
+
+
+ Resource r = getJarForFragment(fragmentName);
+ if (r == null)
+ return -1;
+
+ return resources.indexOf(r);
+ }
+ }
+
+
+
+ public MetaData (WebAppContext context) throws ClassNotFoundException
+ {
+ _context = context;
+
+ }
+
+ public WebAppContext getContext()
+ {
+ return _context;
+ }
+
+
+
+ public void setDefaults (Resource webDefaults)
+ throws Exception
+ {
+ _webDefaultsRoot = new DefaultsDescriptor(webDefaults, this);
+ _webDefaultsRoot.parse();
+ if (_webDefaultsRoot.isOrdered())
+ {
+ if (_ordering == null)
+ _ordering = new AbsoluteOrdering();
+
+ List<String> order = _webDefaultsRoot.getOrdering();
+ for (String s:order)
+ {
+ if (s.equalsIgnoreCase("others"))
+ ((AbsoluteOrdering)_ordering).addOthers();
+ else
+ ((AbsoluteOrdering)_ordering).add(s);
+ }
+ }
+ }
+
+ public void setWebXml (Resource webXml)
+ throws Exception
+ {
+ _webXmlRoot = new Descriptor(webXml, this);
+ _webXmlRoot.parse();
+ if (_webXmlRoot.getMetaDataComplete() == Descriptor.MetaDataComplete.True)
+ _context.setAttribute(METADATA_COMPLETE, Boolean.TRUE);
+ else
+ _context.setAttribute(METADATA_COMPLETE, Boolean.FALSE);
+
+ _context.setAttribute(WEBXML_CLASSNAMES, _webXmlRoot.getClassNames());
+
+ if (_webXmlRoot.isOrdered())
+ {
+ if (_ordering == null)
+ _ordering = new AbsoluteOrdering();
+
+ List<String> order = _webXmlRoot.getOrdering();
+ for (String s:order)
+ {
+ if (s.equalsIgnoreCase("others"))
+ ((AbsoluteOrdering)_ordering).addOthers();
+ else
+ ((AbsoluteOrdering)_ordering).add(s);
+ }
+ }
+ }
+
+ public void setOverride (Resource override)
+ throws Exception
+ {
+ _webOverrideRoot = new OverrideDescriptor(override, this);
+ _webOverrideRoot.setValidating(false);
+ _webOverrideRoot.parse();
+ if (_webOverrideRoot.getMetaDataComplete() == Descriptor.MetaDataComplete.True)
+ _context.setAttribute(METADATA_COMPLETE, Boolean.TRUE);
+ else if (_webOverrideRoot.getMetaDataComplete() == Descriptor.MetaDataComplete.False)
+ _context.setAttribute(METADATA_COMPLETE, Boolean.FALSE);
+
+ if (_webOverrideRoot.isOrdered())
+ {
+ if (_ordering == null)
+ _ordering = new AbsoluteOrdering();
+
+ List<String> order = _webOverrideRoot.getOrdering();
+ for (String s:order)
+ {
+ if (s.equalsIgnoreCase("others"))
+ ((AbsoluteOrdering)_ordering).addOthers();
+ else
+ ((AbsoluteOrdering)_ordering).add(s);
+ }
+ }
+ }
+
+
+ /**
+ * Add a web-fragment.xml
+ *
+ * @param jarResource the jar the fragment is contained in
+ * @param xmlResource the resource representing the xml file
+ * @throws Exception
+ */
+ public void addFragment (Resource jarResource, Resource xmlResource)
+ throws Exception
+ {
+ Boolean metaComplete = (Boolean)_context.getAttribute(METADATA_COMPLETE);
+ if (metaComplete != null && metaComplete.booleanValue())
+ return; //do not process anything else if web.xml/web-override.xml set metadata-complete
+
+ //Metadata-complete is not set, or there is no web.xml
+ FragmentDescriptor descriptor = new FragmentDescriptor(xmlResource, this);
+ _webFragmentResourceMap.put(jarResource, descriptor);
+ _webFragmentRoots.add(descriptor);
+
+ descriptor.parse();
+
+ if (descriptor.getName() != null)
+ _webFragmentNameMap.put(descriptor.getName(), descriptor);
+
+ //If web.xml has specified an absolute ordering, ignore any relative ordering in the fragment
+ if (_ordering != null && _ordering.isAbsolute())
+ return;
+
+ if (_ordering == null && descriptor.isOrdered())
+ _ordering = new RelativeOrdering();
+ }
+
+ /**
+ * Annotations not associated with a WEB-INF/lib fragment jar.
+ * These are from WEB-INF/classes or the ??container path??
+ * @param annotations
+ */
+ public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations)
+ {
+ _annotations.addAll(annotations);
+ }
+
+ public void addDiscoveredAnnotations(Resource resource, List<DiscoveredAnnotation> annotations)
+ {
+ _webFragmentAnnotations.put(resource, new ArrayList<DiscoveredAnnotation>(annotations));
+ }
+
+ public void addDescriptorProcessor(DescriptorProcessor p)
+ {
+ _descriptorProcessors.add(p);
+ }
+
+ public void orderFragments ()
+ {
+ //if we have already ordered them don't do it again
+ if (_orderedResources != null)
+ return;
+
+ if (_ordering != null)
+ {
+ //Get the jars in WEB-INF/lib according to the order specified
+ _orderedResources = _ordering.order((List<Resource>)_context.getAttribute(WebInfConfiguration.WEB_INF_JAR_RESOURCES));
+
+ _context.setAttribute(WebInfConfiguration.WEB_INF_ORDERED_JAR_RESOURCES, _orderedResources);
+ List<String> orderedJars = new ArrayList<String>();
+
+ for (Resource webInfJar:_orderedResources)
+ {
+ //get just the name of the jar file
+ String fullname = webInfJar.getName();
+ int i = fullname.indexOf(".jar");
+ int j = fullname.lastIndexOf("/", i);
+ orderedJars.add(fullname.substring(j+1,i+4));
+ }
+
+ _context.setAttribute(ORDERED_LIBS, orderedJars);
+ }
+ else
+ _orderedResources = new ArrayList<Resource>((List<Resource>)_context.getAttribute(WebInfConfiguration.WEB_INF_JAR_RESOURCES));
+ }
+
+
+ /**
+ * Resolve all servlet/filter/listener metadata from all sources: descriptors and annotations.
+ *
+ */
+ public void resolve ()
+ throws Exception
+ {
+ //TODO - apply all descriptors and annotations in order:
+ //apply descriptorProcessors to web-defaults.xml
+ //apply descriptorProcessors to web.xml
+ //apply descriptorProcessors to web-override.xml
+ //apply discovered annotations from container path
+ //apply discovered annotations from WEB-INF/classes
+ //for the ordering of the jars in WEB-INF/lib:
+ // +apply descriptorProcessors to web-fragment.xml
+ // +apply discovered annotations
+
+ for (DescriptorProcessor p:_descriptorProcessors)
+ {
+ p.process(getWebDefault());
+ p.process(getWebXml());
+ p.process(getOverrideWeb());
+ }
+
+ for (DiscoveredAnnotation a:_annotations)
+ a.apply();
+
+
+ List<Resource> resources = getOrderedResources();
+ for (Resource r:resources)
+ {
+ FragmentDescriptor fd = _webFragmentResourceMap.get(r);
+ if (fd != null)
+ {
+ for (DescriptorProcessor p:_descriptorProcessors)
+ {
+ p.process(fd);
+ }
+ }
+
+ List<DiscoveredAnnotation> fragAnnotations = _webFragmentAnnotations.get(r);
+ if (fragAnnotations != null)
+ {
+ for (DiscoveredAnnotation a:fragAnnotations)
+ a.apply();
+ }
+ }
+ }
+
+ public boolean isDistributable ()
+ {
+ boolean distributable = (
+ (_webDefaultsRoot != null && _webDefaultsRoot.isDistributable())
+ || (_webXmlRoot != null && _webXmlRoot.isDistributable())
+ || (_webOverrideRoot != null && _webOverrideRoot.isDistributable()));
+
+ List<Resource> orderedResources = getOrderedResources();
+ for (Resource r: orderedResources)
+ {
+ FragmentDescriptor d = _webFragmentResourceMap.get(r);
+ if (d!=null)
+ distributable = distributable && d.isDistributable();
+ }
+ return distributable;
+ }
+
+
+ public Descriptor getWebXml ()
+ {
+ return _webXmlRoot;
+ }
+
+ public Descriptor getOverrideWeb ()
+ {
+ return _webOverrideRoot;
+ }
+
+ public Descriptor getWebDefault ()
+ {
+ return _webDefaultsRoot;
+ }
+
+ public List<FragmentDescriptor> getFragments ()
+ {
+ return _webFragmentRoots;
+ }
+
+ public List<Resource> getOrderedResources ()
+ {
+ return _orderedResources;
+ }
+
+ public List<FragmentDescriptor> getOrderedFragments ()
+ {
+ List<FragmentDescriptor> list = new ArrayList<FragmentDescriptor>();
+ if (_orderedResources == null)
+ return list;
+
+ for (Resource r:_orderedResources)
+ {
+ FragmentDescriptor fd = _webFragmentResourceMap.get(r);
+ if (fd != null)
+ list.add(fd);
+ }
+ return list;
+ }
+
+ public Ordering getOrdering()
+ {
+ return _ordering;
+ }
+
+ public void setOrdering (Ordering o)
+ {
+ _ordering = o;
+ }
+
+ public FragmentDescriptor getFragment (Resource jar)
+ {
+ return _webFragmentResourceMap.get(jar);
+ }
+
+ public FragmentDescriptor getFragment(String name)
+ {
+ return _webFragmentNameMap.get(name);
+ }
+
+ public Resource getJarForFragment (String name)
+ {
+ FragmentDescriptor f = getFragment(name);
+ if (f == null)
+ return null;
+
+ Resource jar = null;
+ for (Resource r: _webFragmentResourceMap.keySet())
+ {
+ if (_webFragmentResourceMap.get(r).equals(f))
+ jar = r;
+ }
+ return jar;
+ }
+
+ public Map<String,FragmentDescriptor> getNamedFragments ()
+ {
+ return Collections.unmodifiableMap(_webFragmentNameMap);
+ }
+
+
+ public Origin getOrigin (String name)
+ {
+ OriginInfo x = _origins.get(name);
+ if (x == null)
+ return Origin.NotSet;
+
+ return x.getOriginType();
+ }
+
+
+ public Descriptor getOriginDescriptor (String name)
+ {
+ OriginInfo o = _origins.get(name);
+ if (o == null)
+ return null;
+ return o.getDescriptor();
+ }
+
+ public void setOrigin (String name, Descriptor d)
+ {
+ OriginInfo x = new OriginInfo (name, d);
+ _origins.put(name, x);
+ }
+
+ public void setOrigin (String name)
+ {
+ if (name == null)
+ return;
+
+ OriginInfo x = new OriginInfo (name, Origin.Annotation);
+ _origins.put(name, x);
+ }
+}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/OverrideDescriptor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/OverrideDescriptor.java
new file mode 100644
index 0000000000..fe7adb3599
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/OverrideDescriptor.java
@@ -0,0 +1,29 @@
+// ========================================================================
+// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import org.eclipse.jetty.util.resource.Resource;
+
+/**
+ * OverrideDescriptor
+ *
+ *
+ */
+public class OverrideDescriptor extends Descriptor
+{
+ public OverrideDescriptor(Resource xml, MetaData processor)
+ {
+ super(xml, processor);
+ }
+}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java
new file mode 100644
index 0000000000..952f8da4ee
--- /dev/null
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java
@@ -0,0 +1,1335 @@
+// ========================================================================
+// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jetty.server.DispatcherType;
+import javax.servlet.ServletException;
+import org.eclipse.jetty.servlet.api.ServletRegistration;
+
+
+import org.eclipse.jetty.http.security.Constraint;
+import org.eclipse.jetty.security.ConstraintAware;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.security.authentication.FormAuthenticator;
+import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.FilterMapping;
+import org.eclipse.jetty.servlet.Holder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
+import org.eclipse.jetty.util.LazyList;
+import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.webapp.MetaData.Origin;
+import org.eclipse.jetty.xml.XmlParser;
+
+/**
+ * StandardDescriptorProcessor
+ *
+ *
+ */
+public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
+{
+ public static final String STANDARD_PROCESSOR = "org.eclipse.jetty.standardDescriptorProcessor";
+ protected WebAppContext _context;
+
+ //the shared configuration operated on by web-default.xml, web.xml, web-override.xml and all web-fragment.xml
+ protected ServletHandler _servletHandler;
+ protected SecurityHandler _securityHandler;
+ protected Object _filters;
+ protected Object _filterMappings;
+ protected Object _servlets;
+ protected Object _servletMappings;
+ protected Object _listeners;
+ protected Object _listenerClassNames;
+ protected Object _welcomeFiles;
+ protected Set<String> _roles = new HashSet<String>();
+ protected List<ConstraintMapping> _constraintMappings = new ArrayList<ConstraintMapping>();
+ protected Map _errorPages;
+ protected boolean _hasJSP;
+ protected String _jspServletName;
+ protected String _jspServletClass;
+ protected boolean _defaultWelcomeFileList;
+ protected MetaData _metaData;
+
+
+
+ public StandardDescriptorProcessor ()
+ {
+
+ try
+ {
+ registerVisitor("context-param", this.getClass().getDeclaredMethod("visitContextParam", __signature));
+ registerVisitor("display-name", this.getClass().getDeclaredMethod("visitDisplayName", __signature));
+ registerVisitor("servlet", this.getClass().getDeclaredMethod("visitServlet", __signature));
+ registerVisitor("servlet-mapping", this.getClass().getDeclaredMethod("visitServletMapping", __signature));
+ registerVisitor("session-config", this.getClass().getDeclaredMethod("visitSessionConfig", __signature));
+ registerVisitor("mime-mapping", this.getClass().getDeclaredMethod("visitMimeMapping", __signature));
+ registerVisitor("welcome-file-list", this.getClass().getDeclaredMethod("visitWelcomeFileList", __signature));
+ registerVisitor("locale-encoding-mapping-list", this.getClass().getDeclaredMethod("visitLocaleEncodingList", __signature));
+ registerVisitor("error-page", this.getClass().getDeclaredMethod("visitErrorPage", __signature));
+ registerVisitor("taglib", this.getClass().getDeclaredMethod("visitTagLib", __signature));
+ registerVisitor("jsp-config", this.getClass().getDeclaredMethod("visitJspConfig", __signature));
+ registerVisitor("security-constraint", this.getClass().getDeclaredMethod("visitSecurityConstraint", __signature));
+ registerVisitor("login-config", this.getClass().getDeclaredMethod("visitLoginConfig", __signature));
+ registerVisitor("security-role", this.getClass().getDeclaredMethod("visitSecurityRole", __signature));
+ registerVisitor("filter", this.getClass().getDeclaredMethod("visitFilter", __signature));
+ registerVisitor("filter-mapping", this.getClass().getDeclaredMethod("visitFilterMapping", __signature));
+ registerVisitor("listener", this.getClass().getDeclaredMethod("visitListener", __signature));
+ registerVisitor("distributable", this.getClass().getDeclaredMethod("visitDistributable", __signature));
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+
+
+ /**
+ * @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#start()
+ */
+ public void start(Descriptor descriptor)
+ {
+ _metaData = descriptor.getMetaData();
+ _context = _metaData.getContext();
+
+ //Get the current objects from the context
+ _servletHandler = _context.getServletHandler();
+ _securityHandler = (SecurityHandler)_context.getSecurityHandler();
+ _filters = LazyList.array2List(_servletHandler.getFilters());
+ _filterMappings = LazyList.array2List(_servletHandler.getFilterMappings());
+ _servlets = LazyList.array2List(_servletHandler.getServlets());
+ _servletMappings = LazyList.array2List(_servletHandler.getServletMappings());
+ _listeners = LazyList.array2List(_context.getEventListeners());
+ _welcomeFiles = LazyList.array2List(_context.getWelcomeFiles());
+ if (_securityHandler instanceof ConstraintAware)
+ {
+ _constraintMappings.addAll(((ConstraintAware) _securityHandler).getConstraintMappings());
+ if (((ConstraintAware) _securityHandler).getRoles() != null)
+ {
+ _roles.addAll(((ConstraintAware) _securityHandler).getRoles());
+ }
+ }
+ _errorPages = _context.getErrorHandler() instanceof ErrorPageErrorHandler ? ((ErrorPageErrorHandler)_context.getErrorHandler()).getErrorPages() : null;
+ }
+
+
+
+ /**
+ * @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#end()
+ */
+ public void end(Descriptor descriptor)
+ {
+ //Set the context with the results of the processing
+ _servletHandler.setFilters((FilterHolder[]) LazyList.toArray(_filters, FilterHolder.class));
+ _servletHandler.setFilterMappings((FilterMapping[]) LazyList.toArray(_filterMappings, FilterMapping.class));
+ _servletHandler.setServlets((ServletHolder[]) LazyList.toArray(_servlets, ServletHolder.class));
+ _servletHandler.setServletMappings((ServletMapping[]) LazyList.toArray(_servletMappings, ServletMapping.class));
+ _context.setEventListeners((EventListener[]) LazyList.toArray(_listeners, EventListener.class));
+ _context.setWelcomeFiles((String[]) LazyList.toArray(_welcomeFiles, String.class));
+ // TODO jaspi check this
+ if (_securityHandler instanceof ConstraintAware)
+ {
+ for (ConstraintMapping m:_constraintMappings)
+ ((ConstraintAware) _securityHandler).addConstraintMapping(m);
+ for (String r:_roles)
+ ((ConstraintAware) _securityHandler).addRole(r);
+ }
+
+ if (_errorPages != null && _context.getErrorHandler() instanceof ErrorPageErrorHandler)
+ ((ErrorPageErrorHandler)_context.getErrorHandler()).setErrorPages(_errorPages);
+
+ _roles.clear();
+ _constraintMappings.clear();
+ _metaData = null;
+ _context = null;
+ }
+
+ public void visitContextParam (Descriptor descriptor, XmlParser.Node node)
+ {
+ String name = node.getString("param-name", false, true);
+ String value = node.getString("param-value", false, true);
+ Origin o = _metaData.getOrigin("context-param."+name);
+ switch (o)
+ {
+ case NotSet:
+ {
+ //just set it
+ _context.getInitParams().put(name, value);
+ _metaData.setOrigin("context-param."+name, descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //previously set by a web xml, allow other web xml files to override
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _context.getInitParams().put(name, value);
+ _metaData.setOrigin("context-param."+name, descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //previously set by a web-fragment, this fragment's value must be the same
+ if (descriptor instanceof FragmentDescriptor)
+ {
+ if (!((String)_context.getInitParams().get(name)).equals(value))
+ throw new IllegalStateException("Conflicting context-param "+name+"="+value+" in "+descriptor.getResource());
+ }
+ break;
+ }
+ }
+ if (Log.isDebugEnabled()) Log.debug("ContextParam: " + name + "=" + value);
+
+ }
+
+
+ /* ------------------------------------------------------------ */
+ protected void visitDisplayName(Descriptor descriptor, XmlParser.Node node)
+ {
+ //Servlet Spec 3.0 p. 74 Ignore from web-fragments
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _context.setDisplayName(node.toString(false, true));
+ _metaData.setOrigin("display-name", descriptor);
+ }
+ }
+
+ protected void visitServlet(Descriptor descriptor, XmlParser.Node node)
+ {
+ String id = node.getAttribute("id");
+
+ // initialize holder
+ String servlet_name = node.getString("servlet-name", false, true);
+ ServletHolder holder = _servletHandler.getServlet(servlet_name);
+
+ /*
+ * If servlet of that name does not already exist, create it.
+ */
+ if (holder == null)
+ {
+ holder = _servletHandler.newServletHolder();
+ holder.setName(servlet_name);
+ _servlets = LazyList.add(_servlets, holder);
+ }
+ ServletRegistration.Dynamic registration = holder.getRegistration();
+
+ // init params
+ Iterator iParamsIter = node.iterator("init-param");
+ while (iParamsIter.hasNext())
+ {
+ XmlParser.Node paramNode = (XmlParser.Node) iParamsIter.next();
+ String pname = paramNode.getString("param-name", false, true);
+ String pvalue = paramNode.getString("param-value", false, true);
+
+ Origin origin = _metaData.getOrigin(servlet_name+".servlet.init-param."+pname);
+
+ switch (origin)
+ {
+ case NotSet:
+ {
+ //init-param not already set, so set it
+
+ registration.setInitParameter(pname, pvalue);
+ _metaData.setOrigin(servlet_name+".servlet.init-param."+pname, descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //previously set by a web xml descriptor, if we're parsing another web xml descriptor allow override
+ //otherwise just ignore it
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ registration.setInitParameter(pname, pvalue);
+ _metaData.setOrigin(servlet_name+".servlet.init-param."+pname, descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //previously set by a web-fragment, make sure that the value matches, otherwise its an error
+ if (!registration.getInitParameter(pname).equals(pvalue))
+ throw new IllegalStateException("Mismatching init-param "+pname+"="+pvalue+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ String servlet_class = node.getString("servlet-class", false, true);
+
+ // Handle JSP
+ if (id != null && id.equals("jsp"))
+ {
+ _jspServletName = servlet_name;
+ _jspServletClass = servlet_class;
+ try
+ {
+ Loader.loadClass(this.getClass(), servlet_class);
+ _hasJSP = true;
+ }
+ catch (ClassNotFoundException e)
+ {
+ Log.info("NO JSP Support for {}, did not find {}", _context.getContextPath(), servlet_class);
+ _hasJSP = false;
+ _jspServletClass = servlet_class = "org.eclipse.jetty.servlet.NoJspServlet";
+ }
+ if (registration.getInitParameter("scratchdir") == null)
+ {
+ File tmp = _context.getTempDirectory();
+ File scratch = new File(tmp, "jsp");
+ if (!scratch.exists()) scratch.mkdir();
+ registration.setInitParameter("scratchdir", scratch.getAbsolutePath());
+
+ if ("?".equals(registration.getInitParameter("classpath")))
+ {
+ String classpath = _context.getClassPath();
+ Log.debug("classpath=" + classpath);
+ if (classpath != null)
+ registration.setInitParameter("classpath", classpath);
+ }
+ }
+
+ /* Set the webapp's classpath for Jasper */
+ _context.setAttribute("org.apache.catalina.jsp_classpath", _context.getClassPath());
+ /* Set the system classpath for Jasper */
+ registration.setInitParameter("com.sun.appserv.jsp.classpath", getSystemClassPath());
+ }
+
+ //Set the servlet-class
+ if (servlet_class != null)
+ {
+ descriptor.addClassName(servlet_class);
+
+ Origin o = _metaData.getOrigin(servlet_name+".servlet.servlet-class");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //the class of the servlet has not previously been set, so set it
+ holder.setClassName(servlet_class);
+ _metaData.setOrigin(servlet_name+".servlet.servlet-class", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //the class of the servlet was set by a web xml file, only allow web-override/web-default to change it
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ holder.setClassName(servlet_class);
+ _metaData.setOrigin(servlet_name+".servlet.servlet-class", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //the class was set by another fragment, ensure this fragment's value is the same
+ if (!servlet_class.equals(holder.getClassName()))
+ throw new IllegalStateException("Conflicting servlet-class "+servlet_class+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ // Handler JSP file
+ String jsp_file = node.getString("jsp-file", false, true);
+ if (jsp_file != null)
+ {
+ holder.setForcedPath(jsp_file);
+ holder.setClassName(_jspServletClass);
+ }
+
+ // handle load-on-startup
+ XmlParser.Node startup = node.get("load-on-startup");
+ if (startup != null)
+ {
+ String s = startup.toString(false, true).toLowerCase();
+ int order = 0;
+ if (s.startsWith("t"))
+ {
+ Log.warn("Deprecated boolean load-on-startup. Please use integer");
+ order = 1;
+ }
+ else
+ {
+ try
+ {
+ if (s != null && s.trim().length() > 0) order = Integer.parseInt(s);
+ }
+ catch (Exception e)
+ {
+ Log.warn("Cannot parse load-on-startup " + s + ". Please use integer");
+ Log.ignore(e);
+ }
+ }
+
+ Origin o = _metaData.getOrigin(servlet_name+".servlet.load-on-startup");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //not already set, so set it now
+ registration.setLoadOnStartup(order);
+ _metaData.setOrigin(servlet_name+".servlet.load-on-startup", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //if it was already set by a web xml descriptor and we're parsing another web xml descriptor, then override it
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ registration.setLoadOnStartup(order);
+ _metaData.setOrigin(servlet_name+".servlet.load-on-startup", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //it was already set by another fragment, if we're parsing a fragment, the values must match
+ if (order != holder.getInitOrder())
+ throw new IllegalStateException("Conflicting load-on-startup value in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ Iterator sRefsIter = node.iterator("security-role-ref");
+ while (sRefsIter.hasNext())
+ {
+ XmlParser.Node securityRef = (XmlParser.Node) sRefsIter.next();
+ String roleName = securityRef.getString("role-name", false, true);
+ String roleLink = securityRef.getString("role-link", false, true);
+ if (roleName != null && roleName.length() > 0 && roleLink != null && roleLink.length() > 0)
+ {
+ if (Log.isDebugEnabled()) Log.debug("link role " + roleName + " to " + roleLink + " for " + this);
+ Origin o = _metaData.getOrigin(servlet_name+".servlet.role-name."+roleName);
+ switch (o)
+ {
+ case NotSet:
+ {
+ //set it
+ holder.setUserRoleLink(roleName, roleLink);
+ _metaData.setOrigin(servlet_name+".servlet.role-name."+roleName, descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //only another web xml descriptor (web-default,web-override web.xml) can override an already set value
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ holder.setUserRoleLink(roleName, roleLink);
+ _metaData.setOrigin(servlet_name+".servlet.role-name."+roleName, descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ if (!holder.getUserRoleLink(roleName).equals(roleLink))
+ throw new IllegalStateException("Conflicting role-link for role-name "+roleName+" for servlet "+servlet_name+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+ else
+ {
+ Log.warn("Ignored invalid security-role-ref element: " + "servlet-name=" + holder.getName() + ", " + securityRef);
+ }
+ }
+
+
+ XmlParser.Node run_as = node.get("run-as");
+ if (run_as != null)
+ {
+ String roleName = run_as.getString("role-name", false, true);
+
+ if (roleName != null)
+ {
+ Origin o = _metaData.getOrigin(servlet_name+".servlet.run-as");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //run-as not set, so set it
+ registration.setRunAsRole(roleName);
+ _metaData.setOrigin(servlet_name+".servlet.run-as", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //run-as was set by a web xml, only allow it to be changed if we're currently parsing another web xml(override/default)
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ registration.setRunAsRole(roleName);
+ _metaData.setOrigin(servlet_name+".servlet.run-as", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //run-as was set by another fragment, this fragment must show the same value
+ if (!registration.getRunAsRole().equals(roleName))
+ throw new IllegalStateException("Conflicting run-as role "+roleName+" for servlet "+servlet_name+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ protected void visitServletMapping(Descriptor descriptor, XmlParser.Node node)
+ {
+ //Servlet Spec 3.0, p74
+ //servlet-mappings are always additive, whether from web xml descriptors (web.xml/web-default.xml/web-override.xml) or web-fragments.
+ String servlet_name = node.getString("servlet-name", false, true);
+ ServletMapping mapping = new ServletMapping();
+ mapping.setServletName(servlet_name);
+
+ if (_metaData.getOrigin(servlet_name+".servlet.mappings") == Origin.NotSet)
+ _metaData.setOrigin(servlet_name+".servlet.mappings", descriptor);
+
+ ArrayList paths = new ArrayList();
+ Iterator iter = node.iterator("url-pattern");
+ while (iter.hasNext())
+ {
+ String p = ((XmlParser.Node) iter.next()).toString(false, true);
+ p = normalizePattern(p);
+ paths.add(p);
+ }
+ mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
+ _servletMappings = LazyList.add(_servletMappings, mapping);
+ }
+
+
+ protected void visitSessionConfig(Descriptor descriptor, XmlParser.Node node)
+ {
+ XmlParser.Node tNode = node.get("session-timeout");
+ if (tNode != null)
+ {
+ int timeout = Integer.parseInt(tNode.toString(false, true));
+ _context.getSessionHandler().getSessionManager().setMaxInactiveInterval(timeout * 60);
+ }
+ }
+
+ protected void visitMimeMapping(Descriptor descriptor, XmlParser.Node node)
+ {
+ String extension = node.getString("extension", false, true);
+ if (extension != null && extension.startsWith("."))
+ extension = extension.substring(1);
+ String mimeType = node.getString("mime-type", false, true);
+ if (extension != null)
+ {
+ Origin o = _metaData.getOrigin("extension."+extension);
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no mime-type set for the extension yet
+ _context.getMimeTypes().addMimeMapping(extension, mimeType);
+ _metaData.setOrigin("extension."+extension, descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //a mime-type was set for the extension in a web xml, only allow web-default/web-override to change
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _context.getMimeTypes().addMimeMapping(extension, mimeType);
+ _metaData.setOrigin("extension."+extension, descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment set the value, all web-fragments must have the same value
+ if (!_context.getMimeTypes().getMimeByExtension("."+extension).equals(_context.getMimeTypes().CACHE.lookup(mimeType)))
+ throw new IllegalStateException("Conflicting mime-type "+mimeType+" for extension "+extension+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+ }
+
+ protected void visitWelcomeFileList(Descriptor descriptor, XmlParser.Node node)
+ {
+ Origin o = _metaData.getOrigin("welcome-file-list");
+ switch (o)
+ {
+ case NotSet:
+ {
+ _metaData.setOrigin("welcome-file-list", descriptor);
+ addWelcomeFiles(node);
+ break;
+ }
+ case WebXml:
+ {
+ //web.xml set the welcome-file-list, all other descriptors then just merge in
+ addWelcomeFiles(node);
+ break;
+ }
+ case WebDefaults:
+ {
+ //if web-defaults set the welcome-file-list first and
+ //we're processing web.xml then reset the welcome-file-list
+ if (!(descriptor instanceof DefaultsDescriptor) && !(descriptor instanceof OverrideDescriptor) && !(descriptor instanceof FragmentDescriptor))
+ {
+ _welcomeFiles = null;
+ }
+ addWelcomeFiles(node);
+ break;
+ }
+ case WebOverride:
+ {
+ //web-override set the list, all other descriptors just merge in
+ addWelcomeFiles(node);
+ break;
+ }
+ case WebFragment:
+ {
+ //A web-fragment first set the welcome-file-list. Other descriptors just add.
+ addWelcomeFiles(node);
+ break;
+ }
+ }
+ }
+
+ protected void visitLocaleEncodingList(Descriptor descriptor, XmlParser.Node node)
+ {
+ Iterator iter = node.iterator("locale-encoding-mapping");
+ while (iter.hasNext())
+ {
+ XmlParser.Node mapping = (XmlParser.Node) iter.next();
+ String locale = mapping.getString("locale", false, true);
+ String encoding = mapping.getString("encoding", false, true);
+
+ if (encoding != null)
+ {
+ Origin o = _metaData.getOrigin("locale-encoding."+locale);
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no mapping for the locale yet, so set it
+ _context.addLocaleEncoding(locale, encoding);
+ _metaData.setOrigin("locale-encoding."+locale, descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //a value was set in a web descriptor, only allow another web descriptor to change it (web-default/web-override)
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _context.addLocaleEncoding(locale, encoding);
+ _metaData.setOrigin("locale-encoding."+locale, descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a value was set by a web-fragment, all fragments must have the same value
+ if (!encoding.equals(_context.getLocaleEncoding(locale)))
+ throw new IllegalStateException("Conflicting locale-encoding mapping for locale "+locale+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ protected void visitErrorPage(Descriptor descriptor, XmlParser.Node node)
+ {
+ String error = node.getString("error-code", false, true);
+ if (error == null || error.length() == 0) error = node.getString("exception-type", false, true);
+ String location = node.getString("location", false, true);
+
+ if (_errorPages == null)
+ _errorPages = new HashMap();
+
+ Origin o = _metaData.getOrigin("error."+error);
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no error page setup for this code or exception yet
+ _errorPages.put(error, location);
+ _metaData.setOrigin("error."+error, descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //an error page setup was set in web.xml, only allow other web xml descriptors to override it
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _errorPages.put(error, location);
+ _metaData.setOrigin("error."+error, descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //another web fragment set the same error code or exception, if its different its an error
+ if (!_errorPages.get(error).equals(location))
+ throw new IllegalStateException("Conflicting error-code or exception-type "+error+" in "+descriptor.getResource());
+ break;
+ }
+ }
+
+ }
+
+ protected void addWelcomeFiles (XmlParser.Node node)
+ {
+ Iterator iter = node.iterator("welcome-file");
+ while (iter.hasNext())
+ {
+ XmlParser.Node indexNode = (XmlParser.Node) iter.next();
+ String welcome = indexNode.toString(false, true);
+
+ //Servlet Spec 3.0 p. 74 welcome files are additive
+ _welcomeFiles = LazyList.add(_welcomeFiles, welcome);
+ }
+ }
+
+ protected void visitTagLib(Descriptor descriptor, XmlParser.Node node)
+ {
+ //Additive across web.xml and web-fragment.xml
+ String uri = node.getString("taglib-uri", false, true);
+ String location = node.getString("taglib-location", false, true);
+
+ _context.setResourceAlias(uri, location);
+ }
+
+ protected void visitJspConfig(Descriptor descriptor, XmlParser.Node node)
+ {
+ for (int i = 0; i < node.size(); i++)
+ {
+ Object o = node.get(i);
+ if (o instanceof XmlParser.Node && "taglib".equals(((XmlParser.Node) o).getTag()))
+ visitTagLib(descriptor, (XmlParser.Node) o);
+ }
+
+ // Map URLs from jsp property groups to JSP servlet.
+ // this is more JSP stupidness creaping into the servlet spec
+ Iterator iter = node.iterator("jsp-property-group");
+ Object paths = null;
+ while (iter.hasNext())
+ {
+ XmlParser.Node group = (XmlParser.Node) iter.next();
+ Iterator iter2 = group.iterator("url-pattern");
+ while (iter2.hasNext())
+ {
+ String url = ((XmlParser.Node) iter2.next()).toString(false, true);
+ url = normalizePattern(url);
+ paths = LazyList.add(paths, url);
+ }
+ }
+
+ if (LazyList.size(paths) > 0)
+ {
+ String jspName = getJSPServletName();
+ if (jspName != null)
+ {
+ ServletMapping mapping = new ServletMapping();
+ mapping.setServletName(jspName);
+ mapping.setPathSpecs(LazyList.toStringArray(paths));
+ _servletMappings = LazyList.add(_servletMappings, mapping);
+ }
+ }
+ }
+
+ protected void visitSecurityConstraint(Descriptor descriptor, XmlParser.Node node)
+ {
+ Constraint scBase = new Constraint();
+
+ //ServletSpec 3.0, p74 security-constraints, as minOccurs > 1, are additive
+ //across fragments
+ try
+ {
+ XmlParser.Node auths = node.get("auth-constraint");
+
+ if (auths != null)
+ {
+ scBase.setAuthenticate(true);
+ // auth-constraint
+ Iterator iter = auths.iterator("role-name");
+ Object roles = null;
+ while (iter.hasNext())
+ {
+ String role = ((XmlParser.Node) iter.next()).toString(false, true);
+ roles = LazyList.add(roles, role);
+ }
+ scBase.setRoles(LazyList.toStringArray(roles));
+ }
+
+ XmlParser.Node data = node.get("user-data-constraint");
+ if (data != null)
+ {
+ data = data.get("transport-guarantee");
+ String guarantee = data.toString(false, true).toUpperCase();
+ if (guarantee == null || guarantee.length() == 0 || "NONE".equals(guarantee))
+ scBase.setDataConstraint(Constraint.DC_NONE);
+ else if ("INTEGRAL".equals(guarantee))
+ scBase.setDataConstraint(Constraint.DC_INTEGRAL);
+ else if ("CONFIDENTIAL".equals(guarantee))
+ scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
+ else
+ {
+ Log.warn("Unknown user-data-constraint:" + guarantee);
+ scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
+ }
+ }
+ Iterator iter = node.iterator("web-resource-collection");
+ while (iter.hasNext())
+ {
+ XmlParser.Node collection = (XmlParser.Node) iter.next();
+ String name = collection.getString("web-resource-name", false, true);
+ Constraint sc = (Constraint) scBase.clone();
+ sc.setName(name);
+
+ Iterator iter2 = collection.iterator("url-pattern");
+ while (iter2.hasNext())
+ {
+ String url = ((XmlParser.Node) iter2.next()).toString(false, true);
+ url = normalizePattern(url);
+
+ Iterator iter3 = collection.iterator("http-method");
+ if (iter3.hasNext())
+ {
+ while (iter3.hasNext())
+ {
+ String method = ((XmlParser.Node) iter3.next()).toString(false, true);
+ ConstraintMapping mapping = new ConstraintMapping();
+ mapping.setMethod(method);
+ mapping.setPathSpec(url);
+ mapping.setConstraint(sc);
+ _constraintMappings.add(mapping);
+ }
+ }
+ else
+ {
+ ConstraintMapping mapping = new ConstraintMapping();
+ mapping.setPathSpec(url);
+ mapping.setConstraint(sc);
+ _constraintMappings.add(mapping);
+ }
+ }
+ }
+ }
+ catch (CloneNotSupportedException e)
+ {
+ Log.warn(e);
+ }
+ }
+
+ protected void visitLoginConfig(Descriptor descriptor, XmlParser.Node node) throws Exception
+ {
+ //ServletSpec 3.0 p74 says elements present 0/1 time if specified in web.xml take
+ //precendece over any web-fragment. If not specified in web.xml, then if specified
+ //in a web-fragment must be the same across all web-fragments.
+ XmlParser.Node method = node.get("auth-method");
+ if (method != null)
+ {
+ //handle auth-method merge
+ Origin o = _metaData.getOrigin("auth-method");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //not already set, so set it now
+ _securityHandler.setAuthMethod(method.toString(false, true));
+ _metaData.setOrigin("auth-method", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //if it was already set by a web xml descriptor and we're parsing another web xml descriptor, then override it
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _securityHandler.setAuthMethod(method.toString(false, true));
+ _metaData.setOrigin("auth-method", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //it was already set by another fragment, if we're parsing a fragment, the values must match
+ if (!_securityHandler.getAuthMethod().equals(method.toString(false, true)))
+ throw new IllegalStateException("Conflicting auth-method value in "+descriptor.getResource());
+ break;
+ }
+ }
+
+ //handle realm-name merge
+ XmlParser.Node name = node.get("realm-name");
+ String nameStr = (name == null ? "default" : name.toString(false, true));
+ o = _metaData.getOrigin("realm-name");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no descriptor has set the realm-name yet, so set it
+ _securityHandler.setRealmName(nameStr);
+ _metaData.setOrigin("realm-name", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //set by a web xml file (web.xml/web-default.xm/web-override.xml), only allow it to be changed by another web xml file
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _securityHandler.setRealmName(nameStr);
+ _metaData.setOrigin("realm-name", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a fragment set it, and we must be parsing another fragment, so the values must match
+ if (!_securityHandler.getRealmName().equals(nameStr))
+ throw new IllegalStateException("Conflicting realm-name value in "+descriptor.getResource());
+ break;
+ }
+ }
+
+ if (Constraint.__FORM_AUTH.equals(_securityHandler.getAuthMethod()))
+ {
+ XmlParser.Node formConfig = node.get("form-login-config");
+ if (formConfig != null)
+ {
+ String loginPageName = null;
+ XmlParser.Node loginPage = formConfig.get("form-login-page");
+ if (loginPage != null)
+ loginPageName = loginPage.toString(false, true);
+ String errorPageName = null;
+ XmlParser.Node errorPage = formConfig.get("form-error-page");
+ if (errorPage != null)
+ errorPageName = errorPage.toString(false, true);
+
+ //handle form-login-page
+ o = _metaData.getOrigin("form-login-page");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //Never been set before, so accept it
+ _securityHandler.setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
+ _metaData.setOrigin("form-login-page",descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //a web xml descriptor previously set it, only allow another one to change it (web.xml/web-default.xml/web-override.xml)
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _securityHandler.setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
+ _metaData.setOrigin("form-login-page",descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment previously set it. We must be parsing yet another web-fragment, so the values must agree
+ if (!_securityHandler.getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE).equals(loginPageName))
+ throw new IllegalStateException("Conflicting form-login-page value in "+descriptor.getResource());
+ break;
+ }
+ }
+
+ //handle form-error-page
+ o = _metaData.getOrigin("form-error-page");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //Never been set before, so accept it
+ _securityHandler.setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
+ _metaData.setOrigin("form-error-page",descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //a web xml descriptor previously set it, only allow another one to change it (web.xml/web-default.xml/web-override.xml)
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ _securityHandler.setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
+ _metaData.setOrigin("form-error-page",descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment previously set it. We must be parsing yet another web-fragment, so the values must agree
+ if (!_securityHandler.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE).equals(errorPageName))
+ throw new IllegalStateException("Conflicting form-error-page value in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+ else
+ {
+ throw new IllegalStateException("!form-login-config");
+ }
+ }
+ }
+ }
+
+ protected void visitSecurityRole(Descriptor descriptor, XmlParser.Node node)
+ {
+ //ServletSpec 3.0, p74 elements with multiplicity >1 are additive when merged
+ XmlParser.Node roleNode = node.get("role-name");
+ String role = roleNode.toString(false, true);
+ _roles.add(role);
+ }
+
+
+ protected void visitFilter(Descriptor descriptor, XmlParser.Node node)
+ {
+ String name = node.getString("filter-name", false, true);
+ FilterHolder holder = _servletHandler.getFilter(name);
+ if (holder == null)
+ {
+ holder = _servletHandler.newFilterHolder();
+ holder.setName(name);
+ _filters = LazyList.add(_filters, holder);
+ }
+
+ String filter_class = node.getString("filter-class", false, true);
+ if (filter_class != null)
+ {
+ descriptor.addClassName(filter_class);
+
+ Origin o = _metaData.getOrigin(name+".filter.filter-class");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no class set yet
+ holder.setClassName(filter_class);
+ _metaData.setOrigin(name+".filter.filter-class", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //filter class was set in web.xml, only allow other web xml descriptors (override/default) to change it
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ holder.setClassName(filter_class);
+ _metaData.setOrigin(name+".filter.filter-class", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //the filter class was set up by a web fragment, all fragments must be the same
+ if (!holder.getClassName().equals(filter_class))
+ throw new IllegalStateException("Conflicting filter-class for filter "+name+" in "+descriptor.getResource());
+ break;
+ }
+ }
+
+ }
+
+ Iterator iter = node.iterator("init-param");
+ while (iter.hasNext())
+ {
+ XmlParser.Node paramNode = (XmlParser.Node) iter.next();
+ String pname = paramNode.getString("param-name", false, true);
+ String pvalue = paramNode.getString("param-value", false, true);
+
+ Origin origin = _metaData.getOrigin(name+".filter.init-param."+pname);
+ switch (origin)
+ {
+ case NotSet:
+ {
+ //init-param not already set, so set it
+ holder.setInitParameter(pname, pvalue);
+ _metaData.setOrigin(name+".filter.init-param."+pname, descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //previously set by a web xml descriptor, if we're parsing another web xml descriptor allow override
+ //otherwise just ignore it
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ holder.setInitParameter(pname, pvalue);
+ _metaData.setOrigin(name+".filter.init-param."+pname, descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //previously set by a web-fragment, make sure that the value matches, otherwise its an error
+ if (!holder.getInitParameter(pname).equals(pvalue))
+ throw new IllegalStateException("Mismatching init-param "+pname+"="+pvalue+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ String async=node.getString("async-supported",false,true);
+ if (async!=null)
+ holder.setAsyncSupported(async.length()==0||Boolean.valueOf(async));
+ if (async!=null)
+ {
+ boolean val = async.length()==0||Boolean.valueOf(async);
+ Origin o = _metaData.getOrigin(name+".filter.async-supported");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //set it
+ holder.setAsyncSupported(val);
+ _metaData.setOrigin(name+".filter.async-supported", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //async-supported set by previous web xml descriptor, only allow override if we're parsing another web descriptor(web.xml/web-override.xml/web-default.xml)
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ holder.setAsyncSupported(val);
+ _metaData.setOrigin(name+".filter.async-supported", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //async-supported set by another fragment, this fragment's value must match
+ if (holder.isAsyncSupported() != val)
+ throw new IllegalStateException("Conflicting async-supported="+async+" for filter "+name+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ }
+
+ protected void visitFilterMapping(Descriptor descriptor, XmlParser.Node node)
+ {
+ //Servlet Spec 3.0, p74
+ //filter-mappings are always additive, whether from web xml descriptors (web.xml/web-default.xml/web-override.xml) or web-fragments.
+
+ String filter_name = node.getString("filter-name", false, true);
+
+ FilterMapping mapping = new FilterMapping();
+
+ mapping.setFilterName(filter_name);
+
+ ArrayList paths = new ArrayList();
+ Iterator iter = node.iterator("url-pattern");
+ while (iter.hasNext())
+ {
+ String p = ((XmlParser.Node) iter.next()).toString(false, true);
+ p = normalizePattern(p);
+ paths.add(p);
+ }
+ mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
+
+ ArrayList names = new ArrayList();
+ iter = node.iterator("servlet-name");
+ while (iter.hasNext())
+ {
+ String n = ((XmlParser.Node) iter.next()).toString(false, true);
+ names.add(n);
+ }
+ mapping.setServletNames((String[]) names.toArray(new String[names.size()]));
+
+
+ List<DispatcherType> dispatches = new ArrayList<DispatcherType>();
+ iter=node.iterator("dispatcher");
+ while(iter.hasNext())
+ {
+ String d=((XmlParser.Node)iter.next()).toString(false,true);
+ dispatches.add(FilterMapping.dispatch(d));
+ }
+
+ if (dispatches.size()>0)
+ mapping.setDispatcherTypes(EnumSet.copyOf(dispatches));
+
+ _filterMappings = LazyList.add(_filterMappings, mapping);
+ }
+
+
+ protected void visitListener(Descriptor descriptor, XmlParser.Node node)
+ {
+ String className = node.getString("listener-class", false, true);
+ Object listener = null;
+ try
+ {
+ if (className != null && className.length()> 0)
+ {
+ descriptor.addClassName(className);
+
+ //Servlet Spec 3.0 p 74
+ //Duplicate listener declarations don't result in duplicate listener instances
+ if (!LazyList.contains(_listenerClassNames, className))
+ {
+ LazyList.add(_listenerClassNames, className);
+ Class listenerClass = _context.loadClass(className);
+ listener = newListenerInstance(listenerClass);
+ if (!(listener instanceof EventListener))
+ {
+ Log.warn("Not an EventListener: " + listener);
+ return;
+ }
+ _metaData.setOrigin(className+".listener", descriptor);
+ _listeners = LazyList.add(_listeners, listener);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Log.warn("Could not instantiate listener " + className, e);
+ return;
+ }
+ }
+
+ protected void visitDistributable(Descriptor descriptor, XmlParser.Node node)
+ {
+ // the element has no content, so its simple presence
+ // indicates that the webapp is distributable...
+ //Servlet Spec 3.0 p.74 distributable only if all fragments are distributable
+ descriptor.setDistributable(true);
+ }
+
+ protected Object newListenerInstance(Class<?extends EventListener> clazz) throws ServletException, InstantiationException, IllegalAccessException
+ {
+ try
+ {
+ return ((ServletContextHandler.Context)_context.getServletContext()).createListener(clazz);
+ }
+ catch (ServletException se)
+ {
+ Throwable cause = se.getRootCause();
+ if (cause instanceof InstantiationException)
+ throw (InstantiationException)cause;
+ if (cause instanceof IllegalAccessException)
+ throw (IllegalAccessException)cause;
+ throw se;
+ }
+ }
+
+ protected String getJSPServletName()
+ {
+ if (_jspServletName == null)
+ {
+ Map.Entry entry = _context.getServletHandler().getHolderEntry("test.jsp");
+ if (entry != null)
+ {
+ ServletHolder holder = (ServletHolder) entry.getValue();
+ _jspServletName = holder.getName();
+ }
+ }
+ return _jspServletName;
+ }
+
+ protected String normalizePattern(String p)
+ {
+ if (p != null && p.length() > 0 && !p.startsWith("/") && !p.startsWith("*")) return "/" + p;
+ return p;
+ }
+
+ /**
+ * Generate the classpath (as a string) of all classloaders
+ * above the webapp's classloader.
+ *
+ * This is primarily used for jasper.
+ * @return
+ */
+ protected String getSystemClassPath ()
+ {
+ ClassLoader loader = _context.getClassLoader();
+ if (loader.getParent() != null)
+ loader = loader.getParent();
+
+ StringBuilder classpath=new StringBuilder();
+ while (loader != null && (loader instanceof URLClassLoader))
+ {
+ URL[] urls = ((URLClassLoader)loader).getURLs();
+ if (urls != null)
+ {
+ for (int i=0;i<urls.length;i++)
+ {
+ try
+ {
+ Resource resource = _context.newResource(urls[i]);
+ File file=resource.getFile();
+ if (file!=null && file.exists())
+ {
+ if (classpath.length()>0)
+ classpath.append(File.pathSeparatorChar);
+ classpath.append(file.getAbsolutePath());
+ }
+ }
+ catch (IOException e)
+ {
+ Log.debug(e);
+ }
+ }
+ }
+ loader = loader.getParent();
+ }
+ return classpath.toString();
+ }
+}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/TagLibConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/TagLibConfiguration.java
index d5b349b35c..f5dd88f39e 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/TagLibConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/TagLibConfiguration.java
@@ -45,7 +45,8 @@ import org.eclipse.jetty.xml.XmlParser;
* &lt;/bile&gt;
*
*
- *
+ * TODO - this has been superceded by the new TldScanner in jasper which uses ServletContainerInitializer to
+ * find all the listeners in tag libs and register them.
*/
public class TagLibConfiguration implements Configuration
{
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
index cea44168f2..139d868129 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
@@ -371,11 +371,16 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
- // Prepare for configuration
+ // Prepare for configuration
+ //Make a new MetaData to hold descriptor and annotation metadata
+ MetaData metadata = new MetaData(this);
+ setAttribute(MetaData.METADATA, metadata);
+
for (int i=0;i<_configurations.length;i++)
_configurations[i].preConfigure(this);
super.doStart();
+
// Clean up after configuration
for (int i=0;i<_configurations.length;i++)
@@ -986,12 +991,12 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
protected void startContext()
throws Exception
{
-
-
// Configure webapp
for (int i=0;i<_configurations.length;i++)
_configurations[i].configure(this);
-
+
+ //resolve the metadata
+ ((MetaData)getAttribute(MetaData.METADATA)).resolve();
super.startContext();
}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
index 922952ac15..a4fd810f3f 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
@@ -23,6 +23,7 @@ public class WebInfConfiguration implements Configuration
public static final String TEMPDIR_CREATED = "org.eclipse.jetty.tmpdirCreated";
public static final String CONTAINER_JAR_RESOURCES = "org.eclipse.jetty.containerJars";
public static final String WEB_INF_JAR_RESOURCES = "org.eclipse.jetty.webInfJars";
+ public static final String WEB_INF_ORDERED_JAR_RESOURCES = "org.eclipse.jetty.webInfOrderedJars";
public static final String CONTAINER_JAR_PATTERN = "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern";
public static final String WEBINF_JAR_PATTERN = "org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern";
@@ -96,6 +97,7 @@ public class WebInfConfiguration implements Configuration
}
};
List<Resource> jars = findJars(context);
+
//Convert to uris for matching
URI[] uris = null;
if (jars != null)
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
index f392ab188e..abb952d479 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
@@ -1,5 +1,5 @@
// ========================================================================
-// Copyright (c) 2003-2009 Mort Bay Consulting Pty. Ltd.
+// Copyright (c) 2003-2010 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
@@ -34,52 +34,50 @@ public class WebXmlConfiguration implements Configuration
/* ------------------------------------------------------------------------------- */
/**
- * Process webdefaults.xml
+ *
*
*
*/
public void preConfigure (WebAppContext context) throws Exception
{
- // cannot configure if the context is already started
- if (context.isStarted())
- {
- if (Log.isDebugEnabled())
- {
- Log.debug("Cannot configure webapp after it is started");
- }
- return;
- }
-
- //Get or create a processor to handle webdefaults, web.xml and the fragments
- WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
- if (processor == null)
- {
- processor = new WebXmlProcessor (context);
- context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
- }
-
- //handle webdefault.xml
+
+ MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
+ if (metaData == null)
+ throw new IllegalStateException("No metadata");
+
+
+ //parse webdefault.xml
String defaultsDescriptor = context.getDefaultsDescriptor();
if (defaultsDescriptor != null && defaultsDescriptor.length() > 0)
{
Resource dftResource = Resource.newSystemResource(defaultsDescriptor);
if (dftResource == null)
dftResource = context.newResource(defaultsDescriptor);
- processor.parseDefaults (dftResource);
- processor.processDefaults();
+ metaData.setDefaults (dftResource);
+
}
//parse, but don't process web.xml
Resource webxml = findWebXml(context);
if (webxml != null)
{
- processor.parseWebXml(webxml);
+ metaData.setWebXml(webxml);
+ }
+
+ //parse but don't process override-web.xml
+ String overrideDescriptor = context.getOverrideDescriptor();
+ if (overrideDescriptor != null && overrideDescriptor.length() > 0)
+ {
+ Resource orideResource = Resource.newSystemResource(overrideDescriptor);
+ if (orideResource == null)
+ orideResource = context.newResource(overrideDescriptor);
+ metaData.setOverride(orideResource);
}
}
/* ------------------------------------------------------------------------------- */
/**
- * Process web.xml, web-fragment.xml(s), override-web.xml
+ * Process web-default.xml, web.xml, override-web.xml
*
*/
public void configure (WebAppContext context) throws Exception
@@ -90,35 +88,35 @@ public class WebXmlConfiguration implements Configuration
if (Log.isDebugEnabled()) Log.debug("Cannot configure webapp after it is started");
return;
}
+
+ MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
+ if (metaData == null)
+ throw new IllegalStateException("No metadata");
+
+ metaData.addDescriptorProcessor(new StandardDescriptorProcessor());
- WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
- if (processor == null)
+ /*
+ StandardDescriptorProcessor descriptorProcessor = (StandardDescriptorProcessor)context.getAttribute(StandardDescriptorProcessor.STANDARD_PROCESSOR);
+ if (descriptorProcessor == null)
{
- processor = new WebXmlProcessor (context);
- context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
+ descriptorProcessor = new StandardDescriptorProcessor(metaData);
+ context.setAttribute(StandardDescriptorProcessor.STANDARD_PROCESSOR, descriptorProcessor);
}
+
+ //process web-default.xml
+ descriptorProcessor.process(metaData.getWebDefault());
- //process web.xml (the effective web.xml???)
- processor.processWebXml();
+ //process web.xml
+ descriptorProcessor.process(metaData.getWebXml());
- //process override-web.xml
- String overrideDescriptor = context.getOverrideDescriptor();
- if (overrideDescriptor != null && overrideDescriptor.length() > 0)
- {
- Resource orideResource = Resource.newSystemResource(overrideDescriptor);
- if (orideResource == null)
- orideResource = context.newResource(overrideDescriptor);
- processor.parseOverride(orideResource);
- processor.processOverride();
- }
+ //process override-web.xml
+ descriptorProcessor.process(metaData.getOverrideWeb());
+ */
}
public void postConfigure(WebAppContext context) throws Exception
{
- context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, null);
- context.setAttribute(WebXmlProcessor.METADATA_COMPLETE, null);
- context.setAttribute(WebXmlProcessor.WEBXML_VERSION, null);
- context.setAttribute(WebXmlProcessor.WEBXML_CLASSNAMES, null);
+ context.setAttribute(MetaData.WEBXML_CLASSNAMES, null);
}
/* ------------------------------------------------------------------------------- */
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlProcessor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlProcessor.java
deleted file mode 100644
index 44bdb9f919..0000000000
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlProcessor.java
+++ /dev/null
@@ -1,1060 +0,0 @@
-// ========================================================================
-// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-
-package org.eclipse.jetty.webapp;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.EventListener;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.servlet.Servlet;
-import javax.servlet.UnavailableException;
-
-import org.eclipse.jetty.http.security.Constraint;
-import org.eclipse.jetty.security.ConstraintAware;
-import org.eclipse.jetty.security.ConstraintMapping;
-import org.eclipse.jetty.security.SecurityHandler;
-import org.eclipse.jetty.security.authentication.FormAuthenticator;
-import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.FilterMapping;
-import org.eclipse.jetty.servlet.ServletHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.servlet.ServletMapping;
-import org.eclipse.jetty.util.LazyList;
-import org.eclipse.jetty.util.Loader;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.jetty.xml.XmlParser;
-
-
-
-/**
- * WebXmlProcessor
- *
- */
-public class WebXmlProcessor
-{
- public static final String WEB_PROCESSOR = "org.eclipse.jetty.webProcessor";
- public static final String METADATA_COMPLETE = "org.eclipse.jetty.metadataComplete";
- public static final String WEBXML_VERSION = "org.eclipse.jetty.webXmlVersion";
- public static final String WEBXML_CLASSNAMES = "org.eclipse.jetty.webXmlClassNames";
-
- protected WebAppContext _context;
- protected XmlParser _xmlParser;
- protected Descriptor _webDefaultsRoot;
- protected Descriptor _webXmlRoot;
- protected List<Descriptor> _webFragmentRoots = new ArrayList<Descriptor>();
- protected Descriptor _webOverrideRoot;
-
- protected ServletHandler _servletHandler;
- protected SecurityHandler _securityHandler;
- protected Object _filters;
- protected Object _filterMappings;
- protected Object _servlets;
- protected Object _servletMappings;
- protected Object _listeners;
- protected Object _welcomeFiles;
- protected Set<String> _newRoles = new HashSet<String>();
- protected List<ConstraintMapping> _newConstraintMappings;
- protected Map _errorPages;
- protected boolean _hasJSP;
- protected String _jspServletName;
- protected String _jspServletClass;
- protected boolean _defaultWelcomeFileList;
-
-
- public class Descriptor
- {
- protected Resource _xml;
- protected XmlParser.Node _root;
- protected boolean _metadataComplete;
- protected boolean _hasOrdering;
- protected int _version;
- protected ArrayList<String> _classNames;
-
- public Descriptor (Resource xml)
- {
- _xml = xml;
- }
-
- public void parse ()
- throws Exception
- {
- if (_root == null)
- {
- _root = _xmlParser.parse(_xml.getURL().toString());
- processVersion();
- processOrdering();
- }
- }
-
- public boolean isMetaDataComplete()
- {
- return _metadataComplete;
- }
-
-
- public XmlParser.Node getRoot ()
- {
- return _root;
- }
-
- public int getVersion ()
- {
- return _version;
- }
-
- public Resource getResource ()
- {
- return _xml;
- }
-
- public void process()
- throws Exception
- {
- WebXmlProcessor.this.process(_root);
- }
-
- private void processVersion ()
- {
- String version = _root.getAttribute("version", "DTD");
- if ("2.5".equals(version))
- _version = 25;
- else if ("2.4".equals(version))
- _version = 24;
- else if ("3.0".equals(version))
- _version = 30;
- else if ("DTD".equals(version))
- {
- _version = 23;
- String dtd = _xmlParser.getDTD();
- if (dtd != null && dtd.indexOf("web-app_2_2") >= 0) _version = 22;
- }
-
- if (_version < 25)
- _metadataComplete = true; // does not apply before 2.5
- else
- _metadataComplete = Boolean.valueOf((String)_root.getAttribute("metadata-complete", "false")).booleanValue();
-
- Log.debug(_xml.toString()+": Calculated metadatacomplete = " + _metadataComplete + " with version=" + version);
- }
-
- private void processOrdering ()
- {
- //TODO
- }
-
- private void processClassNames ()
- {
- _classNames = new ArrayList<String>();
- Iterator iter = _root.iterator();
-
- while (iter.hasNext())
- {
- Object o = iter.next();
- if (!(o instanceof XmlParser.Node)) continue;
- XmlParser.Node node = (XmlParser.Node) o;
- String name = node.getTag();
- if ("servlet".equals(name))
- {
- String className = node.getString("servlet-class", false, true);
- if (className != null)
- _classNames.add(className);
- }
- else if ("filter".equals(name))
- {
- String className = node.getString("filter-class", false, true);
- if (className != null)
- _classNames.add(className);
- }
- else if ("listener".equals(name))
- {
- String className = node.getString("listener-class", false, true);
- if (className != null)
- _classNames.add(className);
- }
- }
- }
-
- public ArrayList<String> getClassNames ()
- {
- return _classNames;
- }
- }
-
-
-
-
- public static XmlParser webXmlParser() throws ClassNotFoundException
- {
- XmlParser xmlParser=new XmlParser();
- //set up cache of DTDs and schemas locally
- URL dtd22=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_2.dtd",true);
- URL dtd23=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_3.dtd",true);
- URL j2ee14xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/j2ee_1_4.xsd",true);
- URL webapp24xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_4.xsd",true);
- URL webapp25xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_5.xsd",true);
- URL webapp30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_3_0.xsd",true);
- URL webcommon30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-common_3_0.xsd",true);
- URL webfragment30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-fragment_3_0.xsd",true);
- URL schemadtd=Loader.getResource(Servlet.class,"javax/servlet/resources/XMLSchema.dtd",true);
- URL xmlxsd=Loader.getResource(Servlet.class,"javax/servlet/resources/xml.xsd",true);
- URL webservice11xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/j2ee_web_services_client_1_1.xsd",true);
- URL webservice12xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/javaee_web_services_client_1_2.xsd",true);
- URL datatypesdtd=Loader.getResource(Servlet.class,"javax/servlet/resources/datatypes.dtd",true);
-
- URL jsp20xsd = null;
- URL jsp21xsd = null;
-
- try
- {
- Class jsp_page = Loader.loadClass(WebXmlConfiguration.class, "javax.servlet.jsp.JspPage");
- jsp20xsd = jsp_page.getResource("/javax/servlet/resources/jsp_2_0.xsd");
- jsp21xsd = jsp_page.getResource("/javax/servlet/resources/jsp_2_1.xsd");
- }
- catch (Exception e)
- {
- Log.ignore(e);
- }
- finally
- {
- if (jsp20xsd == null) jsp20xsd = Loader.getResource(Servlet.class, "javax/servlet/resources/jsp_2_0.xsd", true);
- if (jsp21xsd == null) jsp21xsd = Loader.getResource(Servlet.class, "javax/servlet/resources/jsp_2_1.xsd", true);
- }
-
- redirect(xmlParser,"web-app_2_2.dtd",dtd22);
- redirect(xmlParser,"-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",dtd22);
- redirect(xmlParser,"web.dtd",dtd23);
- redirect(xmlParser,"web-app_2_3.dtd",dtd23);
- redirect(xmlParser,"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",dtd23);
- redirect(xmlParser,"XMLSchema.dtd",schemadtd);
- redirect(xmlParser,"http://www.w3.org/2001/XMLSchema.dtd",schemadtd);
- redirect(xmlParser,"-//W3C//DTD XMLSCHEMA 200102//EN",schemadtd);
- redirect(xmlParser,"jsp_2_0.xsd",jsp20xsd);
- redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/jsp_2_0.xsd",jsp20xsd);
- redirect(xmlParser,"jsp_2_1.xsd",jsp21xsd);
- redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/jsp_2_1.xsd",jsp21xsd);
- redirect(xmlParser,"j2ee_1_4.xsd",j2ee14xsd);
- redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/j2ee_1_4.xsd",j2ee14xsd);
- redirect(xmlParser,"web-app_2_4.xsd",webapp24xsd);
- redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd",webapp24xsd);
- redirect(xmlParser,"web-app_2_5.xsd",webapp25xsd);
- redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd",webapp25xsd);
- redirect(xmlParser,"web-app_3_0.xsd",webapp30xsd);
- redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd",webapp30xsd);
- redirect(xmlParser,"web-common_3_0.xsd",webcommon30xsd);
- redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-common_3_0.xsd",webcommon30xsd);
- redirect(xmlParser,"web-fragment_3_0.xsd",webfragment30xsd);
- redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd",webfragment30xsd);
- redirect(xmlParser,"xml.xsd",xmlxsd);
- redirect(xmlParser,"http://www.w3.org/2001/xml.xsd",xmlxsd);
- redirect(xmlParser,"datatypes.dtd",datatypesdtd);
- redirect(xmlParser,"http://www.w3.org/2001/datatypes.dtd",datatypesdtd);
- redirect(xmlParser,"j2ee_web_services_client_1_1.xsd",webservice11xsd);
- redirect(xmlParser,"http://www.ibm.com/webservices/xsd/j2ee_web_services_client_1_1.xsd",webservice11xsd);
- redirect(xmlParser,"javaee_web_services_client_1_2.xsd",webservice12xsd);
- redirect(xmlParser,"http://www.ibm.com/webservices/xsd/javaee_web_services_client_1_2.xsd",webservice12xsd);
-
- return xmlParser;
- }
-
- /* ------------------------------------------------------------------------------- */
- protected static void redirect(XmlParser parser, String resource, URL source)
- {
- if (source != null) parser.redirectEntity(resource, source);
- }
-
-
- public WebXmlProcessor (WebAppContext context) throws ClassNotFoundException
- {
- _context = context;
- _xmlParser = webXmlParser();
- }
-
- public void parseDefaults (Resource webDefaults)
- throws Exception
- {
- _webDefaultsRoot = new Descriptor(webDefaults);
- _webDefaultsRoot.parse();
- }
-
- public void parseWebXml (Resource webXml)
- throws Exception
- {
- _webXmlRoot = new Descriptor(webXml);
- _webXmlRoot.parse();
- _webXmlRoot.processClassNames();
- _context.setAttribute(METADATA_COMPLETE, Boolean.valueOf(_webXmlRoot.isMetaDataComplete()));
- _context.setAttribute(WEBXML_VERSION, Integer.valueOf(_webXmlRoot.getVersion()));
- _context.setAttribute(WEBXML_CLASSNAMES, _webXmlRoot.getClassNames());
- }
-
- public void parseFragment (Resource fragment)
- throws Exception
- {
- if (_webXmlRoot.isMetaDataComplete())
- return; //do not process anything else if main web.xml file is complete
-
- //Metadata-complete is not set, or there is no web.xml
- Descriptor frag = new Descriptor(fragment);
- frag.parse();
- _webFragmentRoots.add(frag);
- }
-
- public void parseOverride (Resource override)
- throws Exception
- {
- _xmlParser.setValidating(false);
- _webOverrideRoot = new Descriptor(override);
- _webOverrideRoot.parse();
- }
-
-
- public void processDefaults ()
- throws Exception
- {
- _webDefaultsRoot.process();
- _defaultWelcomeFileList = _context.getWelcomeFiles() != null;
- }
-
- public void processWebXml ()
- throws Exception
- {
- if (_webXmlRoot!=null)
- _webXmlRoot.process();
- }
-
- public void processFragments ()
- throws Exception
- {
- for (Descriptor frag : _webFragmentRoots)
- {
- frag.process();
- }
- }
-
- public void processOverride ()
- throws Exception
- {
- _webOverrideRoot.process();
- }
-
- public Descriptor getWebXml ()
- {
- return _webXmlRoot;
- }
-
- public Descriptor getOverrideWeb ()
- {
- return _webOverrideRoot;
- }
-
- public Descriptor getWebDefault ()
- {
- return _webDefaultsRoot;
- }
-
- public List<Descriptor> getFragments ()
- {
- return _webFragmentRoots;
- }
-
-
- public void process (XmlParser.Node config)
- throws Exception
- {
-
- //Get the current objects from the context
- _servletHandler = _context.getServletHandler();
- _securityHandler = (SecurityHandler)_context.getSecurityHandler();
- _filters = LazyList.array2List(_servletHandler.getFilters());
- _filterMappings = LazyList.array2List(_servletHandler.getFilterMappings());
- _servlets = LazyList.array2List(_servletHandler.getServlets());
- _servletMappings = LazyList.array2List(_servletHandler.getServletMappings());
- _listeners = LazyList.array2List(_context.getEventListeners());
- _welcomeFiles = LazyList.array2List(_context.getWelcomeFiles());
-
- _newConstraintMappings=new ArrayList<ConstraintMapping>();
- _newRoles=new HashSet<String>();
-
- _errorPages = _context.getErrorHandler() instanceof ErrorPageErrorHandler ? ((ErrorPageErrorHandler)_context.getErrorHandler()).getErrorPages() : null;
-
- Iterator iter = config.iterator();
- XmlParser.Node node = null;
- while (iter.hasNext())
- {
- try
- {
- Object o = iter.next();
- if (!(o instanceof XmlParser.Node)) continue;
- node = (XmlParser.Node) o;
- String name = node.getTag();
- initWebXmlElement(name, node);
- }
- catch (ClassNotFoundException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- Log.warn("Configuration problem at " + node, e);
- throw new UnavailableException("Configuration problem");
- }
- }
-
- //Set the context with the results of the processing
- _servletHandler.setFilters((FilterHolder[]) LazyList.toArray(_filters, FilterHolder.class));
- _servletHandler.setFilterMappings((FilterMapping[]) LazyList.toArray(_filterMappings, FilterMapping.class));
- _servletHandler.setServlets((ServletHolder[]) LazyList.toArray(_servlets, ServletHolder.class));
- _servletHandler.setServletMappings((ServletMapping[]) LazyList.toArray(_servletMappings, ServletMapping.class));
- _context.setEventListeners((EventListener[]) LazyList.toArray(_listeners, EventListener.class));
- _context.setWelcomeFiles((String[]) LazyList.toArray(_welcomeFiles, String.class));
- // TODO jaspi check this
- if (_securityHandler instanceof ConstraintAware)
- {
- for (String role : _newRoles)
- ((ConstraintAware)_securityHandler).addRole(role);
- for (ConstraintMapping mapping : _newConstraintMappings)
- ((ConstraintAware)_securityHandler).addConstraintMapping(mapping);
- }
-
- if (_errorPages != null && _context.getErrorHandler() instanceof ErrorPageErrorHandler)
- ((ErrorPageErrorHandler)_context.getErrorHandler()).setErrorPages(_errorPages);
- }
-
-
-
-
- /* ------------------------------------------------------------ */
- /**
- * Handle web.xml element. This method is called for each top level element
- * within the web.xml file. It may be specialized by derived WebAppHandlers
- * to provide additional configuration and handling.
- *
- * @param element The element name
- * @param node The node containing the element.
- */
- protected void initWebXmlElement(String element, XmlParser.Node node) throws Exception
- {
- if ("display-name".equals(element))
- initDisplayName(node);
- else if ("description".equals(element))
- {
- }
- else if ("context-param".equals(element))
- initContextParam(node);
- else if ("servlet".equals(element))
- initServlet(node);
- else if ("servlet-mapping".equals(element))
- initServletMapping(node);
- else if ("session-config".equals(element))
- initSessionConfig(node);
- else if ("mime-mapping".equals(element))
- initMimeConfig(node);
- else if ("welcome-file-list".equals(element))
- initWelcomeFileList(node);
- else if ("locale-encoding-mapping-list".equals(element))
- initLocaleEncodingList(node);
- else if ("error-page".equals(element))
- initErrorPage(node);
- else if ("taglib".equals(element))
- initTagLib(node);
- else if ("jsp-config".equals(element))
- initJspConfig(node);
- else if ("resource-ref".equals(element))
- {
- if (Log.isDebugEnabled()) Log.debug("No implementation: " + node);
- }
- else if ("security-constraint".equals(element))
- initSecurityConstraint(node);
- else if ("login-config".equals(element))
- initLoginConfig(node);
- else if ("security-role".equals(element))
- initSecurityRole(node);
- else if ("filter".equals(element))
- initFilter(node);
- else if ("filter-mapping".equals(element))
- initFilterMapping(node);
- else if ("listener".equals(element))
- initListener(node);
- else if ("distributable".equals(element))
- initDistributable(node);
- else if ("web-fragment".equals(element))
- {
- }
- else
- {
- if (Log.isDebugEnabled())
- {
- Log.debug("Element {} not handled in {}", element, this);
- Log.debug(node.toString());
- }
- }
- }
-
- /* ------------------------------------------------------------ */
- protected void initDisplayName(XmlParser.Node node)
- {
- _context.setDisplayName(node.toString(false, true));
- }
-
- /* ------------------------------------------------------------ */
- protected void initContextParam(XmlParser.Node node)
- {
- String name = node.getString("param-name", false, true);
- String value = node.getString("param-value", false, true);
- if (Log.isDebugEnabled()) Log.debug("ContextParam: " + name + "=" + value);
- _context.getInitParams().put(name, value);
- }
-
- /* ------------------------------------------------------------ */
- protected void initFilter(XmlParser.Node node)
- {
- String name = node.getString("filter-name", false, true);
- FilterHolder holder = _servletHandler.getFilter(name);
- if (holder == null)
- {
- holder = _servletHandler.newFilterHolder();
- holder.setName(name);
- _filters = LazyList.add(_filters, holder);
- }
-
- String filter_class = node.getString("filter-class", false, true);
- if (filter_class != null) holder.setClassName(filter_class);
-
- Iterator iter = node.iterator("init-param");
- while (iter.hasNext())
- {
- XmlParser.Node paramNode = (XmlParser.Node) iter.next();
- String pname = paramNode.getString("param-name", false, true);
- String pvalue = paramNode.getString("param-value", false, true);
- holder.setInitParameter(pname, pvalue);
- }
-
- String async=node.getString("async-supported",false,true);
- if (async!=null)
- holder.setAsyncSupported(async.length()==0||Boolean.valueOf(async));
-
- String timeout=node.getString("async-timeout",false,true);
- // TODO set it
- }
-
- /* ------------------------------------------------------------ */
- protected void initFilterMapping(XmlParser.Node node)
- {
- String filter_name = node.getString("filter-name", false, true);
-
- FilterMapping mapping = new FilterMapping();
-
- mapping.setFilterName(filter_name);
-
- ArrayList paths = new ArrayList();
- Iterator iter = node.iterator("url-pattern");
- while (iter.hasNext())
- {
- String p = ((XmlParser.Node) iter.next()).toString(false, true);
- p = normalizePattern(p);
- paths.add(p);
- }
- mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
-
- ArrayList names = new ArrayList();
- iter = node.iterator("servlet-name");
- while (iter.hasNext())
- {
- String n = ((XmlParser.Node) iter.next()).toString(false, true);
- names.add(n);
- }
- mapping.setServletNames((String[]) names.toArray(new String[names.size()]));
-
- int dispatcher=FilterMapping.DEFAULT;
- iter=node.iterator("dispatcher");
- while(iter.hasNext())
- {
- String d=((XmlParser.Node)iter.next()).toString(false,true);
- dispatcher|=FilterMapping.dispatch(d);
- }
- mapping.setDispatches(dispatcher);
-
- _filterMappings = LazyList.add(_filterMappings, mapping);
- }
-
- /* ------------------------------------------------------------ */
- protected String normalizePattern(String p)
- {
- if (p != null && p.length() > 0 && !p.startsWith("/") && !p.startsWith("*")) return "/" + p;
- return p;
- }
-
- /* ------------------------------------------------------------ */
- protected void initServlet(XmlParser.Node node)
- {
- String id = node.getAttribute("id");
-
- // initialize holder
- String servlet_name = node.getString("servlet-name", false, true);
- ServletHolder holder = _servletHandler.getServlet(servlet_name);
- if (holder == null)
- {
- holder = _servletHandler.newServletHolder();
- holder.setName(servlet_name);
- _servlets = LazyList.add(_servlets, holder);
- }
-
- // init params
- Iterator iParamsIter = node.iterator("init-param");
- while (iParamsIter.hasNext())
- {
- XmlParser.Node paramNode = (XmlParser.Node) iParamsIter.next();
- String pname = paramNode.getString("param-name", false, true);
- String pvalue = paramNode.getString("param-value", false, true);
- holder.setInitParameter(pname, pvalue);
- }
-
- String servlet_class = node.getString("servlet-class", false, true);
-
- // Handle JSP
- if (id != null && id.equals("jsp"))
- {
- _jspServletName = servlet_name;
- _jspServletClass = servlet_class;
- try
- {
- Loader.loadClass(this.getClass(), servlet_class);
- _hasJSP = true;
- }
- catch (ClassNotFoundException e)
- {
- Log.info("NO JSP Support for {}, did not find {}", _context.getContextPath(), servlet_class);
- _hasJSP = false;
- _jspServletClass = servlet_class = "org.eclipse.jetty.servlet.NoJspServlet";
- }
-
- // set the JSP log
- if (_hasJSP)
- {
- try
- {
- Class<?> logFactory = Loader.loadClass(this.getClass(),"org.eclipse.jetty.jsp.JettyLog");
- Method init = logFactory.getMethod("init");
- Log.debug("Init JSP loggging "+init);
- init.invoke(null);
- }
- catch (Exception e)
- {
- Log.warn(e.toString());
- Log.ignore(e);
- }
- }
-
- if (holder.getInitParameter("scratchdir") == null)
- {
- File tmp = _context.getTempDirectory();
- File scratch = new File(tmp, "jsp");
- if (!scratch.exists()) scratch.mkdir();
- holder.setInitParameter("scratchdir", scratch.getAbsolutePath());
-
- if ("?".equals(holder.getInitParameter("classpath")))
- {
- String classpath = _context.getClassPath();
- Log.debug("classpath=" + classpath);
- if (classpath != null) holder.setInitParameter("classpath", classpath);
- }
- }
- }
- if (servlet_class != null) holder.setClassName(servlet_class);
-
- // Handler JSP file
- String jsp_file = node.getString("jsp-file", false, true);
- if (jsp_file != null)
- {
- holder.setForcedPath(jsp_file);
- holder.setClassName(_jspServletClass);
- }
-
- // handle startup
- XmlParser.Node startup = node.get("load-on-startup");
- if (startup != null)
- {
- String s = startup.toString(false, true).toLowerCase();
- if (s.startsWith("t"))
- {
- Log.warn("Deprecated boolean load-on-startup. Please use integer");
- holder.setInitOrder(1);
- }
- else
- {
- int order = 0;
- try
- {
- if (s != null && s.trim().length() > 0) order = Integer.parseInt(s);
- }
- catch (Exception e)
- {
- Log.warn("Cannot parse load-on-startup " + s + ". Please use integer");
- Log.ignore(e);
- }
- holder.setInitOrder(order);
- }
- }
-
- Iterator sRefsIter = node.iterator("security-role-ref");
- while (sRefsIter.hasNext())
- {
- XmlParser.Node securityRef = (XmlParser.Node) sRefsIter.next();
- String roleName = securityRef.getString("role-name", false, true);
- String roleLink = securityRef.getString("role-link", false, true);
- if (roleName != null && roleName.length() > 0 && roleLink != null && roleLink.length() > 0)
- {
- if (Log.isDebugEnabled()) Log.debug("link role " + roleName + " to " + roleLink + " for " + this);
- holder.setUserRoleLink(roleName, roleLink);
- }
- else
- {
- Log.warn("Ignored invalid security-role-ref element: " + "servlet-name=" + holder.getName() + ", " + securityRef);
- }
- }
-
- XmlParser.Node run_as = node.get("run-as");
- if (run_as != null)
- {
- String roleName = run_as.getString("role-name", false, true);
- if (roleName != null)
- holder.setRunAsRole(roleName);
- }
-
- String async=node.getString("async-supported",false,true);
- if (async!=null)
- holder.setAsyncSupported(async.length()==0||Boolean.valueOf(async));
-
- String timeout=node.getString("async-timeout",false,true);
- // TODO set it
- }
-
- /* ------------------------------------------------------------ */
- protected void initServletMapping(XmlParser.Node node)
- {
- String servlet_name = node.getString("servlet-name", false, true);
- ServletMapping mapping = new ServletMapping();
- mapping.setServletName(servlet_name);
-
- ArrayList paths = new ArrayList();
- Iterator iter = node.iterator("url-pattern");
- while (iter.hasNext())
- {
- String p = ((XmlParser.Node) iter.next()).toString(false, true);
- p = normalizePattern(p);
- paths.add(p);
- }
- mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
-
- _servletMappings = LazyList.add(_servletMappings, mapping);
- }
-
- /* ------------------------------------------------------------ */
- protected void initListener(XmlParser.Node node)
- {
- String className = node.getString("listener-class", false, true);
- Object listener = null;
- try
- {
- Class listenerClass = _context.loadClass(className);
- listener = newListenerInstance(listenerClass);
- if (!(listener instanceof EventListener))
- {
- Log.warn("Not an EventListener: " + listener);
- return;
- }
- _listeners = LazyList.add(_listeners, listener);
- }
- catch (Exception e)
- {
- Log.warn("Could not instantiate listener " + className, e);
- return;
- }
- }
-
- /* ------------------------------------------------------------ */
- protected Object newListenerInstance(Class clazz) throws InstantiationException, IllegalAccessException
- {
- return clazz.newInstance();
- }
-
- /* ------------------------------------------------------------ */
- protected void initDistributable(XmlParser.Node node)
- {
- // the element has no content, so its simple presence
- // indicates that the webapp is distributable...
- if (!_context.isDistributable())
- _context.setDistributable(true);
- }
-
- /* ------------------------------------------------------------ */
- protected void initSessionConfig(XmlParser.Node node)
- {
- XmlParser.Node tNode = node.get("session-timeout");
- if (tNode != null)
- {
- int timeout = Integer.parseInt(tNode.toString(false, true));
- _context.getSessionHandler().getSessionManager().setMaxInactiveInterval(timeout * 60);
- }
- }
-
- /* ------------------------------------------------------------ */
- protected void initMimeConfig(XmlParser.Node node)
- {
- String extension = node.getString("extension", false, true);
- if (extension != null && extension.startsWith(".")) extension = extension.substring(1);
- String mimeType = node.getString("mime-type", false, true);
- _context.getMimeTypes().addMimeMapping(extension, mimeType);
- }
-
- /* ------------------------------------------------------------ */
- protected void initWelcomeFileList(XmlParser.Node node)
- {
- if (_defaultWelcomeFileList)
- _welcomeFiles = null; // erase welcome files from default web.xml
-
- _defaultWelcomeFileList = false;
- Iterator iter = node.iterator("welcome-file");
- while (iter.hasNext())
- {
- XmlParser.Node indexNode = (XmlParser.Node) iter.next();
- String welcome = indexNode.toString(false, true);
- _welcomeFiles = LazyList.add(_welcomeFiles, welcome);
- }
- }
-
- /* ------------------------------------------------------------ */
- protected void initLocaleEncodingList(XmlParser.Node node)
- {
- Iterator iter = node.iterator("locale-encoding-mapping");
- while (iter.hasNext())
- {
- XmlParser.Node mapping = (XmlParser.Node) iter.next();
- String locale = mapping.getString("locale", false, true);
- String encoding = mapping.getString("encoding", false, true);
- _context.addLocaleEncoding(locale, encoding);
- }
- }
-
- /* ------------------------------------------------------------ */
- protected void initErrorPage(XmlParser.Node node)
- {
- String error = node.getString("error-code", false, true);
- if (error == null || error.length() == 0) error = node.getString("exception-type", false, true);
- String location = node.getString("location", false, true);
-
- if (_errorPages == null)
- _errorPages = new HashMap();
- _errorPages.put(error, location);
- }
-
- /* ------------------------------------------------------------ */
- protected void initTagLib(XmlParser.Node node)
- {
- String uri = node.getString("taglib-uri", false, true);
- String location = node.getString("taglib-location", false, true);
-
- _context.setResourceAlias(uri, location);
- }
-
- /* ------------------------------------------------------------ */
- protected void initJspConfig(XmlParser.Node node)
- {
- for (int i = 0; i < node.size(); i++)
- {
- Object o = node.get(i);
- if (o instanceof XmlParser.Node && "taglib".equals(((XmlParser.Node) o).getTag())) initTagLib((XmlParser.Node) o);
- }
-
- // Map URLs from jsp property groups to JSP servlet.
- // this is more JSP stupidness creaping into the servlet spec
- Iterator iter = node.iterator("jsp-property-group");
- Object paths = null;
- while (iter.hasNext())
- {
- XmlParser.Node group = (XmlParser.Node) iter.next();
- Iterator iter2 = group.iterator("url-pattern");
- while (iter2.hasNext())
- {
- String url = ((XmlParser.Node) iter2.next()).toString(false, true);
- url = normalizePattern(url);
- paths = LazyList.add(paths, url);
- }
- }
-
- if (LazyList.size(paths) > 0)
- {
- String jspName = getJSPServletName();
- if (jspName != null)
- {
- ServletMapping mapping = new ServletMapping();
- mapping.setServletName(jspName);
- mapping.setPathSpecs(LazyList.toStringArray(paths));
- _servletMappings = LazyList.add(_servletMappings, mapping);
- }
- }
- }
-
- /* ------------------------------------------------------------ */
- protected void initSecurityConstraint(XmlParser.Node node)
- {
- Constraint scBase = new Constraint();
-
- try
- {
- XmlParser.Node auths = node.get("auth-constraint");
-
- if (auths != null)
- {
- scBase.setAuthenticate(true);
- // auth-constraint
- Iterator iter = auths.iterator("role-name");
- Object roles = null;
- while (iter.hasNext())
- {
- String role = ((XmlParser.Node) iter.next()).toString(false, true);
- roles = LazyList.add(roles, role);
- }
- scBase.setRoles(LazyList.toStringArray(roles));
- }
-
- XmlParser.Node data = node.get("user-data-constraint");
- if (data != null)
- {
- data = data.get("transport-guarantee");
- String guarantee = data.toString(false, true).toUpperCase();
- if (guarantee == null || guarantee.length() == 0 || "NONE".equals(guarantee))
- scBase.setDataConstraint(Constraint.DC_NONE);
- else if ("INTEGRAL".equals(guarantee))
- scBase.setDataConstraint(Constraint.DC_INTEGRAL);
- else if ("CONFIDENTIAL".equals(guarantee))
- scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
- else
- {
- Log.warn("Unknown user-data-constraint:" + guarantee);
- scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
- }
- }
- Iterator iter = node.iterator("web-resource-collection");
- while (iter.hasNext())
- {
- XmlParser.Node collection = (XmlParser.Node) iter.next();
- String name = collection.getString("web-resource-name", false, true);
- Constraint sc = (Constraint) scBase.clone();
- sc.setName(name);
-
- Iterator iter2 = collection.iterator("url-pattern");
- while (iter2.hasNext())
- {
- String url = ((XmlParser.Node) iter2.next()).toString(false, true);
- url = normalizePattern(url);
-
- Iterator iter3 = collection.iterator("http-method");
- if (iter3.hasNext())
- {
- while (iter3.hasNext())
- {
- String method = ((XmlParser.Node) iter3.next()).toString(false, true);
- ConstraintMapping mapping = new ConstraintMapping();
- mapping.setMethod(method);
- mapping.setPathSpec(url);
- mapping.setConstraint(sc);
- _newConstraintMappings.add(mapping);
- }
- }
- else
- {
- ConstraintMapping mapping = new ConstraintMapping();
- mapping.setPathSpec(url);
- mapping.setConstraint(sc);
- _newConstraintMappings.add(mapping);
- }
- }
- }
- }
- catch (CloneNotSupportedException e)
- {
- Log.warn(e);
- }
-
- }
-
- /* ------------------------------------------------------------ */
- protected void initLoginConfig(XmlParser.Node node) throws Exception
- {
- XmlParser.Node method = node.get("auth-method");
- if (method != null)
- {
- XmlParser.Node name = node.get("realm-name");
- _securityHandler.setRealmName(name == null ? "default" : name.toString(false, true));
- _securityHandler.setAuthMethod(method.toString(false, true));
-
-
- if (Constraint.__FORM_AUTH.equals(_securityHandler.getAuthMethod()))
- {
- XmlParser.Node formConfig = node.get("form-login-config");
- if (formConfig != null)
- {
- String loginPageName = null;
- XmlParser.Node loginPage = formConfig.get("form-login-page");
- if (loginPage != null)
- loginPageName = loginPage.toString(false, true);
- String errorPageName = null;
- XmlParser.Node errorPage = formConfig.get("form-error-page");
- if (errorPage != null)
- errorPageName = errorPage.toString(false, true);
- _securityHandler.setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
- _securityHandler.setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
- }
- else
- {
- throw new IllegalArgumentException("!form-login-config");
- }
- }
- }
- }
-
- /* ------------------------------------------------------------ */
- protected void initSecurityRole(XmlParser.Node node)
- {
- XmlParser.Node roleNode = node.get("role-name");
- String role = roleNode.toString(false, true);
- _newRoles.add(role);
- }
-
- /* ------------------------------------------------------------ */
- protected String getJSPServletName()
- {
- if (_jspServletName == null)
- {
- Map.Entry entry = _context.getServletHandler().getHolderEntry("test.jsp");
- if (entry != null)
- {
- ServletHolder holder = (ServletHolder) entry.getValue();
- _jspServletName = holder.getName();
- }
- }
- return _jspServletName;
- }
-}
diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java
new file mode 100644
index 0000000000..7e20c21da2
--- /dev/null
+++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java
@@ -0,0 +1,939 @@
+// ========================================================================
+// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.webapp;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.webapp.MetaData.AbsoluteOrdering;
+import org.eclipse.jetty.webapp.MetaData.RelativeOrdering;
+
+/**
+ * OrderingTest
+ *
+ *
+ */
+public class OrderingTest extends TestCase
+{
+ public class TestResource extends Resource
+ {
+ public String _name;
+
+ public TestResource (String name)
+ {
+ _name =name;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#addPath(java.lang.String)
+ */
+ public Resource addPath(String path) throws IOException, MalformedURLException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#delete()
+ */
+ public boolean delete() throws SecurityException
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#exists()
+ */
+ public boolean exists()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#getFile()
+ */
+ public File getFile() throws IOException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#getName()
+ */
+ public String getName()
+ {
+ return _name;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#getOutputStream()
+ */
+ public OutputStream getOutputStream() throws IOException, SecurityException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#getURL()
+ */
+ public URL getURL()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#isContainedIn(org.eclipse.jetty.util.resource.Resource)
+ */
+ public boolean isContainedIn(Resource r) throws MalformedURLException
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#isDirectory()
+ */
+ public boolean isDirectory()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#lastModified()
+ */
+ public long lastModified()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#length()
+ */
+ public long length()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#list()
+ */
+ public String[] list()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#release()
+ */
+ public void release()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * @see org.eclipse.jetty.util.resource.Resource#renameTo(org.eclipse.jetty.util.resource.Resource)
+ */
+ public boolean renameTo(Resource dest) throws SecurityException
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ }
+
+
+ public void testRelativeOrdering0 ()
+ throws Exception
+ {
+ //Example from ServletSpec p.70
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ List<Resource> resources = new ArrayList<Resource>();
+ metaData._ordering = metaData.new RelativeOrdering();
+
+ //A: after others, after C
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1, f1);
+ f1._otherType = FragmentDescriptor.OtherType.After;
+ //((RelativeOrdering)metaData._ordering).addAfterOthers(r1);
+ f1._afters.add("C");
+
+ //B: before others
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2, f2);
+ f2._otherType = FragmentDescriptor.OtherType.Before;
+ //((RelativeOrdering)metaData._ordering).addBeforeOthers(r2);
+
+ //C: after others
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3, f3);
+ f3._otherType = FragmentDescriptor.OtherType.After;
+ //((RelativeOrdering)metaData._ordering).addAfterOthers(r3);
+
+ //D: no ordering
+ TestResource jar4 = new TestResource("D");
+ resources.add(jar4);
+ TestResource r4 = new TestResource("D/web-fragment.xml");
+ FragmentDescriptor f4 = new FragmentDescriptor(r4, metaData);
+ f4._name="D";
+ metaData._webFragmentNameMap.put(f4._name, f4);
+ metaData._webFragmentResourceMap.put(jar4, f4);
+ f4._otherType = FragmentDescriptor.OtherType.None;
+ //((RelativeOrdering)metaData._ordering).addNoOthers(r4);
+
+ //E: no ordering
+ TestResource jar5 = new TestResource("E");
+ resources.add(jar5);
+ TestResource r5 = new TestResource("E/web-fragment.xml");
+ FragmentDescriptor f5 = new FragmentDescriptor(r5, metaData);
+ f5._name="E";
+ metaData._webFragmentNameMap.put(f5._name, f5);
+ metaData._webFragmentResourceMap.put(jar5, f5);
+ f5._otherType = FragmentDescriptor.OtherType.None;
+ //((RelativeOrdering)metaData._ordering).addNoOthers(r5);
+
+ //F: before others, before B
+ TestResource jar6 = new TestResource("F");
+ resources.add(jar6);
+ TestResource r6 = new TestResource("F/web-fragment.xml");
+ FragmentDescriptor f6 = new FragmentDescriptor(r6, metaData);
+ f6._name="F";
+ metaData._webFragmentNameMap.put(f6._name, f6);
+ metaData._webFragmentResourceMap.put(jar6,f6);
+ f6._otherType = FragmentDescriptor.OtherType.Before;
+ //((RelativeOrdering)metaData._ordering).addBeforeOthers(r6);
+ f6._befores.add("B");
+
+ //
+ // p.70 outcome: F, B, D, E, C, A
+ //
+ String[] outcomes = {"FBDECA"};
+ List<Resource> orderedList = metaData._ordering.order(resources);
+
+ String result = "";
+ for (Resource r:orderedList)
+ result+=(((TestResource)r)._name);
+
+ if (!checkResult(result, outcomes))
+ fail("No outcome matched "+result);
+ }
+
+
+
+
+ public void testRelativeOrdering1 ()
+ throws Exception
+ {
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new RelativeOrdering();
+
+ //Example from ServletSpec p.70-71
+ //No name: after others, before C
+ TestResource jar1 = new TestResource("plain");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("plain/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = FragmentDescriptor.NAMELESS+"1";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1,f1);
+ f1._otherType = FragmentDescriptor.OtherType.After;
+ //((RelativeOrdering)metaData._ordering).addAfterOthers(f1);
+ f1._befores.add("C");
+
+ //B: before others
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2,f2);
+ f2._otherType = FragmentDescriptor.OtherType.Before;
+ //((RelativeOrdering)metaData._ordering).addBeforeOthers(f2);
+
+ //C: no ordering
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3,f3);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f3);
+ f3._otherType = FragmentDescriptor.OtherType.None;
+
+ //D: after others
+ TestResource jar4 = new TestResource("D");
+ resources.add(jar4);
+ TestResource r4 = new TestResource("D/web-fragment.xml");
+ FragmentDescriptor f4 = new FragmentDescriptor(r4, metaData);
+ f4._name="D";
+ metaData._webFragmentNameMap.put(f4._name, f4);
+ metaData._webFragmentResourceMap.put(jar4,f4);
+ //((RelativeOrdering)metaData._ordering).addAfterOthers(f4);
+ f4._otherType = FragmentDescriptor.OtherType.After;
+
+ //E: before others
+ TestResource jar5 = new TestResource("E");
+ resources.add(jar5);
+ TestResource r5 = new TestResource("E/web-fragment.xml");
+ FragmentDescriptor f5 = new FragmentDescriptor(r5, metaData);
+ f5._name="E";
+ metaData._webFragmentNameMap.put(f5._name, f5);
+ metaData._webFragmentResourceMap.put(jar5,f5);
+ //((RelativeOrdering)metaData._ordering).addBeforeOthers(f5);
+ f5._otherType = FragmentDescriptor.OtherType.Before;
+
+ //F: no ordering
+ TestResource jar6 = new TestResource("F");
+ resources.add(jar6);
+ TestResource r6 = new TestResource("F/web-fragment.xml");
+ FragmentDescriptor f6 = new FragmentDescriptor(r6, metaData);
+ f6._name="F";
+ metaData._webFragmentNameMap.put(f6._name, f6);
+ metaData._webFragmentResourceMap.put(jar6,f6);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f6);
+ f6._otherType = FragmentDescriptor.OtherType.None;
+
+ List<Resource> orderedList = metaData._ordering.order(resources);
+
+ // p.70-71 Possible outcomes are:
+ // B, E, F, noname, C, D
+ // B, E, F, noname, D, C
+ // E, B, F, noname, C, D
+ // E, B, F, noname, D, C
+ // E, B, F, D, noname, C
+ //
+ String[] outcomes = {"BEFplainCD",
+ "BEFplainDC",
+ "EBFplainCD",
+ "EBFplainDC",
+ "EBFDplain"};
+
+ String orderedNames = "";
+ for (Resource r:orderedList)
+ orderedNames+=(((TestResource)r)._name);
+
+ if (!checkResult(orderedNames, outcomes))
+ fail("No outcome matched "+orderedNames);
+ }
+
+
+ public void testRelativeOrdering2 ()
+ throws Exception
+ {
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new RelativeOrdering();
+
+ //Example from Spec p. 71-72
+
+ //A: after B
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1, f1);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f1);
+ f1._otherType = FragmentDescriptor.OtherType.None;
+ f1._afters.add("B");
+
+ //B: no order
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2, f2);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f2);
+ f2._otherType = FragmentDescriptor.OtherType.None;
+
+ //C: before others
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3,f3);
+ //((RelativeOrdering)metaData._ordering).addBeforeOthers(f3);
+ f3._otherType = FragmentDescriptor.OtherType.Before;
+
+ //D: no order
+ TestResource jar4 = new TestResource("D");
+ resources.add(jar4);
+ TestResource r4 = new TestResource("D/web-fragment.xml");
+ FragmentDescriptor f4 = new FragmentDescriptor(r4, metaData);
+ f4._name="D";
+ metaData._webFragmentNameMap.put(f4._name, f4);
+ metaData._webFragmentResourceMap.put(jar4, f4);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f4);
+ f4._otherType = FragmentDescriptor.OtherType.None;
+ //
+ // p.71-72 possible outcomes are:
+ // C,B,D,A
+ // C,D,B,A
+ // C,B,A,D
+ //
+ String[] outcomes = {"CBDA",
+ "CDBA",
+ "CBAD"};
+
+
+ List<Resource> orderedList = metaData._ordering.order(resources);
+ String result = "";
+ for (Resource r:orderedList)
+ result+=(((TestResource)r)._name);
+
+ if (!checkResult(result, outcomes))
+ fail ("No outcome matched "+result);
+ }
+
+
+ public void testRelativeOrdering3 ()
+ throws Exception
+ {
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new RelativeOrdering();
+
+ //A: after others, before C
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1, f1);
+ //((RelativeOrdering)metaData._ordering).addAfterOthers(f1);
+ f1._otherType = FragmentDescriptor.OtherType.After;
+ f1._befores.add("C");
+
+ //B: before others, before C
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2,f2);
+ //((RelativeOrdering)metaData._ordering).addBeforeOthers(f2);
+ f2._otherType = FragmentDescriptor.OtherType.Before;
+ f2._befores.add("C");
+
+ //C: no ordering
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3,f3);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f3);
+ f3._otherType = FragmentDescriptor.OtherType.None;
+
+ //result: BAC
+ String[] outcomes = {"BAC"};
+
+ List<Resource> orderedList = metaData._ordering.order(resources);
+ String result = "";
+ for (Resource r:orderedList)
+ result+=(((TestResource)r)._name);
+
+ if (!checkResult(result, outcomes))
+ fail ("No outcome matched "+result);
+ }
+
+ public void testCircular1 ()
+ throws Exception
+ {
+
+ //A: after B
+ //B: after A
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new RelativeOrdering();
+
+ //A: after B
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1, f1);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f1);
+ f1._otherType = FragmentDescriptor.OtherType.None;
+ f1._afters.add("B");
+
+ //B: after A
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2, f2);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f2);
+ f2._otherType = FragmentDescriptor.OtherType.None;
+ f2._afters.add("A");
+
+ try
+ {
+ List<Resource> orderedList = metaData._ordering.order(resources);
+ fail("No circularity detected");
+ }
+ catch (Exception e)
+ {
+ assertTrue (e instanceof IllegalStateException);
+ }
+ }
+
+
+
+
+ public void testInvalid1 ()
+ throws Exception
+ {
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new RelativeOrdering();
+
+ //A: after others, before C
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1,f1);
+ //((RelativeOrdering)metaData._ordering).addAfterOthers(r1);
+ f1._otherType = FragmentDescriptor.OtherType.After;
+ f1._befores.add("C");
+
+ //B: before others, after C
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2,f2);
+ //((RelativeOrdering)metaData._ordering).addBeforeOthers(r2);
+ f2._otherType = FragmentDescriptor.OtherType.Before;
+ f2._afters.add("C");
+
+ //C: no ordering
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3,f3);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(r3);
+ f3._otherType = FragmentDescriptor.OtherType.None;
+
+ try
+ {
+ List<Resource> orderedList = metaData._ordering.order(resources);
+ String result = "";
+ for (Resource r:orderedList)
+ result +=((TestResource)r)._name;
+ System.err.println("Invalid Result = "+result);
+ fail("A and B have an impossible relationship to C");
+ }
+ catch (Exception e)
+ {
+ assertTrue (e instanceof IllegalStateException);
+ }
+ }
+
+
+ public void testAbsoluteOrdering1 ()
+ throws Exception
+ {
+ //
+ // A,B,C,others
+ //
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new AbsoluteOrdering();
+ ((AbsoluteOrdering)metaData._ordering).add("A");
+ ((AbsoluteOrdering)metaData._ordering).add("B");
+ ((AbsoluteOrdering)metaData._ordering).add("C");
+ ((AbsoluteOrdering)metaData._ordering).addOthers();
+
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1,f1);
+
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2, f2);
+
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3, f3);
+
+ TestResource jar4 = new TestResource("D");
+ resources.add(jar4);
+ TestResource r4 = new TestResource("D/web-fragment.xml");
+ FragmentDescriptor f4 = new FragmentDescriptor((Resource)null, metaData);
+ f4._name="D";
+ metaData._webFragmentNameMap.put(f4._name, f4);
+ metaData._webFragmentResourceMap.put(jar4, f4);
+
+ TestResource jar5 = new TestResource("E");
+ resources.add(jar5);
+ TestResource r5 = new TestResource("E/web-fragment.xml");
+ FragmentDescriptor f5 = new FragmentDescriptor((Resource)null, metaData);
+ f5._name="E";
+ metaData._webFragmentNameMap.put(f5._name, f5);
+ metaData._webFragmentResourceMap.put(jar5, f5);
+
+ TestResource jar6 = new TestResource("plain");
+ resources.add(jar6);
+ TestResource r6 = new TestResource ("plain/web-fragment.xml");
+ FragmentDescriptor f6 = new FragmentDescriptor((Resource)null, metaData);
+ f6._name=FragmentDescriptor.NAMELESS+"1";
+ metaData._webFragmentNameMap.put(f6._name, f6);
+ metaData._webFragmentResourceMap.put(jar6, f6);
+
+ List<Resource> list = metaData._ordering.order(resources);
+
+ String[] outcomes = {"ABCDEplain"};
+ String result = "";
+ for (Resource r:list)
+ result += ((TestResource)r)._name;
+
+ if (!checkResult(result, outcomes))
+ fail("No outcome matched "+result);
+ }
+
+
+ public void testAbsoluteOrdering2 ()
+ throws Exception
+ {
+ // C,B,A
+ List<Resource> resources = new ArrayList<Resource>();
+
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new AbsoluteOrdering();
+ ((AbsoluteOrdering)metaData._ordering).add("C");
+ ((AbsoluteOrdering)metaData._ordering).add("B");
+ ((AbsoluteOrdering)metaData._ordering).add("A");
+
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1,f1);
+
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2,f2);
+
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3,f3);
+
+ TestResource jar4 = new TestResource("D");
+ resources.add(jar4);
+ TestResource r4 = new TestResource("D/web-fragment.xml");
+ FragmentDescriptor f4 = new FragmentDescriptor(r4, metaData);
+ f4._name="D";
+ metaData._webFragmentNameMap.put(f4._name, f4);
+ metaData._webFragmentResourceMap.put(jar4,f4);
+
+ TestResource jar5 = new TestResource("E");
+ resources.add(jar5);
+ TestResource r5 = new TestResource("E/web-fragment.xml");
+ FragmentDescriptor f5 = new FragmentDescriptor(r5, metaData);
+ f5._name="E";
+ metaData._webFragmentNameMap.put(f5._name, f5);
+ metaData._webFragmentResourceMap.put(jar5,f5);
+
+ TestResource jar6 = new TestResource("plain");
+ resources.add(jar6);
+ TestResource r6 = new TestResource("plain/web-fragment.xml");
+ FragmentDescriptor f6 = new FragmentDescriptor(r6, metaData);
+ f6._name=FragmentDescriptor.NAMELESS+"1";
+ metaData._webFragmentNameMap.put(f6._name, f6);
+ metaData._webFragmentResourceMap.put(jar6,f6);
+
+ List<Resource> list = metaData._ordering.order(resources);
+ String[] outcomes = {"CBA"};
+ String result = "";
+ for (Resource r:list)
+ result += ((TestResource)r)._name;
+
+
+ if (!checkResult(result, outcomes))
+ fail("No outcome matched "+result);
+ }
+
+ public void testAbsoluteOrdering3 ()
+ throws Exception
+ {
+ //empty <absolute-ordering>
+
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new AbsoluteOrdering();
+ List<Resource> resources = new ArrayList<Resource>();
+
+ resources.add(new TestResource("A"));
+ resources.add(new TestResource("B"));
+
+ List<Resource> list = metaData._ordering.order(resources);
+ assertTrue(list.isEmpty());
+ }
+
+
+ public void testRelativeOrderingWithPlainJars ()
+ throws Exception
+ {
+ //B,A,C other jars with no fragments
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new RelativeOrdering();
+
+ //A: after others, before C
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1, f1);
+ //((RelativeOrdering)metaData._ordering).addAfterOthers(f1);
+ f1._otherType = FragmentDescriptor.OtherType.After;
+ f1._befores.add("C");
+
+ //B: before others, before C
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2,f2);
+ //((RelativeOrdering)metaData._ordering).addBeforeOthers(f2);
+ f2._otherType = FragmentDescriptor.OtherType.Before;
+ f2._befores.add("C");
+
+ //C: after A
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3,f3);
+ //((RelativeOrdering)metaData._ordering).addNoOthers(f3);
+ f3._otherType = FragmentDescriptor.OtherType.None;
+ f3._afters.add("A");
+
+ //No fragment jar 1
+ TestResource r4 = new TestResource("plain1");
+ resources.add(r4);
+
+ //No fragment jar 2
+ TestResource r5 = new TestResource("plain2");
+ resources.add(r5);
+
+ //result: BAC
+ String[] outcomes = {"Bplain1plain2AC"};
+
+ List<Resource> orderedList = metaData._ordering.order(resources);
+ String result = "";
+ for (Resource r:orderedList)
+ result+=(((TestResource)r)._name);
+
+ if (!checkResult(result, outcomes))
+ fail ("No outcome matched "+result);
+ }
+
+ public void testAbsoluteOrderingWithPlainJars()
+ throws Exception
+ {
+ //
+ // A,B,C,others
+ //
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData(wac);
+ metaData._ordering = metaData.new AbsoluteOrdering();
+ ((AbsoluteOrdering)metaData._ordering).add("A");
+ ((AbsoluteOrdering)metaData._ordering).add("B");
+ ((AbsoluteOrdering)metaData._ordering).add("C");
+ ((AbsoluteOrdering)metaData._ordering).addOthers();
+
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1,f1);
+
+ TestResource jar2 = new TestResource("B");
+ resources.add(jar2);
+ TestResource r2 = new TestResource("B/web-fragment.xml");
+ FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
+ f2._name="B";
+ metaData._webFragmentNameMap.put(f2._name, f2);
+ metaData._webFragmentResourceMap.put(jar2, f2);
+
+ TestResource jar3 = new TestResource("C");
+ resources.add(jar3);
+ TestResource r3 = new TestResource("C/web-fragment.xml");
+ FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
+ f3._name="C";
+ metaData._webFragmentNameMap.put(f3._name, f3);
+ metaData._webFragmentResourceMap.put(jar3, f3);
+
+ TestResource jar4 = new TestResource("D");
+ resources.add(jar4);
+ TestResource r4 = new TestResource("D/web-fragment.xml");
+ FragmentDescriptor f4 = new FragmentDescriptor((Resource)null, metaData);
+ f4._name="D";
+ metaData._webFragmentNameMap.put(f4._name, f4);
+ metaData._webFragmentResourceMap.put(jar4, f4);
+
+ TestResource jar5 = new TestResource("E");
+ resources.add(jar5);
+ TestResource r5 = new TestResource("E/web-fragment.xml");
+ FragmentDescriptor f5 = new FragmentDescriptor((Resource)null, metaData);
+ f5._name="E";
+ metaData._webFragmentNameMap.put(f5._name, f5);
+ metaData._webFragmentResourceMap.put(jar5, f5);
+
+ TestResource jar6 = new TestResource("plain");
+ resources.add(jar6);
+ TestResource r6 = new TestResource("plain/web-fragment.xml");
+ FragmentDescriptor f6 = new FragmentDescriptor((Resource)null, metaData);
+ f6._name=FragmentDescriptor.NAMELESS+"1";
+ metaData._webFragmentNameMap.put(f6._name, f6);
+ metaData._webFragmentResourceMap.put(jar6, f6);
+
+ //plain jar
+ TestResource r7 = new TestResource("plain1");
+ resources.add(r7);
+
+ TestResource r8 = new TestResource("plain2");
+ resources.add(r8);
+
+ List<Resource> list = metaData._ordering.order(resources);
+
+ String[] outcomes = {"ABCDEplainplain1plain2"};
+ String result = "";
+ for (Resource r:list)
+ result += ((TestResource)r)._name;
+
+ if (!checkResult(result, outcomes))
+ fail("No outcome matched "+result);
+ }
+
+
+
+ public boolean checkResult (String result, String[] outcomes)
+ {
+ boolean matched = false;
+ for (String s:outcomes)
+ {
+ if (s.equals(result))
+ matched = true;
+ }
+ return matched;
+ }
+}

Back to the top