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
This commit is contained in:
Michael Gorovoy 2010-05-04 16:16:24 +00:00
parent 52d8ac5321
commit a4d20486b2
3 changed files with 370 additions and 111 deletions

View File

@ -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

View File

@ -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;
}
}

View File

@ -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)
{
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;
}
}
return false;
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)
{
Object systemClasses = server.getAttribute(SERVER_SYS_CLASSES);
if (systemClasses != null && systemClasses instanceof String[])
_systemClasses = ClasspathPattern.fromArray((String[])systemClasses);
}
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);
}