work in progress to Configurations as ServiceLoader

This commit is contained in:
Greg Wilkins 2015-12-04 08:52:37 +11:00
parent 6e11f22de4
commit 9e82fa0a22
26 changed files with 405 additions and 441 deletions

View File

@ -47,7 +47,7 @@ import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.Configurations;
/**
* Starts the Jetty Distribution's demo-base directory using entirely
@ -176,7 +176,7 @@ public class LikeJettyXml
server.addBean(deployer);
// === setup jetty plus ==
Configuration.ClassList.setServerDefault(server).addIfAbsent("org.eclipse.jetty.plus.webapp.EnvConfiguration","org.eclipse.jetty.plus.webapp.PlusConfiguration");
Configurations.setServerDefault(server).add("org.eclipse.jetty.plus.webapp.EnvConfiguration","org.eclipse.jetty.plus.webapp.PlusConfiguration");
// === jetty-stats.xml ===
StatisticsHandler stats = new StatisticsHandler();

View File

@ -101,7 +101,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
super(new String[]{WebXmlConfiguration.class.getName(),MetaInfConfiguration.class.getName(),FragmentConfiguration.class.getName(),PlusConfiguration.class.getName()},
new String[]{JettyWebXmlConfiguration.class.getName()},
new String[]{"org.eclipse.jetty.util.annotation."},
new String[]{"-org.eclipse.jetty.util.annotation."});
new String[]{"-org.eclipse.jetty.util.annotation.","org.objectweb.asm."});
}
/**

View File

@ -0,0 +1 @@
org.eclipse.jetty.annotations.AnnotationConfiguration

View File

@ -29,6 +29,7 @@ import java.util.regex.Pattern;
import org.apache.tools.ant.AntClassLoader;
import org.eclipse.jetty.util.PatternMatcher;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
@ -38,9 +39,9 @@ public class AntWebInfConfiguration extends WebInfConfiguration
{
@Override
public String getName()
public Class<? extends Configuration> replaces()
{
return WebInfConfiguration.class.getName();
return WebInfConfiguration.class;
}

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.Configuration;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
@ -50,9 +51,9 @@ public class AntWebXmlConfiguration extends WebXmlConfiguration
}
@Override
public String getName()
public Class<? extends Configuration> replaces()
{
return WebXmlConfiguration.class.getName();
return WebXmlConfiguration.class;
}
public void setClassPathFiles(List classPathFiles)

View File

@ -0,0 +1,3 @@
org.eclipse.jetty.ant.AntWebInfConfiguration
org.eclipse.jetty.ant.AntWebXmlConfiguration
org.eclipse.jetty.ant.types.FileMatchingConfiguration

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
@ -52,9 +53,9 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
protected List<Resource> _unpackedOverlayResources;
@Override
public String getName()
public Class<? extends Configuration> replaces()
{
return WebInfConfiguration.class.getName();
return WebInfConfiguration.class;
}
/**

View File

@ -0,0 +1,2 @@
org.eclipse.jetty.maven.plugin.MavenQuickStartConfiguration
org.eclipse.jetty.maven.plugin.MavenWebInfConfiguration

View File

@ -40,7 +40,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.Configurations;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.osgi.framework.Bundle;
@ -583,15 +583,15 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
if (_configurationClasses != null)
return _configurationClasses;
Configuration.ClassList defaults = Configuration.ClassList.serverDefault(_serverWrapper.getServer());
Configurations defaults = Configurations.serverDefault(_serverWrapper.getServer());
//add before JettyWebXmlConfiguration
if (annotationsAvailable())
defaults.addIfAbsent(AnnotationConfiguration.class.getName());
defaults.add(AnnotationConfiguration.class.getName());
//add in EnvConfiguration and PlusConfiguration just after FragmentConfiguration
if (jndiAvailable())
defaults.addIfAbsent(
defaults.add(
EnvConfiguration.class.getName(),
PlusConfiguration.class.getName());
String[] asArray = new String[defaults.size()];

View File

@ -37,6 +37,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.osgi.framework.Bundle;
@ -66,9 +67,9 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
public static final String FRAGMENT_AND_REQUIRED_RESOURCES = "org.eclipse.jetty.osgi.fragmentAndRequiredResources";
@Override
public String getName()
public Class<? extends Configuration> replaces()
{
return WebInfConfiguration.class.getName();
return WebInfConfiguration.class;
}
/* ------------------------------------------------------------ */

