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

View File

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

View File

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

View File

@ -20,12 +20,14 @@ package org.eclipse.jetty.embedded;
import java.io.File;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.plus.jndi.EnvEntry;
import org.eclipse.jetty.plus.jndi.Resource;
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.server.Server;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
/**
@ -38,18 +40,13 @@ public class ServerWithAnnotations
// Create the server
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
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("/");
File warFile = new File(
"../../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.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.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
/**
@ -36,20 +37,16 @@ public class ServerWithJNDI
// Create the server
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
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
File warFile = new File(
"../../jetty-distribution/target/distribution/demo-base/webapps/test.war");
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
// 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">
<Arg><Ref refid="Server" /></Arg>
<Call name="addBefore">
<Arg name="beforeClass">org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Arg>
<Call name="addIfAbsent">
<Arg>
<Array type="String">
<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.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.MultiException;
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.statistic.CounterStatistic;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.FragmentDescriptor;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
import org.eclipse.jetty.webapp.MetaDataComplete;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebDescriptor;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
/**
* Configuration for Annotations
@ -89,6 +94,14 @@ public class AnnotationConfiguration extends AbstractConfiguration
protected CounterStatistic _webInfClassesStats;
protected Pattern _sciExcludePattern;
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
*

View File

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

View File

@ -400,17 +400,24 @@ public class JettyWebAppContext extends WebAppContext
@Override
protected void loadConfigurations() throws Exception
protected void loadConfigurations()
{
super.loadConfigurations();
//inject configurations with config from maven plugin
for (Configuration c:getConfigurations())
try
{
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());
//inject configurations with config from maven plugin
for (Configuration c:getConfigurations())
{
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;
public void setQuickStartWebXml (Resource r)
{
_quickStartWebXml = r;

View File

@ -50,6 +50,12 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
protected static int COUNTER = 0;
protected Resource _originalResourceBase;
protected List<Resource> _unpackedOverlayResources;
@Override
public String getName()
{
return WebInfConfiguration.class.getName();
}
/**
* @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.HashMap;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppProvider;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader;
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.util.Loader;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
@ -584,14 +587,13 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
//add before JettyWebXmlConfiguration
if (annotationsAvailable())
defaults.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.osgi.annotations.AnnotationConfiguration");
defaults.addIfAbsent(AnnotationConfiguration.class.getName());
//add in EnvConfiguration and PlusConfiguration just after FragmentConfiguration
if (jndiAvailable())
defaults.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.plus.webapp.PlusConfiguration");
defaults.addIfAbsent(
EnvConfiguration.class.getName(),
PlusConfiguration.class.getName());
String[] asArray = new String[defaults.size()];
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_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">
<Arg><Ref refid="Server" /></Arg>
<Call name="addAfter">
<Arg name="afterClass">org.eclipse.jetty.webapp.FragmentConfiguration</Arg>
<Call name="addIfAbsent">
<Arg>
<Array type="String">
<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.webapp.AbstractConfiguration;
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.WebAppContext;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
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 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)
{
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.Logger;
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.WebXmlConfiguration;
/**
@ -44,6 +48,12 @@ public class PlusConfiguration extends AbstractConfiguration
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
public void preConfigure (WebAppContext context)
throws Exception

View File

@ -39,6 +39,12 @@ public class QuickStartConfiguration extends WebInfConfiguration
{
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)
*/

View File

