diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index 7ea0f5aa063..2a564e8e86d 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -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(); diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java index 5f88e895fc5..b98a702258a 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java @@ -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."}); } /** diff --git a/jetty-annotations/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration b/jetty-annotations/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration new file mode 100644 index 00000000000..87590589c0e --- /dev/null +++ b/jetty-annotations/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration @@ -0,0 +1 @@ +org.eclipse.jetty.annotations.AnnotationConfiguration diff --git a/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebInfConfiguration.java b/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebInfConfiguration.java index 3f2960bfabd..e12fe4bf57b 100644 --- a/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebInfConfiguration.java +++ b/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebInfConfiguration.java @@ -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 replaces() { - return WebInfConfiguration.class.getName(); + return WebInfConfiguration.class; } diff --git a/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebXmlConfiguration.java b/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebXmlConfiguration.java index 5b9a09db97e..d553957e64b 100644 --- a/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebXmlConfiguration.java +++ b/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebXmlConfiguration.java @@ -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 replaces() { - return WebXmlConfiguration.class.getName(); + return WebXmlConfiguration.class; } public void setClassPathFiles(List classPathFiles) diff --git a/jetty-ant/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration b/jetty-ant/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration new file mode 100644 index 00000000000..ab9a4416c36 --- /dev/null +++ b/jetty-ant/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration @@ -0,0 +1,3 @@ +org.eclipse.jetty.ant.AntWebInfConfiguration +org.eclipse.jetty.ant.AntWebXmlConfiguration +org.eclipse.jetty.ant.types.FileMatchingConfiguration diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenWebInfConfiguration.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenWebInfConfiguration.java index 99a8f63d12d..b40dfc9aa70 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenWebInfConfiguration.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenWebInfConfiguration.java @@ -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 _unpackedOverlayResources; @Override - public String getName() + public Class replaces() { - return WebInfConfiguration.class.getName(); + return WebInfConfiguration.class; } /** diff --git a/jetty-maven-plugin/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration b/jetty-maven-plugin/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration new file mode 100644 index 00000000000..ce245252006 --- /dev/null +++ b/jetty-maven-plugin/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration @@ -0,0 +1,2 @@ +org.eclipse.jetty.maven.plugin.MavenQuickStartConfiguration +org.eclipse.jetty.maven.plugin.MavenWebInfConfiguration diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java index 45aeec17770..683106de4f9 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java @@ -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()]; diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java index 8f3f751b86a..4f2b9a296a3 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java @@ -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 replaces() { - return WebInfConfiguration.class.getName(); + return WebInfConfiguration.class; } /* ------------------------------------------------------------ */ diff --git a/jetty-osgi/jetty-osgi-boot/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration b/jetty-osgi/jetty-osgi-boot/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration new file mode 100644 index 00000000000..f6709863026 --- /dev/null +++ b/jetty-osgi/jetty-osgi-boot/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration @@ -0,0 +1,2 @@ +org.eclipse.jetty.osgi.annotations.AnnotationConfiguration +org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration diff --git a/jetty-plus/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration b/jetty-plus/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration new file mode 100644 index 00000000000..86f99caa0a0 --- /dev/null +++ b/jetty-plus/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration @@ -0,0 +1,2 @@ +org.eclipse.jetty.plus.webapp.PlusConfiguration +org.eclipse.jetty.plus.webapp.EnvConfiguration diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java index 5482d7b213b..e9aef18ca69 100644 --- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java @@ -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 replaces() { - return WebInfConfiguration.class.getName(); + return WebInfConfiguration.class; } /** diff --git a/jetty-quickstart/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration b/jetty-quickstart/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration new file mode 100644 index 00000000000..8103d26cbea --- /dev/null +++ b/jetty-quickstart/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration @@ -0,0 +1 @@ +org.eclipse.jetty.quickstart.QuickStartConfiguration diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java index 228fbaeb643..9cd1806a0a1 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java @@ -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 getAfterThis() { diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java index e30c4d5fa69..48ac4bff8a3 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java @@ -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 +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 _name = _inclusive ? pattern : pattern.substring(1).trim(); } + boolean isInclusive() + { + return _inclusive; + } + @Override public String toString() { @@ -77,9 +78,9 @@ public class ClasspathPattern extends AbstractList } /* ------------------------------------------------------------ */ - public ClasspathPattern(String[] patterns) + public ClasspathPattern(String... patterns) { - setAll(patterns); + add(patterns); } /* ------------------------------------------------------------ */ @@ -89,41 +90,21 @@ public class ClasspathPattern extends AbstractList } /* ------------------------------------------------------------ */ - @Override - public String get(int index) + public void add(String... patterns) { - return _entries.get(index)._pattern; - } - - /* ------------------------------------------------------------ */ - @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); + 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 remove(int index) - { - Entry e = _entries.remove(index); - return e==null?null:e._pattern; - } /* ------------------------------------------------------------ */ public boolean remove(String pattern) @@ -138,66 +119,24 @@ public class ClasspathPattern extends AbstractList } 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 - */ - private void setAll(String[] classes) - { - _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 array of classpath patterns */ - public String[] getPatterns() + public String[] toArray() { - return toArray(new String[_entries.size()]); + return _entries.stream().map(e->{return e.toString();}).toArray(String[]::new); + } + + /* ------------------------------------------------------------ */ + /** + * @return array of classpath patterns + */ + public List getPatterns() + { + return _entries.stream().map(e->{return e.toString();}).collect(Collectors.toList()); } /* ------------------------------------------------------------ */ @@ -247,42 +186,4 @@ public class ClasspathPattern extends AbstractList return false; } - public void addAfter(String afterPattern,String... patterns) - { - if (patterns!=null && afterPattern!=null) - { - ListIterator iter = listIterator(); - while (iter.hasNext()) - { - String cc=iter.next(); - if (afterPattern.equals(cc)) - { - for (int i=0;i iter = listIterator(); - while (iter.hasNext()) - { - String cc=iter.next(); - if (beforePattern.equals(cc)) - { - iter.previous(); - for (int i=0;i replaces() { return null; } /* ------------------------------------------------------------------------------- */ /** Get known Configuration Dependencies. @@ -75,6 +68,11 @@ public interface Configuration */ public default List 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. *