View File

@ -0,0 +1,2 @@
org.eclipse.jetty.osgi.annotations.AnnotationConfiguration
org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration

View File

@ -0,0 +1,2 @@
org.eclipse.jetty.plus.webapp.PlusConfiguration
org.eclipse.jetty.plus.webapp.EnvConfiguration

View File

@ -24,6 +24,7 @@ import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.StandardDescriptorProcessor;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
@ -40,9 +41,9 @@ public class QuickStartConfiguration extends WebInfConfiguration
private static final Logger LOG = Log.getLogger(QuickStartConfiguration.class);
@Override
public String getName()
public Class<? extends Configuration> replaces()
{
return WebInfConfiguration.class.getName();
return WebInfConfiguration.class;
}
/**

View File

@ -0,0 +1 @@
org.eclipse.jetty.quickstart.QuickStartConfiguration

View File

@ -51,13 +51,6 @@ public class AbstractConfiguration implements Configuration
_server=Collections.unmodifiableList(serverClasses==null?Collections.emptyList():Arrays.asList(serverClasses));
}
@Override
public String getName()
{
return this.getClass().getName();
}
@Override
public List<String> getAfterThis()
{

View File

@ -19,13 +19,9 @@
package org.eclipse.jetty.webapp;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.jetty.util.StringUtil;
import java.util.stream.Collectors;
/* ------------------------------------------------------------ */
/**
@ -45,14 +41,14 @@ import org.eclipse.jetty.util.StringUtil;
* in this string should be separated by ':' (semicolon) or ',' (comma).
*/
public class ClasspathPattern extends AbstractList<String>
public class ClasspathPattern
{
private static class Entry
{
public final String _pattern;
public final String _name;
public final boolean _inclusive;
public final boolean _package;
final String _pattern;
final String _name;
final boolean _inclusive;
final boolean _package;
Entry(String pattern)
{
@ -62,6 +58,11 @@ public class ClasspathPattern extends AbstractList<String>
_name = _inclusive ? pattern : pattern.substring(1).trim();
}
boolean isInclusive()
{
return _inclusive;
}
@Override
public String toString()
{
@ -77,9 +78,9 @@ public class ClasspathPattern extends AbstractList<String>
}
/* ------------------------------------------------------------ */
public ClasspathPattern(String[] patterns)
public ClasspathPattern(String... patterns)
{
setAll(patterns);
add(patterns);
}
/* ------------------------------------------------------------ */
@ -89,41 +90,21 @@ public class ClasspathPattern extends AbstractList<String>
}
/* ------------------------------------------------------------ */
@Override
public String get(int index)
public void add(String... patterns)
{
return _entries.get(index)._pattern;
for (String p :patterns)
{
if (_entries.stream().anyMatch(e->{return p.equals(e.toString());}))
continue;
Entry e = new Entry(p);
if (e.isInclusive())
_entries.add(e);
else
_entries.add(0,e);
}
}
/* ------------------------------------------------------------ */
@Override
public String set(int index, String element)
{
Entry e = _entries.set(index,new Entry(element));
return e==null?null:e._pattern;
}
/* ------------------------------------------------------------ */
@Override
public void add(int index, String element)
{
_entries.add(index,new Entry(element));
}
/* ------------------------------------------------------------ */
@Deprecated
public void addPattern(String element)
{
add(element);
}
/* ------------------------------------------------------------ */
@Override
public String remove(int index)
{
Entry e = _entries.remove(index);
return e==null?null:e._pattern;
}
/* ------------------------------------------------------------ */
public boolean remove(String pattern)
@ -139,65 +120,23 @@ public class ClasspathPattern extends AbstractList<String>
return false;
}
/* ------------------------------------------------------------ */
@Override
public int size()
{
return _entries.size();
}
/* ------------------------------------------------------------ */
/**
* Initialize the matcher by parsing each classpath pattern in an array
*
* @param classes array of classpath patterns
* @return array of classpath patterns
*/
private void setAll(String[] classes)
public String[] toArray()
{
_entries.clear();
addAll(classes);
}
/* ------------------------------------------------------------ */
/**
* @param classes array of classpath patterns
*/
private void addAll(String[] classes)
{
if (classes!=null)
addAll(Arrays.asList(classes));
}
/* ------------------------------------------------------------ */
/**
* @param classes array of classpath patterns
*/
public void prepend(String[] classes)
{
if (classes != null)
{
int i=0;
for (String c : classes)
{
add(i,c);
i++;
}
}
}
/* ------------------------------------------------------------ */
public void prependPattern(String pattern)
{
add(0,pattern);
return _entries.stream().map(e->{return e.toString();}).toArray(String[]::new);
}
/* ------------------------------------------------------------ */
/**
* @return array of classpath patterns
*/
public String[] getPatterns()
public List<String> getPatterns()
{
return toArray(new String[_entries.size()]);
return _entries.stream().map(e->{return e.toString();}).collect(Collectors.toList());
}
/* ------------------------------------------------------------ */
@ -247,42 +186,4 @@ public class ClasspathPattern extends AbstractList<String>
return false;
}
public void addAfter(String afterPattern,String... patterns)
{
if (patterns!=null && afterPattern!=null)
{
ListIterator<String> iter = listIterator();
while (iter.hasNext())
{
String cc=iter.next();
if (afterPattern.equals(cc))
{
for (int i=0;i<patterns.length;i++)
iter.add(patterns[i]);
return;
}
}
}
throw new IllegalArgumentException("after '"+afterPattern+"' not found in "+this);
}
public void addBefore(String beforePattern,String... patterns)
{
if (patterns!=null && beforePattern!=null)
{
ListIterator<String> iter = listIterator();
while (iter.hasNext())
{
String cc=iter.next();
if (beforePattern.equals(cc))
{
iter.previous();
for (int i=0;i<patterns.length;i++)
iter.add(patterns[i]);
return;
}
}
}
throw new IllegalArgumentException("before '"+beforePattern+"' not found in "+this);
}
}

