diff options
author | Michael Gorovoy | 2010-05-04 16:16:24 +0000 |
---|---|---|
committer | Michael Gorovoy | 2010-05-04 16:16:24 +0000 |
commit | a4d20486b2ddc76db0cf96bd0e2e26fa2a5f1dea (patch) | |
tree | 14e0e835e3002d3fb4180082b6e4ba6afbb9315d | |
parent | 52d8ac532100f92586c9aeeb560f36d86d242e66 (diff) | |
download | org.eclipse.jetty.project-a4d20486b2ddc76db0cf96bd0e2e26fa2a5f1dea.tar.gz org.eclipse.jetty.project-a4d20486b2ddc76db0cf96bd0e2e26fa2a5f1dea.tar.xz org.eclipse.jetty.project-a4d20486b2ddc76db0cf96bd0e2e26fa2a5f1dea.zip |
286889 Allow System and Server classes to be set on Server instance and when applied to all webapps
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1688 7e9141cc-0065-0410-87d8-b60c137991c4
-rw-r--r-- | VERSION.txt | 1 | ||||
-rw-r--r-- | jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java | 262 | ||||
-rw-r--r-- | jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java | 216 |
3 files changed, 369 insertions, 110 deletions
diff --git a/VERSION.txt b/VERSION.txt index 4f2b25bcb7..ffb0353337 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1,4 +1,5 @@ jetty-7.1.0.RC1-SNAPSHOT + + 286889 Allow System and Server classes to be set on Server instance and when applied to all webapps + 296650 JETTY-1198 reset idle timeout on request body chunks + 291448 SessionManager has isCheckingRemoteSessionIdEncoding + 297104 HTTP CONNECT does not work correct with SSL destinations 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 new file mode 100644 index 0000000000..d57cc012ca --- /dev/null +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java @@ -0,0 +1,262 @@ +// ======================================================================== +// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== + + +package org.eclipse.jetty.webapp; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.StringTokenizer; + + +/* ------------------------------------------------------------ */ +/** + * ClasspathPattern performs sequential pattern matching of a class name + * against an internal array of classpath pattern entries. + * + * When an entry starts with '-' (minus), reverse matching is performed. + * When an entry ends with '.' (period), prefix matching is performed. + * + * When class is initialized from a classpath pattern string, entries + * in this string should be separated by ':' (semicolon) or ',' (comma). + */ + +public class ClasspathPattern +{ + private class Entry + { + public String classpath = null; + public boolean result = false; + public boolean partial = false; + } + + private ArrayList<String> _patterns = null; + private ArrayList<Entry> _entries = null; + + public ClasspathPattern(String[] patterns) + { + setPatterns(patterns); + } + + public ClasspathPattern(String pattern) + { + setPattern(pattern); + } + + /* ------------------------------------------------------------ */ + /** + * Create a new instance from a String array of classpath patterns + * + * @param patterns array of classpath patterns + * @return + */ + public static ClasspathPattern fromArray(String[] patterns) + { + return new ClasspathPattern(patterns); + } + + /* ------------------------------------------------------------ */ + /** + * Create a new instance from a classpath pattern sring + * + * @param patterns classpath pattern string + * @return + */ + public static ClasspathPattern fromString(String patterns) + { + return new ClasspathPattern(patterns); + } + + /* ------------------------------------------------------------ */ + /** + * Initialize the matcher by parsing each classpath pattern in an array + * + * @param patterns array of classpath patterns + */ + private void setPatterns(String[] patterns) + { + if (patterns == null) + { + _patterns = null; + _entries = null; + } + else + { + _patterns = new ArrayList<String>(); + _entries = new ArrayList<Entry>(); + } + + if (_patterns != null) { + Entry entry = null; + for (String pattern : patterns) + { + entry = createEntry(pattern); + if (entry != null) { + _patterns.add(pattern); + _entries.add(entry); + } + } + } + } + + /* ------------------------------------------------------------ */ + /** + * Initialize the matcher by parsing each classpath pattern in an array + * + * @param patterns array of classpath patterns + */ + private void addPatterns(String[] patterns) + { + if (patterns != null) + { + if (_patterns == null) + { + setPatterns(patterns); + } + else + { + Entry entry = null; + for (String pattern : patterns) + { + entry = createEntry(pattern); + if (entry != null) { + _patterns.add(pattern); + _entries.add(entry); + } + } + } + } + } + + /* ------------------------------------------------------------ */ + /** + * Create an entry object containing information about + * a single classpath pattern + * + * @param pattern single classpath pattern + * @return corresponding Entry object + */ + private Entry createEntry(String pattern) + { + Entry entry = null; + + if (pattern != null) + { + String item = pattern.trim(); + if (item.length() > 0) + { + entry = new Entry(); + entry.result = !item.startsWith("-"); + entry.partial = item.endsWith("."); + entry.classpath = entry.result ? item : item.substring(1).trim(); + } + } + return entry; + } + + /* ------------------------------------------------------------ */ + /** + * Initialize the matcher by parsing a classpath pattern string + * + * @param pattern classpath pattern string + */ + public void setPattern(String pattern) + { + ArrayList<String> patterns = new ArrayList<String>(); + StringTokenizer entries = new StringTokenizer(pattern, ":,"); + while (entries.hasMoreTokens()) + { + patterns.add(entries.nextToken()); + } + + setPatterns((String[])patterns.toArray()); + } + + /* ------------------------------------------------------------ */ + /** + * Parse a classpath pattern string and appending the result + * to the existing configuration. + * + * @param pattern classpath pattern string + */ + public void addPattern(String pattern) + { + ArrayList<String> patterns = new ArrayList<String>(); + StringTokenizer entries = new StringTokenizer(pattern, ":,"); + while (entries.hasMoreTokens()) + { + patterns.add(entries.nextToken()); + } + + addPatterns((String[])patterns.toArray()); + } + + /* ------------------------------------------------------------ */ + /** + * @return array of classpath patterns + */ + public String[] getPatterns() + { + String[] patterns = null; + + if (_patterns!=null) + { + patterns = _patterns.toArray(new String[_patterns.size()]); + } + + return patterns; + } + + /* ------------------------------------------------------------ */ + /** + * Match the class name against the pattern + * + * @param name name of the class to match + * @return true if class matches the pattern + */ + public boolean match(String name) + { + boolean result=false; + + if (_entries != null) + { + int startIdx = 0; + name = name.replace('/','.'); + name = name.replaceFirst("^[.]+",""); + + for (Entry entry : _entries) + { + if (entry != null) + { + if (entry.partial) + { + if (name.startsWith(entry.classpath)) + { + result = entry.result; + break; + } + } + else + { + if (name.equals(entry.classpath)) + { + result = entry.result; + break; + } + } + } + } + } + return result; + } +} 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 f1d50945db..18e8ad26af 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 @@ -20,6 +20,7 @@ import java.net.URL; import java.security.PermissionCollection; import java.util.EventListener; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.jar.JarFile; @@ -67,6 +68,8 @@ public class WebAppContext extends ServletContextHandler public final static String WEB_DEFAULTS_XML="org/eclipse/jetty/webapp/webdefault.xml"; public final static String ERROR_PAGE="org.eclipse.jetty.server.error_page"; public final static String SERVER_CONFIG = "org.eclipse.jetty.webapp.configuration"; + public final static String SERVER_SYS_CLASSES = "org.eclipse.jetty.webapp.systemClasses"; + public final static String SERVER_SRV_CLASSES = "org.eclipse.jetty.webapp.serverClasses"; private static String[] __dftConfigurationClasses = { @@ -77,7 +80,42 @@ public class WebAppContext extends ServletContextHandler "org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.webapp.TagLibConfiguration" } ; - private String[] _configurationClasses=__dftConfigurationClasses; + + // System classes are classes that cannot be replaced by + // the web application, and they are *always* loaded via + // system classloader. + private final static String[] __dftSystemClasses = + { + "java.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2) + "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 + "apache.commons.logging.", // special case + "org.eclipse.jetty.continuation.", // webapp cannot change continuation classes + "org.eclipse.jetty.jndi.", // webapp cannot change naming classes + "org.eclipse.jetty.plus.jaas.", // webapp cannot change jaas classes + "org.eclipse.jetty.websocket.", // WebSocket is a jetty extension + "org.eclipse.jetty.servlet.DefaultServlet" // webapp cannot change default servlets + } ; + + // Server classes are classes that are hidden from being + // loaded by the web application using system classloader, + // so if web application needs to load any of such classes, + // it has to include them in its distribution. + private final static String[] __dftServerClasses = + { + "-org.eclipse.jetty.continuation.", // don't hide continuation classes + "-org.eclipse.jetty.jndi.", // don't hide naming classes + "-org.eclipse.jetty.plus.jaas.", // don't hide jaas classes + "-org.eclipse.jetty.websocket.", // don't hide websocket extension + "-org.eclipse.jetty.servlet.DefaultServlet", // don't hide default servlet + "org.eclipse.jetty." // hide other jetty classes + } ; + + private String[] _configurationClasses=null; + private ClasspathPattern _systemClasses = null; + private ClasspathPattern _serverClasses = null; + private Configuration[] _configurations; private String _defaultsDescriptor=WEB_DEFAULTS_XML; private String _descriptor=null; @@ -88,26 +126,7 @@ public class WebAppContext extends ServletContextHandler private boolean _logUrlOnStart =false; private boolean _parentLoaderPriority= Boolean.getBoolean("org.eclipse.jetty.server.webapp.parentLoaderPriority"); private PermissionCollection _permissions; - private String[] _systemClasses = { - "java.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2) - "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.apache.commons.logging.", // special case. - "org.eclipse.jetty.continuation.", // webapp cannot change continuation classes - "org.eclipse.jetty.jndi.", // webapp cannot change naming classes - "org.eclipse.jetty.plus.jaas.", // webapp cannot change jetty jaas classes - "org.eclipse.jetty.servlet.DefaultServlet", // webapp cannot change default servlets - "org.eclipse.jetty.websocket.", // WebSocket is a jetty extension - }; - private String[] _serverClasses = { - "-org.eclipse.jetty.continuation.", // don't hide continuation classes - "-org.eclipse.jetty.jndi.", // don't hide naming classes - "-org.eclipse.jetty.plus.jaas.", // don't hide jaas modules - "-org.eclipse.jetty.servlet.DefaultServlet", // webapp cannot change default servlets - "-org.eclipse.jetty.websocket.", // don't hide websocket extension - "org.eclipse.jetty." // hide rest of jetty classes - }; + private File _tmpDir; private String _war; private String _extraClasspath; @@ -326,7 +345,12 @@ public class WebAppContext extends ServletContextHandler // Setup configurations loadConfigurations(); + // Setup system classes + loadSystemClasses(); + // Setup server classes + loadServerClasses(); + // Configure classloader _ownClassLoader=false; if (getClassLoader()==null) @@ -464,7 +488,6 @@ public class WebAppContext extends ServletContextHandler { return _permissions; } - /* ------------------------------------------------------------ */ /** @@ -473,25 +496,18 @@ public class WebAppContext extends ServletContextHandler */ public String[] getServerClasses() { - return _serverClasses; + if (_serverClasses == null) + loadServerClasses(); + + return _serverClasses.getPatterns(); } - + public void addServerClass(String classname) { - for (int i = 0, n = _serverClasses.length; i < n; i++) - { - if (_serverClasses[i].equals(classname)) - { - // Already present. - return; - } - } - - int len = _serverClasses.length + 1; - String sysclass[] = new String[len]; - System.arraycopy(_serverClasses,0,sysclass,0,len - 1); - sysclass[len - 1] = classname; - _serverClasses = sysclass; + if (_serverClasses == null) + loadServerClasses(); + + _serverClasses.addPattern(classname); } /* ------------------------------------------------------------ */ @@ -501,95 +517,75 @@ public class WebAppContext extends ServletContextHandler */ public String[] getSystemClasses() { - return _systemClasses; + if (_systemClasses == null) + loadSystemClasses(); + + return _systemClasses.getPatterns(); } public void addSystemClass(String classname) { - for (int i = 0, n = _systemClasses.length; i < n; i++) - { - if (_systemClasses[i].equals(classname)) - { - // Already present. - return; - } - } - - int len = _systemClasses.length + 1; - String sysclass[] = new String[len]; - System.arraycopy(_systemClasses,0,sysclass,0,len - 1); - sysclass[len - 1] = classname; - _systemClasses = sysclass; + if (_systemClasses == null) + loadSystemClasses(); + + _systemClasses.addPattern(classname); } /* ------------------------------------------------------------ */ public boolean isServerClass(String name) { - name=name.replace('/','.'); - while(name.startsWith(".")) - name=name.substring(1); - - String[] server_classes = getServerClasses(); - if (server_classes!=null) - { - for (int i=0;i<server_classes.length;i++) - { - boolean result=true; - String c=server_classes[i]; - if (c.startsWith("-")) - { - c=c.substring(1); // TODO cache - result=false; - } - - if (c.endsWith(".")) - { - if (name.startsWith(c)) - return result; - } - else if (name.equals(c)) - return result; - } - } - return false; + if (_serverClasses == null) + loadServerClasses(); + + return _serverClasses.match(name); } /* ------------------------------------------------------------ */ public boolean isSystemClass(String name) { - name=name.replace('/','.'); - while(name.startsWith(".")) - name=name.substring(1); - String[] system_classes = getSystemClasses(); - if (system_classes!=null) + if (_systemClasses == null) + loadSystemClasses(); + + return _systemClasses.match(name); + } + + private void loadSystemClasses() + { + if (_systemClasses != null) + return; + + //look for a Server attribute with the list of System classes + //to apply to every web application. If not present, use our defaults. + Server server = getServer(); + if (server != null) { - for (int i=0;i<system_classes.length;i++) - { - boolean result=true; - String c=system_classes[i]; - - if (c.startsWith("-")) - { - c=c.substring(1); // TODO cache - result=false; - } - - if (c.endsWith(".")) - { - if (name.startsWith(c)) - return result; - } - else if (name.equals(c)) - return result; - } + Object systemClasses = server.getAttribute(SERVER_SYS_CLASSES); + if (systemClasses != null && systemClasses instanceof String[]) + _systemClasses = ClasspathPattern.fromArray((String[])systemClasses); } - return false; - + if (_systemClasses == null) + _systemClasses = ClasspathPattern.fromArray(__dftSystemClasses); } - - + private void loadServerClasses() + { + if (_serverClasses != null) + return; + + //look for a Server attribute with the list of Server classes + //to apply to every web application. If not present, use our defaults. + Server server = getServer(); + if (server != null) + { + Object serverClasses = server.getAttribute(SERVER_SRV_CLASSES); + if (serverClasses != null || serverClasses instanceof String[]) + _serverClasses = ClasspathPattern.fromArray((String[])serverClasses); + } + + if (_serverClasses == null) + _serverClasses = ClasspathPattern.fromArray(__dftServerClasses); + } /* ------------------------------------------------------------ */ /** @@ -859,7 +855,7 @@ public class WebAppContext extends ServletContextHandler */ public void setServerClasses(String[] serverClasses) { - _serverClasses = serverClasses==null?null:(String[])serverClasses.clone(); + _serverClasses = ClasspathPattern.fromArray(serverClasses); } /* ------------------------------------------------------------ */ @@ -879,7 +875,7 @@ public class WebAppContext extends ServletContextHandler */ public void setSystemClasses(String[] systemClasses) { - _systemClasses = systemClasses==null?null:(String[])systemClasses.clone(); + _systemClasses = ClasspathPattern.fromArray(systemClasses); } |