From 8c91c6c16698c5345040604d27633470eab03d91 Mon Sep 17 00:00:00 2001 From: Michael Gorovoy Date: Tue, 13 Apr 2010 15:56:48 +0000 Subject: [PATCH] 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@1507 7e9141cc-0065-0410-87d8-b60c137991c4 --- VERSION.txt | 1 + .../jetty/webapp/ClasspathPattern.java | 188 ++++++++++++++ .../eclipse/jetty/webapp/WebAppContext.java | 235 ++++++++---------- 3 files changed, 297 insertions(+), 127 deletions(-) create mode 100644 jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java diff --git a/VERSION.txt b/VERSION.txt index 3c20fb2442f..a08e492b71a 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1,5 +1,6 @@ jetty-7.1-SNAPSHOT + + 286889 Allow System and Server classes to be set on Server instance and when applied to all webapps + 294563 Websocket client connection + 297104 Improve handling of CONNECT method + 306349 ProxyServlet does not work unless deployed at / 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 00000000000..273b59d4e31 --- /dev/null +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java @@ -0,0 +1,188 @@ +// ======================================================================== +// 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.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 String[] _patterns = null; + private 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 = patterns.clone(); + _entries = new Entry[patterns.length]; + } + + if (_patterns != null) { + String item = null; + for (int idx=0; idx<_patterns.length; idx++) + { + item = _patterns[idx].trim(); + if (item != null) + { + Entry entry = new Entry(); + entry.result = !item.startsWith("-"); + entry.partial = item.endsWith("."); + entry.classpath = entry.result ? item : item.substring(1).trim(); + _entries[idx] = entry; + } + } + } + } + + /* ------------------------------------------------------------ */ + /** + * Initialize the matcher by parsing a classpath pattern string + * + * @param pattern classpath pattern string + */ + private void setPattern(String pattern) + { + ArrayList patterns = new ArrayList(); + StringTokenizer entries = new StringTokenizer(pattern, ":,"); + while (entries.hasMoreTokens()) + { + patterns.add(entries.nextToken()); + } + + setPatterns((String[])patterns.toArray()); + } + + /* ------------------------------------------------------------ */ + /** + * @return array of classpath patterns + */ + public String[] getPatterns() + { + 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('/','.'); + while(name.startsWith(".")) + ++startIdx; + if (startIdx > 0) + name = name.substring(startIdx); + + for (int idx=0; idx<_entries.length; idx++) + { + Entry entry = _entries[idx]; + 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 c25b40fd182..61e6976c86b 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 @@ -30,6 +30,7 @@ import javax.servlet.http.HttpSessionListener; import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HandlerContainer; +import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.server.session.SessionHandler; @@ -64,8 +65,10 @@ 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 = + private final static String[] __dftConfigurationClasses = { "org.eclipse.jetty.webapp.WebInfConfiguration", "org.eclipse.jetty.webapp.WebXmlConfiguration", @@ -74,7 +77,40 @@ public class WebAppContext extends ServletContextHandler "org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.webapp.TagLibConfiguration" } ; + + // 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.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.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; @@ -85,26 +121,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; @@ -318,7 +335,12 @@ public class WebAppContext extends ServletContextHandler // Setup configurations loadConfigurations(); + // Setup system classes + loadSystemClasses(); + // Setup server classes + loadServerClasses(); + // Configure classloader _ownClassLoader=false; if (getClassLoader()==null) @@ -456,7 +478,6 @@ public class WebAppContext extends ServletContextHandler { return _permissions; } - /* ------------------------------------------------------------ */ /** @@ -465,27 +486,12 @@ 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; - } - /* ------------------------------------------------------------ */ /** * @see #setSystemClasses(String[]) @@ -493,95 +499,67 @@ 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; - } - /* ------------------------------------------------------------ */ 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