@ -49,12 +49,13 @@ public class TopologicalSort<T>
{
private final Map<T,Set<T>> _dependencies = new HashMap<>();
/**
* Add a dependency to be considered in the sort.
* @param dependent The dependent item will be sorted after all its dependencies
* @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);
if (set==null)
@ -62,7 +63,20 @@ public class TopologicalSort<T>
set=new HashSet<>();
_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

View File

@ -18,8 +18,52 @@
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
{
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
{
}

View File

@ -20,13 +20,18 @@ package org.eclipse.jetty.webapp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Predicate;
import java.util.stream.Collectors;
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;
/* ------------------------------------------------------------------------------- */
/** Base Class for WebApplicationContext 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 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.
@ -94,9 +119,10 @@ public interface Configuration
*/
public void cloneConfigure (WebAppContext template, WebAppContext context) throws Exception;
public class ClassList extends ArrayList<String>
public class ClassList
{
List<Configuration> _instances = new ArrayList<>();
/* ------------------------------------------------------------ */
/** Get/Set/Create the server default Configuration ClassList.
* <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
* @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);
if (cl!=null)
return cl;
cl=serverDefault(server);
server.addBean(cl);
server.setAttribute(ATTR,null);
server.setAttribute(Configuration.ATTR,null);
return cl;
}
@ -134,7 +160,7 @@ public interface Configuration
cl= server.getBean(ClassList.class);
if (cl!=null)
return new ClassList(cl);
Object attr = server.getAttribute(ATTR);
Object attr = server.getAttribute(Configuration.ATTR);
if (attr instanceof ClassList)
return new ClassList((ClassList)attr);
if (attr instanceof String[])
@ -148,28 +174,78 @@ public interface Configuration
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)
{
addAll(Arrays.asList(classes));
for (String c:classes)
_instances.add(newConfiguration(c));
}
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)
{
if (configClass!=null && afterClass!=null)
{
ListIterator<String> iter = listIterator();
ListIterator<Configuration> iter = _instances.listIterator();
while (iter.hasNext())
{
String cc=iter.next();
if (afterClass.equals(cc))
Configuration c=iter.next();
if (afterClass.equals(c.getClass().getName()) || afterClass.equals(c.getName()))
{
for (int i=0;i<configClass.length;i++)
iter.add(configClass[i]);
for (String cc: configClass)
iter.add(newConfiguration(cc));
return;
}
}
@ -181,21 +257,42 @@ public interface Configuration
{
if (configClass!=null && beforeClass!=null)
{
ListIterator<String> iter = listIterator();
ListIterator<Configuration> iter = _instances.listIterator();
while (iter.hasNext())
{
String cc=iter.next();
if (beforeClass.equals(cc))
Configuration c=iter.next();
if (beforeClass.equals(c.getClass().getName()) || beforeClass.equals(c.getName()))
{
iter.previous();
for (int i=0;i<configClass.length;i++)
iter.add(configClass[i]);
for (String cc: configClass)
iter.add(newConfiguration(cc));
return;
}
}
}
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 final static String FRAGMENT_RESOURCES="org.eclipse.jetty.webFragments";
public FragmentConfiguration()
{
super(new String[]{MetaInfConfiguration.class.getName()},null);
}
@Override
public void preConfigure(WebAppContext context) throws Exception
@ -40,7 +45,6 @@ public class FragmentConfiguration extends AbstractConfiguration
//find all web-fragment.xmls
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 JETTY_WEB_XML = "jetty-web.xml";
public JettyWebXmlConfiguration()
{
super(new String[]{WebXmlConfiguration.class.getName(),FragmentConfiguration.class.getName(),MetaInfConfiguration.class.getName()},null);
}
/**
* Configure
* 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_RESOURCES = WebInfConfiguration.RESOURCE_DIRS;
/* ------------------------------------------------------------------------------- */
public MetaInfConfiguration()
{
super(new String[]{WebXmlConfiguration.class.getName()},null);
}
@Override
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.Set;
import javax.management.RuntimeErrorException;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration.Dynamic;
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.Loader;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.TopologicalSort;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
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"};
/* default configurations.
* Order is determined by Topological sort in preconfigure
*/
public static final String[] DEFAULT_CONFIGURATION_CLASSES =
{
"org.eclipse.jetty.webapp.WebInfConfiguration",
"org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.webapp.MetaInfConfiguration",
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration"
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
} ;
// System classes are classes that cannot be replaced by
@ -289,7 +294,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return _unavailableException;
}
/* ------------------------------------------------------------ */
/**
* Set Resource Alias.
@ -447,6 +451,30 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
// Setup configurations
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
loadSystemClasses();
@ -790,7 +818,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
}
/* ------------------------------------------------------------ */
private void loadServerClasses()
protected void loadServerClasses()
{
if (_serverClasses != null)
{
@ -916,16 +944,27 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
/* ------------------------------------------------------------ */
protected void loadConfigurations()
throws Exception
{
//if the configuration instances have been set explicitly, use them
if (_configurations.size()>0)
return;
if (_configurationClasses.size()==0)
_configurationClasses.addAll(Configuration.ClassList.serverDefault(getServer()));
for (String configClass : _configurationClasses)
_configurations.add((Configuration)Loader.loadClass(configClass).newInstance());
{
_configurations.addAll(Configuration.ClassList.serverDefault(getServer()).getConfigurations());
}
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));
}
/* ------------------------------------------------------------ */
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
@ -1541,4 +1592,5 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
return _metadata;
}
}

View File

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

View File

@ -35,7 +35,13 @@ public class WebXmlConfiguration extends AbstractConfiguration
{
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()));
}
@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
public void testConfigurationInstances ()

View File

@ -12,28 +12,6 @@
</Arg>
</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="war"><Property name="jetty.webapps" default="."/>/test-jndi.war</Set>
<Set name="extractWAR">true</Set>

View File

@ -14,30 +14,6 @@
</Arg>
</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="war"><Property name="jetty.webapps"/>/test-spec.war</Set>
<Set name="configurationDiscovered">true</Set>