View File

@ -18,17 +18,10 @@
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;
@ -42,10 +35,10 @@ 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)
/** Get a class that this class replaces/extends
* @return The class this Configuration replaces/extends or null if it replaces no other configuration
*/
public default String getName() { return this.getClass().getName(); }
public default Class<? extends Configuration> replaces() { return null; }
/* ------------------------------------------------------------------------------- */
/** Get known Configuration Dependencies.
@ -75,6 +68,11 @@ public interface Configuration
*/
public default List<String> getServerClasses() { return Collections.emptyList(); }
/**
* @return true if the Configuration should be enabled by default by being on server classpath
*/
public default boolean isEnabledByDefault() { return false; }
/* ------------------------------------------------------------------------------- */
/** Set up for configuration.
* <p>
@ -133,133 +131,25 @@ public interface Configuration
*/
public void cloneConfigure (WebAppContext template, WebAppContext context) throws Exception;
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
* either be a ClassList instance or an String[] of class names); or a new instance
* with default configuration classes.</p>
* <p>This method also adds the obtained ClassList instance as a dependent bean
* on the server and clears the attribute</p>
* @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.
/**
* @deprecated Use {@link Configurations}
*/
public static ClassList setServerDefault(Server server) throws ClassNotFoundException, InstantiationException, IllegalAccessException
public class ClassList extends Configurations
{
ClassList cl=server.getBean(ClassList.class);
if (cl!=null)
return cl;
cl=serverDefault(server);
server.addBean(cl);
server.setAttribute(Configuration.ATTR,null);
return cl;
}
/* ------------------------------------------------------------ */
/** Get/Create the server default Configuration ClassList.
* <p>Get the class list from: a Server bean; or the attribute (which can
* either be a ClassList instance or an String[] of class names); or a new instance
* with default configuration classes.
* @param server The server the default is for
* @return A copy of the server default ClassList instance of the configuration classes for this server. Changes to the returned list will not change the server default.
*/
public static ClassList serverDefault(Server server)
{
ClassList cl=null;
if (server!=null)
{
cl= server.getBean(ClassList.class);
if (cl!=null)
return new ClassList(cl);
Object attr = server.getAttribute(Configuration.ATTR);
if (attr instanceof ClassList)
return new ClassList((ClassList)attr);
if (attr instanceof String[])
return new ClassList((String[])attr);
}
return new ClassList();
}
public ClassList()
{
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)
{
for (String c:classes)
_instances.add(newConfiguration(c));
}
public ClassList(List<String> 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);
}
}
@Deprecated
public void addAfter(@Name("afterClass") String afterClass,@Name("configClass")String... configClass)
{
if (configClass!=null && afterClass!=null)
{
ListIterator<Configuration> iter = _instances.listIterator();
ListIterator<String> iter = _configurations.listIterator();
while (iter.hasNext())
{
Configuration c=iter.next();
if (afterClass.equals(c.getClass().getName()) || afterClass.equals(c.getName()))
Configuration c=getConfiguration(iter.next());
if (afterClass.equals(c.getClass().getName()) || afterClass.equals(c.replaces().getName()))
{
for (String cc: configClass)
iter.add(newConfiguration(cc));
iter.add(cc);
return;
}
}
@ -267,19 +157,21 @@ public interface Configuration
throw new IllegalArgumentException("afterClass '"+afterClass+"' not found in "+this);
}
@Deprecated
public void addBefore(@Name("beforeClass") String beforeClass,@Name("configClass")String... configClass)
{
if (configClass!=null && beforeClass!=null)
{
ListIterator<Configuration> iter = _instances.listIterator();
ListIterator<String> iter = _configurations.listIterator();
while (iter.hasNext())
{
Configuration c=iter.next();
if (beforeClass.equals(c.getClass().getName()) || beforeClass.equals(c.getName()))
Configuration c=getConfiguration(iter.next());
if (beforeClass.equals(c.getClass().getName()) || beforeClass.equals(c.replaces().getName()))
{
iter.previous();
for (String cc: configClass)
iter.add(newConfiguration(cc));
iter.add(cc);
return;
}
}
@ -287,26 +179,5 @@ public interface Configuration
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

@ -0,0 +1,217 @@
//
// ========================================================================
// Copyright (c) 1995-2015 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.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.ServiceLoader;
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;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class Configurations
{
private static final Logger LOG = Log.getLogger(Configurations.class);
private static final Map<String,Configuration> __known = new HashMap<>();
static
{
ServiceLoader<Configuration> configs = ServiceLoader.load(Configuration.class);
for (Configuration configuration : configs)
__known.put(configuration.getClass().getName(),configuration);
}
public static Collection<Configuration> getKnown()
{
return Collections.unmodifiableCollection(__known.values());
}
protected List<String> _configurations = new ArrayList<>();
/* ------------------------------------------------------------ */
/** Get/Set/Create the server default Configuration ClassList.
* <p>Get the class list from: a Server bean; or the attribute (which can
* either be a ClassList instance or an String[] of class names); or a new instance
* with default configuration classes.</p>
* <p>This method also adds the obtained ClassList instance as a dependent bean
* on the server and clears the attribute</p>
* @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 Configurations setServerDefault(Server server) throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
Configurations cl=server.getBean(Configurations.class);
if (cl!=null)
return cl;
cl=serverDefault(server);
server.addBean(cl);
server.setAttribute(Configuration.ATTR,null);
return cl;
}
/* ------------------------------------------------------------ */
/** Get/Create the server default Configuration ClassList.
* <p>Get the class list from: a Server bean; or the attribute (which can
* either be a ClassList instance or an String[] of class names); or a new instance
* with default configuration classes.
* @param server The server the default is for
* @return A copy of the server default ClassList instance of the configuration classes for this server. Changes to the returned list will not change the server default.
*/
public static Configurations serverDefault(Server server)
{
Configurations cl=null;
if (server!=null)
{
cl= server.getBean(Configurations.class);
if (cl!=null)
return new Configurations(cl);
Object attr = server.getAttribute(Configuration.ATTR);
if (attr instanceof Configurations)
return new Configurations((Configurations)attr);
if (attr instanceof String[])
return new Configurations((String[])attr);
}
return new Configurations();
}
public Configurations()
{
this(WebAppContext.DEFAULT_CONFIGURATION_CLASSES);
}
protected static Configuration getConfiguration(String classname)
{
Configuration configuration = __known.get(classname);
if (configuration==null)
{
try
{
@SuppressWarnings("unchecked")
Class<Configuration> clazz = Loader.loadClass(classname);
configuration = clazz.newInstance();
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e)
{
throw new RuntimeException(e);
}
LOG.info("Unknown configuration {}",classname);
__known.put(configuration.getClass().getName(),configuration);
}
return configuration;
}
public Configurations(String... classes)
{
add(classes);
}
public Configurations(List<String> classes)
{
add(classes.toArray(new String[classes.size()]));
}
public Configurations(Configurations classlist)
{
_configurations.addAll(classlist._configurations);
}
public void add(@Name("configClass")String... configClass)
{
loop: for (String c : configClass)
{
Configuration configuration = getConfiguration(c);
// Do we need to replace any existing configuration?
Class<? extends Configuration> replaces = configuration.replaces();
if (replaces!=null)
{
for (ListIterator<String> i=_configurations.listIterator();i.hasNext();)
{
if (i.next().equals(replaces.getName()))
{
i.set(c);
continue loop;
}
}
}
if (!_configurations.contains(c))
_configurations.add(c);
}
}
public int size()
{
return _configurations.size();
}
public String[] toArray(String[] asArray)
{
return _configurations.toArray(new String[_configurations.size()]);
}
public List<Configuration> getConfigurations()
{
// instantiate configurations list
List<Configuration> configurations = _configurations.stream().map(n->{return __known.get(n);}).collect(Collectors.toList());
// Sort the configurations
Map<String,Configuration> map = new HashMap<>();
TopologicalSort<Configuration> sort = new TopologicalSort<>();
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("{} configurations {}",configurations);
return configurations;
}
@Override
public String toString()
{
return getConfigurations().toString();
}
}

View File

@ -37,6 +37,12 @@ public class FragmentConfiguration extends AbstractConfiguration
super(new String[]{MetaInfConfiguration.class.getName()},null);
}
@Override
public boolean isEnabledByDefault()
{
return true;
}
@Override
public void preConfigure(WebAppContext context) throws Exception
{

View File

@ -54,6 +54,11 @@ public class JettyWebXmlConfiguration extends AbstractConfiguration
super(new String[]{WebXmlConfiguration.class.getName(),FragmentConfiguration.class.getName(),MetaInfConfiguration.class.getName()},null);
}
@Override
public boolean isEnabledByDefault()
{
return true;
}
/**
* Configure

View File

@ -76,6 +76,14 @@ public class MetaInfConfiguration extends AbstractConfiguration
super(new String[]{WebXmlConfiguration.class.getName()},null);
}
/* ------------------------------------------------------------------------------- */
@Override
public boolean isEnabledByDefault()
{
return true;
}
/* ------------------------------------------------------------------------------- */
@Override
public void preConfigure(final WebAppContext context) throws Exception
{

View File

@ -33,6 +33,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import javax.servlet.ServletContext;
@ -99,16 +100,12 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
/*
* 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",
} ;
Configurations.getKnown().stream()
.filter(c->{return c.isEnabledByDefault();})
.map(c->{return c.getClass().getName();})
.toArray(String[]::new);
// System classes are classes that cannot be replaced by
// the web application, and they are *always* loaded via
@ -121,6 +118,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
"javax.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2)
"org.xml.", // needed by javax.xml
"org.w3c.", // needed by javax.xml
"org.eclipse.jetty.jmx.", // webapp cannot change jmx classes
"org.eclipse.jetty.continuation.", // webapp cannot change continuation classes
"org.eclipse.jetty.jaas.", // webapp cannot change jaas classes
@ -152,8 +151,9 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
"-org.eclipse.jetty.apache.", // don't hide jetty apache impls
"-org.eclipse.jetty.util.log.", // don't hide server log
"-org.eclipse.jetty.alpn.", // don't hide ALPN
"org.objectweb.asm.", // hide asm used by jetty
"org.eclipse.jdt.", // hide jdt used by jetty
"org.eclipse.jetty." // hide other jetty classes
} ;
@ -444,62 +444,32 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
*/
public void preConfigure() throws Exception
{
// Setup configurations
loadConfigurations();
// Sort the configurations
Map<String,Configuration> map = new HashMap<>();
TopologicalSort<Configuration> sort = new TopologicalSort<>();
for (Configuration c:_configurations)
{
Configuration duplicate = map.put(c.getName(),c);
if (duplicate!=null)
LOG.warn("Duplicate configuration in {} for {} and {}",this,duplicate,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 default system classes
loadSystemClasses();
// Setup server classes
// Setup default server classes
loadServerClasses();
// Setup Configuration classes
for (Configuration configuration:_configurations)
// Add the known server class inclusions for all configurations
for (Configuration configuration : Configurations.getKnown())
{
configuration.getSystemClasses().forEach(c->
for (String pattern: configuration.getServerClasses())
{
if (c.startsWith("-"))
prependSystemClass(c);
else
addSystemClass(c);
});
configuration.getServerClasses().forEach(c->
{
if (c.startsWith("-"))
prependServerClass(c);
else
addServerClass(c);
});
if (!pattern.startsWith("-"))
addServerClass(pattern);
}
}
// Setup Configuration classes for this webapp!
loadConfigurations();
for (Configuration configuration:_configurations)
{
for (String pattern: configuration.getSystemClasses())
addSystemClass(pattern);
for (String pattern: configuration.getServerClasses())
if (pattern.startsWith("-"))
addServerClass(pattern);
}
// Configure classloader
_ownClassLoader=false;
@ -704,27 +674,22 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
@ManagedAttribute(value="classes and packages hidden by the context classloader", readonly=true)
public String[] getServerClasses()
{
if (_serverClasses == null)
loadServerClasses();
return _serverClasses.getPatterns();
return _serverClasses.toArray();
}
/* ------------------------------------------------------------ */
/** Add to the list of Server classes.
* @param classOrPackage A fully qualified class name (eg com.foo.MyClass)
* or a qualified package name ending with '.' (eg com.foo.). If the class
* or package has '-' it is excluded from the server classes and order is thus
* important when added system class patterns. This argument may also be a comma
* separated list of classOrPackage patterns.
* or package has '-' it is excluded from the server classes. This argument
* may also be a comma separated list of classOrPackage patterns.
* @see #setServerClasses(String[])
* @see <a href="http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html">Jetty Documentation: Classloading</a>
*/
public void addServerClass(String classOrPackage)
{
if (_serverClasses == null)
loadServerClasses();
_serverClasses.add(classOrPackage);
}
@ -732,18 +697,15 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
/** Prepend to the list of Server classes.
* @param classOrPackage A fully qualified class name (eg com.foo.MyClass)
* or a qualified package name ending with '.' (eg com.foo.). If the class
* or package has '-' it is excluded from the server classes and order is thus
* important when added system class patterns. This argument may also be a comma
* or package has '-' it is excluded from the server classes. This argument may also be a comma
* separated list of classOrPackage patterns.
* @deprecated Order is no longer significant so use {@link #addServerClass(String)} instead.
* @see #setServerClasses(String[])
* @see <a href="http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html">Jetty Documentation: Classloading</a>
*/
public void prependServerClass(String classOrPackage)
{
if (_serverClasses == null)
loadServerClasses();
_serverClasses.prependPattern(classOrPackage);
addServerClass(classOrPackage);
}
/* ------------------------------------------------------------ */
@ -754,56 +716,48 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
@ManagedAttribute(value="classes and packages given priority by context classloader", readonly=true)
public String[] getSystemClasses()
{
if (_systemClasses == null)
loadSystemClasses();
return _systemClasses.getPatterns();
return _systemClasses.toArray();
}
/* ------------------------------------------------------------ */
/** Add to the list of System classes.
* @param classOrPackage A fully qualified class name (eg com.foo.MyClass)
* or a qualified package name ending with '.' (eg com.foo.). If the class
* or package has '-' it is excluded from the system classes and order is thus
* important when added system class patterns. This argument may also be a comma
* or package has '-' it is excluded from the system classes.
* This argument may also be a comma
* separated list of classOrPackage patterns.
* @see #setSystemClasses(String[])
* @see <a href="http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html">Jetty Documentation: Classloading</a>
*/
public void addSystemClass(String classOrPackage)
{
if (_systemClasses == null)
loadSystemClasses();
_systemClasses.add(classOrPackage);
}
/* ------------------------------------------------------------ */
/** Prepend to the list of System classes.
* @param classOrPackage A fully qualified class name (eg com.foo.MyClass)
* or a qualified package name ending with '.' (eg com.foo.). If the class
* or package has '-' it is excluded from the system classes and order is thus
* important when added system class patterns.This argument may also be a comma
* or package has '-' it is excluded from the system classes.
* This argument may also be a comma
* separated list of classOrPackage patterns.
* @deprecated Order is no longer significant so use {@link #addSystemClass(String)} instead.
* @see #setSystemClasses(String[])
* @see <a href="http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html">Jetty Documentation: Classloading</a>
*/
public void prependSystemClass(String classOrPackage)
{
if (_systemClasses == null)
loadSystemClasses();
_systemClasses.prependPattern(classOrPackage);
_systemClasses.add(classOrPackage);
}
/* ------------------------------------------------------------ */
@Override
public boolean isServerClass(String name)
{
if (_serverClasses == null)
loadServerClasses();
return _serverClasses.match(name);
}
@ -811,9 +765,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
@Override
public boolean isSystemClass(String name)
{
if (_systemClasses == null)
loadSystemClasses();
return _systemClasses.match(name);
}
@ -971,7 +923,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
if (_configurationClasses.size()==0)
{
_configurations.addAll(Configuration.ClassList.serverDefault(getServer()).getConfigurations());
_configurations.addAll(Configurations.serverDefault(getServer()).getConfigurations());
}
else
{
@ -1007,8 +959,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
dumpBeans(out,indent,
Collections.singletonList(new ClassLoaderDump(getClassLoader())),
Collections.singletonList(new DumpableCollection("Systemclasses "+this,_systemClasses)),
Collections.singletonList(new DumpableCollection("Serverclasses "+this,_serverClasses)),
Collections.singletonList(new DumpableCollection("Systemclasses "+this,_systemClasses.getPatterns())),
Collections.singletonList(new DumpableCollection("Serverclasses "+this,_serverClasses.getPatterns())),
Collections.singletonList(new DumpableCollection("Configurations "+this,_configurations)),
Collections.singletonList(new DumpableCollection("Handler attributes "+this,((AttributesMap)getAttributes()).getAttributeEntrySet())),
Collections.singletonList(new DumpableCollection("Context attributes "+this,((Context)getServletContext()).getAttributeEntrySet())),

View File

@ -65,6 +65,12 @@ public class WebInfConfiguration extends AbstractConfiguration
super();
}
@Override
public boolean isEnabledByDefault()
{
return true;
}
@Override
public void preConfigure(final WebAppContext context) throws Exception
{

View File

@ -42,6 +42,13 @@ public class WebXmlConfiguration extends AbstractConfiguration
super(new String[]{WebInfConfiguration.class.getName()},null);
}
/* ------------------------------------------------------------------------------- */
@Override
public boolean isEnabledByDefault()
{
return true;
}
/* ------------------------------------------------------------------------------- */
/**
*

View File

@ -0,0 +1,6 @@
org.eclipse.jetty.webapp.CloneConfiguration
org.eclipse.jetty.webapp.FragmentConfiguration
org.eclipse.jetty.webapp.JettyWebXmlConfiguration
org.eclipse.jetty.webapp.MetaInfConfiguration
org.eclipse.jetty.webapp.WebInfConfiguration
org.eclipse.jetty.webapp.WebXmlConfiguration

View File

@ -21,24 +21,22 @@ package org.eclipse.jetty.webapp;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
public class ClasspathPatternTest
{
private final ClasspathPattern pattern = new ClasspathPattern();
private ClasspathPattern pattern = new ClasspathPattern();
@Before
public void before()
{
pattern.clear();
pattern = new ClasspathPattern();
pattern.add("org.package.");
pattern.add("-org.excluded.");
pattern.add("org.example.FooBar");
pattern.add("-org.example.Excluded");
pattern.addAll(Arrays.asList(new String[]{"-org.example.Nested$Minus","org.example.Nested","org.example.Nested$Something"}));
pattern.add("-org.example.Nested$Minus","org.example.Nested","org.example.Nested$Something");
}
@Test
@ -77,28 +75,6 @@ public class ClasspathPatternTest
assertTrue(pattern.match("org.example.Nested$Other"));
}
@Test
public void testAddBefore()
{
pattern.addBefore("-org.excluded.","org.excluded.ExceptionOne","org.excluded.ExceptionTwo");
assertTrue(pattern.match("org.excluded.ExceptionOne"));
assertTrue(pattern.match("org.excluded.ExceptionTwo"));
assertFalse(pattern.match("org.example.Unknown"));
}
@Test
public void testAddAfter()
{
pattern.addAfter("org.package.","org.excluded.ExceptionOne","org.excluded.ExceptionTwo");
assertTrue(pattern.match("org.excluded.ExceptionOne"));
assertTrue(pattern.match("org.excluded.ExceptionTwo"));
assertFalse(pattern.match("org.example.Unknown"));
}
@Test
public void testDoubledNested()
{