Self ordering WebApp Configurations

This commit is contained in:
Greg Wilkins 2015-11-27 11:47:03 +11:00
parent cea05f17d9
commit 2972354db7
30 changed files with 379 additions and 163 deletions

View File

@ -27,6 +27,7 @@ import java.net.URI;
import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspException;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.FS; import org.eclipse.jetty.toolchain.test.FS;
@ -63,15 +64,7 @@ public class JstlTest
File testTagLibDir = MavenTestingUtils.getProjectDir("src/test/taglibjar"); File testTagLibDir = MavenTestingUtils.getProjectDir("src/test/taglibjar");
JAR.create(testTagLibDir,new File(libDir, "testtaglib.jar")); JAR.create(testTagLibDir,new File(libDir, "testtaglib.jar"));
// Configure WebAppContext // Configure WebAppCont
Configuration.ClassList classlist = Configuration.ClassList
.setServerDefault(server);
classlist.addBefore(
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration");
WebAppContext context = new WebAppContext(); WebAppContext context = new WebAppContext();
context.setContextPath("/"); context.setContextPath("/");
@ -79,6 +72,9 @@ public class JstlTest
FS.ensureEmpty(scratchDir); FS.ensureEmpty(scratchDir);
JspConfig.init(context,testWebAppDir.toURI(),scratchDir); JspConfig.init(context,testWebAppDir.toURI(),scratchDir);
context.addConfiguration(new AnnotationConfiguration());
server.setHandler(context); server.setHandler(context);
// Start Server // Start Server

View File

@ -176,10 +176,7 @@ public class LikeJettyXml
server.addBean(deployer); server.addBean(deployer);
// === setup jetty plus == // === setup jetty plus ==
Configuration.ClassList.setServerDefault(server).addAfter( Configuration.ClassList.setServerDefault(server).addIfAbsent("org.eclipse.jetty.plus.webapp.EnvConfiguration","org.eclipse.jetty.plus.webapp.PlusConfiguration");
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.plus.webapp.PlusConfiguration");
// === jetty-stats.xml === // === jetty-stats.xml ===
StatisticsHandler stats = new StatisticsHandler(); StatisticsHandler stats = new StatisticsHandler();

View File

@ -21,10 +21,10 @@ package org.eclipse.jetty.embedded;
import java.io.File; import java.io.File;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
public class OneWebAppWithJsp public class OneWebAppWithJsp
@ -64,14 +64,11 @@ public class OneWebAppWithJsp
webapp.setWar( warFile.getAbsolutePath() ); webapp.setWar( warFile.getAbsolutePath() );
webapp.setExtractWAR(true); webapp.setExtractWAR(true);
// This webapp will use jsps and jstl. We need to enable the // This webapp will use jsps and jstl. We need to enable the
// AnnotationConfiguration in order to correctly // AnnotationConfiguration in order to correctly
// set up the jsp container // set up the jsp container
Configuration.ClassList classlist = Configuration.ClassList webapp.addConfiguration(new AnnotationConfiguration());
.setServerDefault( server );
classlist.addBefore(
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration" );
// Set the ContainerIncludeJarPattern so that jetty examines these // Set the ContainerIncludeJarPattern so that jetty examines these
// container-path jars for tlds, web-fragments etc. // container-path jars for tlds, web-fragments etc.

View File

@ -20,12 +20,14 @@ package org.eclipse.jetty.embedded;
import java.io.File; import java.io.File;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.plus.jndi.EnvEntry; import org.eclipse.jetty.plus.jndi.EnvEntry;
import org.eclipse.jetty.plus.jndi.Resource; import org.eclipse.jetty.plus.jndi.Resource;
import org.eclipse.jetty.plus.jndi.Transaction; import org.eclipse.jetty.plus.jndi.Transaction;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
/** /**
@ -38,18 +40,13 @@ public class ServerWithAnnotations
// Create the server // Create the server
Server server = new Server(8080); Server server = new Server(8080);
// Enable parsing of jndi-related parts of web.xml and jetty-env.xml
Configuration.ClassList classlist = Configuration.ClassList
.setServerDefault(server);
classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.plus.webapp.PlusConfiguration");
classlist.addBefore(
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration");
// Create a WebApp // Create a WebApp
WebAppContext webapp = new WebAppContext(); WebAppContext webapp = new WebAppContext();
// Enable parsing of jndi-related parts of web.xml and jetty-env.xml
webapp.addConfiguration(new EnvConfiguration(),new PlusConfiguration(),new AnnotationConfiguration());
webapp.setContextPath("/"); webapp.setContextPath("/");
File warFile = new File( File warFile = new File(
"../../jetty-distribution/target/distribution/demo-base/webapps/test.war"); "../../jetty-distribution/target/distribution/demo-base/webapps/test.war");

View File

@ -21,8 +21,9 @@ package org.eclipse.jetty.embedded;
import java.io.File; import java.io.File;
import java.util.Properties; import java.util.Properties;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
/** /**
@ -36,20 +37,16 @@ public class ServerWithJNDI
// Create the server // Create the server
Server server = new Server(8080); Server server = new Server(8080);
// Enable parsing of jndi-related parts of web.xml and jetty-env.xml
Configuration.ClassList classlist = Configuration.ClassList
.setServerDefault(server);
classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.plus.webapp.PlusConfiguration");
// Create a WebApp // Create a WebApp
WebAppContext webapp = new WebAppContext(); WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/"); webapp.setContextPath("/");
File warFile = new File( File warFile = new File(
"../../jetty-distribution/target/distribution/demo-base/webapps/test.war"); "../../jetty-distribution/target/distribution/demo-base/webapps/test.war");
webapp.setWar(warFile.getAbsolutePath()); webapp.setWar(warFile.getAbsolutePath());
server.setHandler(webapp); server.setHandler(webapp);
// Enable parsing of jndi-related parts of web.xml and jetty-env.xml
webapp.addConfiguration(new EnvConfiguration(),new PlusConfiguration());
// Register new transaction manager in JNDI // Register new transaction manager in JNDI
// At runtime, the webapp accesses this as java:comp/UserTransaction // At runtime, the webapp accesses this as java:comp/UserTransaction

View File

@ -7,8 +7,7 @@
<!-- =========================================================== --> <!-- =========================================================== -->
<Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="setServerDefault"> <Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="setServerDefault">
<Arg><Ref refid="Server" /></Arg> <Arg><Ref refid="Server" /></Arg>
<Call name="addBefore"> <Call name="addIfAbsent">
<Arg name="beforeClass">org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Arg>
<Arg> <Arg>
<Array type="String"> <Array type="String">
<Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item> <Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>

View File

@ -45,6 +45,7 @@ import javax.servlet.annotation.HandlesTypes;
import org.eclipse.jetty.annotations.AnnotationParser.Handler; import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.plus.annotation.ContainerInitializer; import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.util.ConcurrentHashSet; import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.MultiException; import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
@ -53,10 +54,14 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.statistic.CounterStatistic; import org.eclipse.jetty.util.statistic.CounterStatistic;
import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.FragmentDescriptor; import org.eclipse.jetty.webapp.FragmentDescriptor;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
import org.eclipse.jetty.webapp.MetaDataComplete; import org.eclipse.jetty.webapp.MetaDataComplete;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebDescriptor; import org.eclipse.jetty.webapp.WebDescriptor;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
/** /**
* Configuration for Annotations * Configuration for Annotations
@ -89,6 +94,14 @@ public class AnnotationConfiguration extends AbstractConfiguration
protected CounterStatistic _webInfClassesStats; protected CounterStatistic _webInfClassesStats;
protected Pattern _sciExcludePattern; protected Pattern _sciExcludePattern;
protected ServiceLoader<ServletContainerInitializer> _loadedInitializers = null; protected ServiceLoader<ServletContainerInitializer> _loadedInitializers = null;
public AnnotationConfiguration()
{
super(new String[]{WebXmlConfiguration.class.getName(),MetaInfConfiguration.class.getName(),FragmentConfiguration.class.getName(),PlusConfiguration.class.getName()},
new String[]{JettyWebXmlConfiguration.class.getName()});
}
/** /**
* TimeStatistic * TimeStatistic
* *

View File

@ -37,6 +37,12 @@ import org.eclipse.jetty.webapp.WebXmlConfiguration;
public class AntWebInfConfiguration extends WebInfConfiguration public class AntWebInfConfiguration extends WebInfConfiguration
{ {
@Override
public String getName()
{
return WebInfConfiguration.class.getName();
}
@Override @Override
public void preConfigure(final WebAppContext context) throws Exception public void preConfigure(final WebAppContext context) throws Exception

View File

@ -23,6 +23,7 @@ import java.util.List;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration; import org.eclipse.jetty.webapp.WebXmlConfiguration;
@ -36,8 +37,6 @@ public class AntWebXmlConfiguration extends WebXmlConfiguration
{ {
private static final Logger LOG = Log.getLogger(WebXmlConfiguration.class); private static final Logger LOG = Log.getLogger(WebXmlConfiguration.class);
/** List of classpath files. */ /** List of classpath files. */
private List classPathFiles; private List classPathFiles;
@ -50,6 +49,12 @@ public class AntWebXmlConfiguration extends WebXmlConfiguration
super(); super();
} }
@Override
public String getName()
{
return WebXmlConfiguration.class.getName();
}
public void setClassPathFiles(List classPathFiles) public void setClassPathFiles(List classPathFiles)
{ {
this.classPathFiles = classPathFiles; this.classPathFiles = classPathFiles;

View File

@ -400,17 +400,24 @@ public class JettyWebAppContext extends WebAppContext
@Override @Override
protected void loadConfigurations() throws Exception protected void loadConfigurations()
{ {
super.loadConfigurations(); super.loadConfigurations();
//inject configurations with config from maven plugin try
for (Configuration c:getConfigurations())
{ {
if (c instanceof EnvConfiguration && getJettyEnvXml() != null) //inject configurations with config from maven plugin
((EnvConfiguration)c).setJettyEnvXml(Resource.toURL(new File(getJettyEnvXml()))); for (Configuration c:getConfigurations())
else if (c instanceof MavenQuickStartConfiguration && getQuickStartWebDescriptor() != null) {
((MavenQuickStartConfiguration)c).setQuickStartWebXml(getQuickStartWebDescriptor()); if (c instanceof EnvConfiguration && getJettyEnvXml() != null)
((EnvConfiguration)c).setJettyEnvXml(Resource.toURL(new File(getJettyEnvXml())));
else if (c instanceof MavenQuickStartConfiguration && getQuickStartWebDescriptor() != null)
((MavenQuickStartConfiguration)c).setQuickStartWebXml(getQuickStartWebDescriptor());
}
}
catch(Exception e)
{
throw new RuntimeException(e);
} }
} }

View File

@ -42,7 +42,7 @@ public class MavenQuickStartConfiguration extends QuickStartConfiguration
private Resource _quickStartWebXml; private Resource _quickStartWebXml;
public void setQuickStartWebXml (Resource r) public void setQuickStartWebXml (Resource r)
{ {
_quickStartWebXml = r; _quickStartWebXml = r;

View File

@ -50,6 +50,12 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
protected static int COUNTER = 0; protected static int COUNTER = 0;
protected Resource _originalResourceBase; protected Resource _originalResourceBase;
protected List<Resource> _unpackedOverlayResources; protected List<Resource> _unpackedOverlayResources;
@Override
public String getName()
{
return WebInfConfiguration.class.getName();
}
/** /**
* @see org.eclipse.jetty.webapp.WebInfConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext) * @see org.eclipse.jetty.webapp.WebInfConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)

View File

@ -24,12 +24,15 @@ import java.util.Dictionary;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppProvider; import org.eclipse.jetty.deploy.AppProvider;
import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper; import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader; import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AbstractLifeCycle;
@ -584,14 +587,13 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
//add before JettyWebXmlConfiguration //add before JettyWebXmlConfiguration
if (annotationsAvailable()) if (annotationsAvailable())
defaults.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", defaults.addIfAbsent(AnnotationConfiguration.class.getName());
"org.eclipse.jetty.osgi.annotations.AnnotationConfiguration");
//add in EnvConfiguration and PlusConfiguration just after FragmentConfiguration //add in EnvConfiguration and PlusConfiguration just after FragmentConfiguration
if (jndiAvailable()) if (jndiAvailable())
defaults.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", defaults.addIfAbsent(
"org.eclipse.jetty.plus.webapp.EnvConfiguration", EnvConfiguration.class.getName(),
"org.eclipse.jetty.plus.webapp.PlusConfiguration"); PlusConfiguration.class.getName());
String[] asArray = new String[defaults.size()]; String[] asArray = new String[defaults.size()];
return defaults.toArray(asArray); return defaults.toArray(asArray);
} }

View File

@ -65,6 +65,11 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
public static final String FRAGMENT_AND_REQUIRED_BUNDLES = "org.eclipse.jetty.osgi.fragmentAndRequiredBundles"; public static final String FRAGMENT_AND_REQUIRED_BUNDLES = "org.eclipse.jetty.osgi.fragmentAndRequiredBundles";
public static final String FRAGMENT_AND_REQUIRED_RESOURCES = "org.eclipse.jetty.osgi.fragmentAndRequiredResources"; public static final String FRAGMENT_AND_REQUIRED_RESOURCES = "org.eclipse.jetty.osgi.fragmentAndRequiredResources";
@Override
public String getName()
{
return WebInfConfiguration.class.getName();
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**

View File

@ -11,8 +11,7 @@
<!-- =========================================================== --> <!-- =========================================================== -->
<Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="setServerDefault"> <Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="setServerDefault">
<Arg><Ref refid="Server" /></Arg> <Arg><Ref refid="Server" /></Arg>
<Call name="addAfter"> <Call name="addIfAbsent">
<Arg name="afterClass">org.eclipse.jetty.webapp.FragmentConfiguration</Arg>
<Arg> <Arg>
<Array type="String"> <Array type="String">
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>

View File

@ -41,8 +41,12 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppClassLoader; import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import org.eclipse.jetty.xml.XmlConfiguration; import org.eclipse.jetty.xml.XmlConfiguration;
@ -56,6 +60,12 @@ public class EnvConfiguration extends AbstractConfiguration
private static final String JETTY_ENV_BINDINGS = "org.eclipse.jetty.jndi.EnvConfiguration"; private static final String JETTY_ENV_BINDINGS = "org.eclipse.jetty.jndi.EnvConfiguration";
private URL jettyEnvXmlUrl; private URL jettyEnvXmlUrl;
public EnvConfiguration()
{
super(new String[]{WebXmlConfiguration.class.getName(),MetaInfConfiguration.class.getName(),FragmentConfiguration.class.getName()},
new String[]{PlusConfiguration.class.getName(),JettyWebXmlConfiguration.class.getName()});
}
public void setJettyEnvXml (URL url) public void setJettyEnvXml (URL url)
{ {
this.jettyEnvXmlUrl = url; this.jettyEnvXmlUrl = url;

View File

@ -30,7 +30,11 @@ import org.eclipse.jetty.plus.jndi.Transaction;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
/** /**
@ -44,6 +48,12 @@ public class PlusConfiguration extends AbstractConfiguration
private Integer _key; private Integer _key;
public PlusConfiguration()
{
super(new String[]{EnvConfiguration.class.getName(),WebXmlConfiguration.class.getName(),MetaInfConfiguration.class.getName(),FragmentConfiguration.class.getName()},
new String[]{JettyWebXmlConfiguration.class.getName()});
}
@Override @Override
public void preConfigure (WebAppContext context) public void preConfigure (WebAppContext context)
throws Exception throws Exception

View File

@ -39,6 +39,12 @@ public class QuickStartConfiguration extends WebInfConfiguration
{ {
private static final Logger LOG = Log.getLogger(QuickStartConfiguration.class); private static final Logger LOG = Log.getLogger(QuickStartConfiguration.class);
@Override
public String getName()
{
return WebInfConfiguration.class.getName();
}
/** /**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext) * @see org.eclipse.jetty.webapp.AbstractConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
*/ */

View File

@ -49,12 +49,13 @@ public class TopologicalSort<T>
{ {
private final Map<T,Set<T>> _dependencies = new HashMap<>(); private final Map<T,Set<T>> _dependencies = new HashMap<>();
/** /**
* Add a dependency to be considered in the sort. * Add a dependency to be considered in the sort.
* @param dependent The dependent item will be sorted after all its dependencies * @param dependent The dependent item will be sorted after all its dependencies
* @param dependency The dependency item, will be sorted before its dependent item * @param dependency The dependency item, will be sorted before its dependent item
*/ */
public void addDependency(T dependent, T dependency) public void addDependency(T dependent, T... dependency)
{ {
Set<T> set = _dependencies.get(dependent); Set<T> set = _dependencies.get(dependent);
if (set==null) if (set==null)
@ -62,7 +63,20 @@ public class TopologicalSort<T>
set=new HashSet<>(); set=new HashSet<>();
_dependencies.put(dependent,set); _dependencies.put(dependent,set);
} }
set.add(dependency); for (T d:dependency)
set.add(d);
}
/**
* An alternative to {@link #addDependency(Object, Object)}, which is
* equivalent to addDependency(after,before) as the after item is dependent
* of the before item.
* @param before The item will be sorted before the after
* @param after The item will be sorted after the before
*/
public void addBeforeAfter(T before, T after)
{
addDependency(after,before);
} }
/** Sort the passed array according to dependencies previously set with /** Sort the passed array according to dependencies previously set with

View File

@ -18,8 +18,52 @@
package org.eclipse.jetty.webapp; package org.eclipse.jetty.webapp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class AbstractConfiguration implements Configuration public class AbstractConfiguration implements Configuration
{ {
private final List<String> _after;
private final List<String> _before;
protected AbstractConfiguration()
{
_after=Collections.emptyList();
_before=Collections.emptyList();
}
protected AbstractConfiguration(String[] before,String[] after)
{
_after=Collections.unmodifiableList(after==null?Collections.emptyList():Arrays.asList(after));
_before=Collections.unmodifiableList(before==null?Collections.emptyList():Arrays.asList(before));
}
protected AbstractConfiguration(List<String> after,List<String> before)
{
_after=Collections.unmodifiableList(after==null?Collections.emptyList():new ArrayList<>(after));
_before=Collections.unmodifiableList(before==null?Collections.emptyList():new ArrayList<>(before));
}
@Override
public String getName()
{
return this.getClass().getName();
}
@Override
public List<String> getAfterThis()
{
return _after;
}
@Override
public List<String> getBeforeThis()
{
return _before;
}
public void preConfigure(WebAppContext context) throws Exception public void preConfigure(WebAppContext context) throws Exception
{ {
} }

View File

@ -20,13 +20,18 @@ package org.eclipse.jetty.webapp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.TopologicalSort;
import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.annotation.Name;
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
/** Base Class for WebApplicationContext Configuration. /** Base Class for WebApplicationContext Configuration.
* This class can be extended to customize or extend the configuration * This class can be extended to customize or extend the configuration
@ -35,6 +40,26 @@ import org.eclipse.jetty.util.annotation.Name;
public interface Configuration public interface Configuration
{ {
public final static String ATTR="org.eclipse.jetty.webapp.configuration"; public final static String ATTR="org.eclipse.jetty.webapp.configuration";
/* ------------------------------------------------------------------------------- */
/** Get the name of the configuration used for a {@link TopologicalSort}
* @return The name of the Configuration (defaults to classname)
*/
public default String getName() { return this.getClass().getName(); }
/* ------------------------------------------------------------------------------- */
/** Get known Configuration Dependencies.
* @return The names of Configurations that {@link TopologicalSort} must order
* before this configuration.
*/
public default List<String> getBeforeThis() { return Collections.emptyList(); }
/* ------------------------------------------------------------------------------- */
/** Get known Configuration Dependents.
* @return The names of Configurations that {@link TopologicalSort} must order
* after this configuration.
*/
public default List<String> getAfterThis(){ return Collections.emptyList(); }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
/** Set up for configuration. /** Set up for configuration.
@ -94,9 +119,10 @@ public interface Configuration
*/ */
public void cloneConfigure (WebAppContext template, WebAppContext context) throws Exception; public void cloneConfigure (WebAppContext template, WebAppContext context) throws Exception;
public class ClassList
public class ClassList extends ArrayList<String>
{ {
List<Configuration> _instances = new ArrayList<>();
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Get/Set/Create the server default Configuration ClassList. /** Get/Set/Create the server default Configuration ClassList.
* <p>Get the class list from: a Server bean; or the attribute (which can * <p>Get the class list from: a Server bean; or the attribute (which can
@ -107,14 +133,14 @@ public interface Configuration
* @param server The server the default is for * @param server The server the default is for
* @return the server default ClassList instance of the configuration classes for this server. Changes to this list will change the server default instance. * @return the server default ClassList instance of the configuration classes for this server. Changes to this list will change the server default instance.
*/ */
public static ClassList setServerDefault(Server server) public static ClassList setServerDefault(Server server) throws ClassNotFoundException, InstantiationException, IllegalAccessException
{ {
ClassList cl=server.getBean(ClassList.class); ClassList cl=server.getBean(ClassList.class);
if (cl!=null) if (cl!=null)
return cl; return cl;
cl=serverDefault(server); cl=serverDefault(server);
server.addBean(cl); server.addBean(cl);
server.setAttribute(ATTR,null); server.setAttribute(Configuration.ATTR,null);
return cl; return cl;
} }
@ -134,7 +160,7 @@ public interface Configuration
cl= server.getBean(ClassList.class); cl= server.getBean(ClassList.class);
if (cl!=null) if (cl!=null)
return new ClassList(cl); return new ClassList(cl);
Object attr = server.getAttribute(ATTR); Object attr = server.getAttribute(Configuration.ATTR);
if (attr instanceof ClassList) if (attr instanceof ClassList)
return new ClassList((ClassList)attr); return new ClassList((ClassList)attr);
if (attr instanceof String[]) if (attr instanceof String[])
@ -148,28 +174,78 @@ public interface Configuration
this(WebAppContext.DEFAULT_CONFIGURATION_CLASSES); this(WebAppContext.DEFAULT_CONFIGURATION_CLASSES);
} }
private Configuration newConfiguration(String classname)
{
try
{
Class<Configuration> clazz = Loader.loadClass(classname);
return clazz.newInstance();
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e)
{
throw new RuntimeException(e);
}
}
public ClassList(String[] classes) public ClassList(String[] classes)
{ {
addAll(Arrays.asList(classes)); for (String c:classes)
_instances.add(newConfiguration(c));
} }
public ClassList(List<String> classes) public ClassList(List<String> classes)
{ {
addAll(classes); for (String c:classes)
_instances.add(newConfiguration(c));
}
public ClassList(Configuration.ClassList classlist)
{
_instances.addAll(classlist._instances);
}
public void add(@Name("configClass")String... configClass)
{
loop: for (String c : configClass)
{
Configuration configuration = newConfiguration(c);
ListIterator<Configuration> i = _instances.listIterator();
while(i.hasNext())
{
Configuration next = i.next();
if (next.getName().equals(configuration.getName()))
{
i.set(configuration);
continue loop;
}
}
_instances.add(configuration);
}
}
public void addIfAbsent(@Name("configClass")String... configClass)
{
for (String c : configClass)
{
Configuration configuration = newConfiguration(c);
if (!_instances.stream().map(i->{return i.getName();}).anyMatch(n->{return configuration.getName().equals(n);}))
_instances.add(configuration);
}
} }
public void addAfter(@Name("afterClass") String afterClass,@Name("configClass")String... configClass) public void addAfter(@Name("afterClass") String afterClass,@Name("configClass")String... configClass)
{ {
if (configClass!=null && afterClass!=null) if (configClass!=null && afterClass!=null)
{ {
ListIterator<String> iter = listIterator(); ListIterator<Configuration> iter = _instances.listIterator();
while (iter.hasNext()) while (iter.hasNext())
{ {
String cc=iter.next(); Configuration c=iter.next();
if (afterClass.equals(cc)) if (afterClass.equals(c.getClass().getName()) || afterClass.equals(c.getName()))
{ {
for (int i=0;i<configClass.length;i++) for (String cc: configClass)
iter.add(configClass[i]); iter.add(newConfiguration(cc));
return; return;
} }
} }
@ -181,21 +257,42 @@ public interface Configuration
{ {
if (configClass!=null && beforeClass!=null) if (configClass!=null && beforeClass!=null)
{ {
ListIterator<String> iter = listIterator(); ListIterator<Configuration> iter = _instances.listIterator();
while (iter.hasNext()) while (iter.hasNext())
{ {
String cc=iter.next(); Configuration c=iter.next();
if (beforeClass.equals(cc)) if (beforeClass.equals(c.getClass().getName()) || beforeClass.equals(c.getName()))
{ {
iter.previous(); iter.previous();
for (int i=0;i<configClass.length;i++) for (String cc: configClass)
iter.add(configClass[i]); iter.add(newConfiguration(cc));
return; return;
} }
} }
} }
throw new IllegalArgumentException("beforeClass '"+beforeClass+"' not found in "+this); throw new IllegalArgumentException("beforeClass '"+beforeClass+"' not found in "+this);
} }
public int size()
{
return _instances.size();
}
public String[] toArray(String[] asArray)
{
return _instances.stream().map(i->{return i.getClass().getName();}).toArray(n->{return new String[n];});
}
public List<Configuration> getConfigurations()
{
return _instances.stream().map(i->{return newConfiguration(i.getClass().getName());}).collect(Collectors.toList());
}
@Override
public String toString()
{
return getConfigurations().toString();
}
} }
} }

View File

@ -31,6 +31,11 @@ import org.eclipse.jetty.util.resource.Resource;
public class FragmentConfiguration extends AbstractConfiguration public class FragmentConfiguration extends AbstractConfiguration
{ {
public final static String FRAGMENT_RESOURCES="org.eclipse.jetty.webFragments"; public final static String FRAGMENT_RESOURCES="org.eclipse.jetty.webFragments";
public FragmentConfiguration()
{
super(new String[]{MetaInfConfiguration.class.getName()},null);
}
@Override @Override
public void preConfigure(WebAppContext context) throws Exception public void preConfigure(WebAppContext context) throws Exception
@ -40,7 +45,6 @@ public class FragmentConfiguration extends AbstractConfiguration
//find all web-fragment.xmls //find all web-fragment.xmls
findWebFragments(context, context.getMetaData()); findWebFragments(context, context.getMetaData());
} }

View File

@ -48,6 +48,13 @@ public class JettyWebXmlConfiguration extends AbstractConfiguration
public static final String XML_CONFIGURATION = "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"; public static final String XML_CONFIGURATION = "org.eclipse.jetty.webapp.JettyWebXmlConfiguration";
public static final String JETTY_WEB_XML = "jetty-web.xml"; public static final String JETTY_WEB_XML = "jetty-web.xml";
public JettyWebXmlConfiguration()
{
super(new String[]{WebXmlConfiguration.class.getName(),FragmentConfiguration.class.getName(),MetaInfConfiguration.class.getName()},null);
}
/** /**
* Configure * Configure
* Apply web-jetty.xml configuration * Apply web-jetty.xml configuration

View File

@ -70,6 +70,12 @@ public class MetaInfConfiguration extends AbstractConfiguration
public static final String METAINF_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES; public static final String METAINF_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES;
public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_DIRS; public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_DIRS;
/* ------------------------------------------------------------------------------- */
public MetaInfConfiguration()
{
super(new String[]{WebXmlConfiguration.class.getName()},null);
}
@Override @Override
public void preConfigure(final WebAppContext context) throws Exception public void preConfigure(final WebAppContext context) throws Exception
{ {

View File

@ -35,6 +35,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.management.RuntimeErrorException;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration.Dynamic; import javax.servlet.ServletRegistration.Dynamic;
import javax.servlet.ServletSecurityElement; import javax.servlet.ServletSecurityElement;
@ -61,6 +62,7 @@ import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.AttributesMap; import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.MultiException; import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.TopologicalSort;
import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;
@ -96,13 +98,16 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
private String[] __dftProtectedTargets = {"/web-inf", "/meta-inf"}; private String[] __dftProtectedTargets = {"/web-inf", "/meta-inf"};
/* default configurations.
* Order is determined by Topological sort in preconfigure
*/
public static final String[] DEFAULT_CONFIGURATION_CLASSES = public static final String[] DEFAULT_CONFIGURATION_CLASSES =
{ {
"org.eclipse.jetty.webapp.WebInfConfiguration", "org.eclipse.jetty.webapp.WebInfConfiguration",
"org.eclipse.jetty.webapp.WebXmlConfiguration", "org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.webapp.MetaInfConfiguration", "org.eclipse.jetty.webapp.MetaInfConfiguration",
"org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration" "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
} ; } ;
// System classes are classes that cannot be replaced by // System classes are classes that cannot be replaced by
@ -289,7 +294,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return _unavailableException; return _unavailableException;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* Set Resource Alias. * Set Resource Alias.
@ -447,6 +451,30 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
// Setup configurations // Setup configurations
loadConfigurations(); loadConfigurations();
// Sort the configurations
Map<String,Configuration> map = new HashMap<>();
TopologicalSort<Configuration> sort = new TopologicalSort<>();
for (Configuration c:_configurations)
map.put(c.getName(),c);
for (Configuration c:_configurations)
{
for (String b:c.getBeforeThis())
{
Configuration before=map.get(b);
if (before!=null)
sort.addBeforeAfter(before,c);
}
for (String a:c.getAfterThis())
{
Configuration after=map.get(a);
if (after!=null)
sort.addBeforeAfter(c,after);
}
}
sort.sort(_configurations);
if (LOG.isDebugEnabled())
LOG.debug("sorted {}",_configurations);
// Setup system classes // Setup system classes
loadSystemClasses(); loadSystemClasses();
@ -790,7 +818,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
private void loadServerClasses() protected void loadServerClasses()
{ {
if (_serverClasses != null) if (_serverClasses != null)
{ {
@ -916,16 +944,27 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
protected void loadConfigurations() protected void loadConfigurations()
throws Exception
{ {
//if the configuration instances have been set explicitly, use them //if the configuration instances have been set explicitly, use them
if (_configurations.size()>0) if (_configurations.size()>0)
return; return;
if (_configurationClasses.size()==0) if (_configurationClasses.size()==0)
_configurationClasses.addAll(Configuration.ClassList.serverDefault(getServer())); {
for (String configClass : _configurationClasses) _configurations.addAll(Configuration.ClassList.serverDefault(getServer()).getConfigurations());
_configurations.add((Configuration)Loader.loadClass(configClass).newInstance()); }
else
{
try
{
for (String configClass : _configurationClasses)
_configurations.add((Configuration)Loader.loadClass(configClass).newInstance());
}
catch (InstantiationException | IllegalAccessException | ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -990,6 +1029,18 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
_configurations.addAll(Arrays.asList(configurations)); _configurations.addAll(Arrays.asList(configurations));
} }
/* ------------------------------------------------------------ */
public void addConfiguration(Configuration... configuration)
{
if (isStarted())
throw new IllegalStateException();
loadConfigurations();
for (Configuration c:configuration)
_configurations.add(c);
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* The default descriptor is a web.xml format file that is applied to the context before the standard WEB-INF/web.xml * The default descriptor is a web.xml format file that is applied to the context before the standard WEB-INF/web.xml
@ -1541,4 +1592,5 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{ {
return _metadata; return _metadata;
} }
} }

View File

@ -60,6 +60,16 @@ public class WebInfConfiguration extends AbstractConfiguration
protected Resource _preUnpackBaseResource; protected Resource _preUnpackBaseResource;
public WebInfConfiguration()
{
super();
}
public WebInfConfiguration(List<String> after, List<String> before)
{
super(after,before);
// TODO Auto-generated constructor stub
}
@Override @Override

View File

@ -35,7 +35,13 @@ public class WebXmlConfiguration extends AbstractConfiguration
{ {
private static final Logger LOG = Log.getLogger(WebXmlConfiguration.class); private static final Logger LOG = Log.getLogger(WebXmlConfiguration.class);
/* ------------------------------------------------------------------------------- */
public WebXmlConfiguration()
{
super(new String[]{WebInfConfiguration.class.getName()},null);
}
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
/** /**
* *

View File

@ -60,36 +60,6 @@ public class WebAppContextTest
assertTrue(Arrays.equals(classNames, wac.getConfigurationClasses())); assertTrue(Arrays.equals(classNames, wac.getConfigurationClasses()));
} }
@Test
public void testConfigurationClassesExplicit ()
{
String[] classNames = {"x.y.z"};
Server server = new Server();
server.setAttribute(Configuration.ATTR, classNames);
//test an explicitly set classnames list overrides that from the server
WebAppContext wac = new WebAppContext();
String[] myClassNames = {"a.b.c", "d.e.f"};
wac.setConfigurationClasses(myClassNames);
wac.setServer(server);
String[] names = wac.getConfigurationClasses();
assertTrue(Arrays.equals(myClassNames, names));
//test if no explicit classnames, they come from the server
WebAppContext wac2 = new WebAppContext();
wac2.setServer(server);
try
{
wac2.loadConfigurations();
}
catch(Exception e)
{
Log.getRootLogger().ignore(e);
}
assertTrue(Arrays.equals(classNames, wac2.getConfigurationClasses()));
}
@Test @Test
public void testConfigurationInstances () public void testConfigurationInstances ()

View File

@ -12,28 +12,6 @@
</Arg> </Arg>
</New> </New>
<!-- =============================================================== -->
<!-- Configure the webapp -->
<!-- =============================================================== -->
<!-- Only uncomment if you are not using etc/jetty-plus.xml from start.ini
<Set name="configurationClasses">
<Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="serverDefault">
<Arg><Ref refid="Server" /></Arg>
<Call name="addAfter">
<Arg name="afterClass">org.eclipse.jetty.webapp.FragmentConfiguration</Arg>
<Arg>
<Array type="String">
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
<Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>
</Array>
</Arg>
</Call>
</Call>
</Set>
-->
<Set name="contextPath">/test-jndi</Set> <Set name="contextPath">/test-jndi</Set>
<Set name="war"><Property name="jetty.webapps" default="."/>/test-jndi.war</Set> <Set name="war"><Property name="jetty.webapps" default="."/>/test-jndi.war</Set>
<Set name="extractWAR">true</Set> <Set name="extractWAR">true</Set>

View File

@ -14,30 +14,6 @@
</Arg> </Arg>
</New> </New>
<!-- =============================================================== -->
<!-- Configure the webapp -->
<!-- =============================================================== -->
<!-- Only uncomment this if you are not using the plus and
annotations sections of start.ini
<Set name="configurationClasses">
<Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="serverDefault">
<Arg><Ref refid="Server" /></Arg>
<Call name="addAfter">
<Arg name="afterClass">org.eclipse.jetty.webapp.FragmentConfiguration</Arg>
<Arg>
<Array type="String">
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
<Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>
</Array>
</Arg>
</Call>
</Call>
</Set>
-->
<Set name="contextPath">/test-spec</Set> <Set name="contextPath">/test-spec</Set>
<Set name="war"><Property name="jetty.webapps"/>/test-spec.war</Set> <Set name="war"><Property name="jetty.webapps"/>/test-spec.war</Set>
<Set name="configurationDiscovered">true</Set> <Set name="configurationDiscovered">true</Set>