@@ -133,133 +131,25 @@ public interface Configuration */ public void cloneConfigure (WebAppContext template, WebAppContext context) throws Exception; - public class ClassList - { - List _instances = new ArrayList<>(); - - /* ------------------------------------------------------------ */ - /** Get/Set/Create the server default Configuration ClassList. - *

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.

- *

This method also adds the obtained ClassList instance as a dependent bean - * on the server and clears the attribute

- * @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) throws ClassNotFoundException, InstantiationException, IllegalAccessException - { - 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. - *

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 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 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 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 Use {@link Configurations} + */ + public class ClassList extends Configurations + { + @Deprecated public void addAfter(@Name("afterClass") String afterClass,@Name("configClass")String... configClass) { if (configClass!=null && afterClass!=null) { - ListIterator iter = _instances.listIterator(); + ListIterator 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 iter = _instances.listIterator(); + ListIterator 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 getConfigurations() - { - return _instances.stream().map(i->{return newConfiguration(i.getClass().getName());}).collect(Collectors.toList()); - } - - @Override - public String toString() - { - return getConfigurations().toString(); - } } } diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Configurations.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Configurations.java new file mode 100644 index 00000000000..3a5aac744fb --- /dev/null +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Configurations.java @@ -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 __known = new HashMap<>(); + static + { + ServiceLoader configs = ServiceLoader.load(Configuration.class); + for (Configuration configuration : configs) + __known.put(configuration.getClass().getName(),configuration); + } + + public static Collection getKnown() + { + return Collections.unmodifiableCollection(__known.values()); + } + + protected List _configurations = new ArrayList<>(); + + /* ------------------------------------------------------------ */ + /** Get/Set/Create the server default Configuration ClassList. + *

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.

+ *

This method also adds the obtained ClassList instance as a dependent bean + * on the server and clears the attribute

+ * @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. + *

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 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 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 replaces = configuration.replaces(); + if (replaces!=null) + { + for (ListIterator 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 getConfigurations() + { + // instantiate configurations list + List configurations = _configurations.stream().map(n->{return __known.get(n);}).collect(Collectors.toList()); + + // Sort the configurations + Map map = new HashMap<>(); + TopologicalSort 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(); + } + +} \ No newline at end of file diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java index 810a3c484c5..de55d22f8d5 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java @@ -36,6 +36,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 diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java index 383489e30f1..acc796046a2 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java @@ -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 diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java index 3b7cf15ff4d..0138d410132 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java @@ -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 { diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java index cce67c210e2..c726169021d 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java @@ -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", - } ; + public static final String[] DEFAULT_CONFIGURATION_CLASSES = + 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 map = new HashMap<>(); - TopologicalSort 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(); + loadServerClasses(); + 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 Jetty Documentation: Classloading */ public void addServerClass(String classOrPackage) { - if (_serverClasses == null) - loadServerClasses(); - + 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 Jetty Documentation: Classloading */ 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(); + loadSystemClasses(); + 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 Jetty Documentation: Classloading */ public void addSystemClass(String classOrPackage) { - if (_systemClasses == null) - loadSystemClasses(); - + 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 - * separated list of classOrPackage patterns. + * 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 Jetty Documentation: Classloading */ public void prependSystemClass(String classOrPackage) { - if (_systemClasses == null) - loadSystemClasses(); - - _systemClasses.prependPattern(classOrPackage); + loadSystemClasses(); + _systemClasses.add(classOrPackage); } /* ------------------------------------------------------------ */ @Override public boolean isServerClass(String name) { - if (_serverClasses == null) - loadServerClasses(); - + 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(); - + 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())), diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java index 1827936d048..a41a3bd5252 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java @@ -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 { diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java index 4c5a59df90d..fc0a0774105 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java @@ -42,6 +42,13 @@ public class WebXmlConfiguration extends AbstractConfiguration super(new String[]{WebInfConfiguration.class.getName()},null); } + /* ------------------------------------------------------------------------------- */ + @Override + public boolean isEnabledByDefault() + { + return true; + } + /* ------------------------------------------------------------------------------- */ /** * diff --git a/jetty-webapp/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration b/jetty-webapp/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration new file mode 100644 index 00000000000..7bfedb9773d --- /dev/null +++ b/jetty-webapp/src/main/resources/META-INF/services/org.eclipse.jetty.webapp.Configuration @@ -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 diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/ClasspathPatternTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/ClasspathPatternTest.java index 1b41bc9b34e..6cfe787c0ec 100644 --- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/ClasspathPatternTest.java +++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/ClasspathPatternTest.java @@ -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() {