Merge branch 'jetty-7' into release-7
This commit is contained in:
commit
073ab7af20
|
@ -29,6 +29,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
|
@ -426,7 +427,7 @@ public class AnnotationParser
|
|||
List<DiscoverableAnnotationHandler> handlers = _annotationHandlers.get(annotationName);
|
||||
if (handlers == null)
|
||||
return Collections.emptyList();
|
||||
return new ArrayList<DiscoverableAnnotationHandler>();
|
||||
return new ArrayList<DiscoverableAnnotationHandler>(handlers);
|
||||
}
|
||||
|
||||
public List<DiscoverableAnnotationHandler> getAnnotationHandlers()
|
||||
|
@ -580,7 +581,7 @@ public class AnnotationParser
|
|||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().endsWith(".class"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
|
||||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
if ((resolver == null)
|
||||
|
@ -624,7 +625,7 @@ public class AnnotationParser
|
|||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().endsWith(".class"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
|
||||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.annotations;
|
|||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.naming.InitialContext;
|
||||
|
@ -262,7 +263,7 @@ public class ResourceAnnotationHandler extends AbstractIntrospectableAnnotationH
|
|||
|
||||
//default name is the javabean property name
|
||||
String name = method.getName().substring(3);
|
||||
name = name.substring(0,1).toLowerCase()+name.substring(1);
|
||||
name = name.substring(0,1).toLowerCase(Locale.ENGLISH)+name.substring(1);
|
||||
name = clazz.getCanonicalName()+"/"+name;
|
||||
|
||||
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.eclipse.jetty.client;
|
|||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
|
||||
import org.eclipse.jetty.client.helperClasses.SslServerAndClientCreator;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
|
@ -51,7 +53,7 @@ public class SslHttpExchangeTest extends HttpExchangeTest
|
|||
{
|
||||
// Use Junit 4.x to flag test as ignored if encountering IBM JVM
|
||||
// Will show up in various junit reports as an ignored test as well.
|
||||
Assume.assumeThat(System.getProperty("java.vendor").toLowerCase(),not(containsString("ibm")));
|
||||
Assume.assumeThat(System.getProperty("java.vendor").toLowerCase(Locale.ENGLISH),not(containsString("ibm")));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.io.OutputStream;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -126,7 +127,7 @@ public class SslSecurityListenerTest
|
|||
public void testSslGet() throws Exception
|
||||
{
|
||||
// TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532
|
||||
if (System.getProperty("java.vendor").toLowerCase().indexOf("ibm")>=0)
|
||||
if (System.getProperty("java.vendor").toLowerCase(Locale.ENGLISH).indexOf("ibm")>=0)
|
||||
{
|
||||
LOG.warn("Skipped SSL testSslGet on IBM JVM");
|
||||
return;
|
||||
|
|
|
@ -214,6 +214,7 @@ public class WebSocketUpgradeTest
|
|||
return _websocket;
|
||||
}
|
||||
};
|
||||
_handler.getWebSocketFactory().setMinVersion(-1);
|
||||
|
||||
_server.setHandler(_handler);
|
||||
_server.start();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.deploy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.deploy.providers.ScanningAppProvider;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
|
@ -223,7 +224,7 @@ public class WebAppDeployer extends AbstractLifeCycle
|
|||
|
||||
Resource app=r.addPath(r.encode(context));
|
||||
|
||||
if (context.toLowerCase().endsWith(".war")||context.toLowerCase().endsWith(".jar"))
|
||||
if (context.toLowerCase(Locale.ENGLISH).endsWith(".war")||context.toLowerCase(Locale.ENGLISH).endsWith(".jar"))
|
||||
{
|
||||
context=context.substring(0,context.length()-4);
|
||||
Resource unpacked=r.addPath(context);
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.deploy.providers;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.deploy.App;
|
||||
import org.eclipse.jetty.deploy.ConfigurationManager;
|
||||
|
@ -45,7 +46,7 @@ public class ContextProvider extends ScanningAppProvider
|
|||
{
|
||||
if (!dir.exists())
|
||||
return false;
|
||||
String lowername = name.toLowerCase();
|
||||
String lowername = name.toLowerCase(Locale.ENGLISH);
|
||||
if (lowername.startsWith("."))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.File;
|
|||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.deploy.App;
|
||||
import org.eclipse.jetty.deploy.util.FileID;
|
||||
|
@ -59,7 +60,7 @@ public class WebAppProvider extends ScanningAppProvider
|
|||
{
|
||||
return false;
|
||||
}
|
||||
String lowername = name.toLowerCase();
|
||||
String lowername = name.toLowerCase(Locale.ENGLISH);
|
||||
|
||||
File file = new File(dir,name);
|
||||
// is it not a directory and not a war ?
|
||||
|
@ -279,9 +280,9 @@ public class WebAppProvider extends ScanningAppProvider
|
|||
{
|
||||
context = URIUtil.SLASH;
|
||||
}
|
||||
else if (context.toLowerCase().startsWith("root-"))
|
||||
else if (context.toLowerCase(Locale.ENGLISH).startsWith("root-"))
|
||||
{
|
||||
int dash=context.toLowerCase().indexOf('-');
|
||||
int dash=context.toLowerCase(Locale.ENGLISH).indexOf('-');
|
||||
String virtual = context.substring(dash+1);
|
||||
wah.setVirtualHosts(new String[]{virtual});
|
||||
context = URIUtil.SLASH;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.deploy.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Simple, yet surprisingly common utility methods for identifying various file types commonly seen and worked with in a
|
||||
|
@ -38,7 +39,7 @@ public class FileID
|
|||
{
|
||||
if (path.isFile())
|
||||
{
|
||||
String name = path.getName().toLowerCase();
|
||||
String name = path.getName().toLowerCase(Locale.ENGLISH);
|
||||
return (name.endsWith(".war") || name.endsWith(".jar"));
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,7 @@ public class FileID
|
|||
return false;
|
||||
}
|
||||
|
||||
String name = path.getName().toLowerCase();
|
||||
String name = path.getName().toLowerCase(Locale.ENGLISH);
|
||||
return (name.endsWith(".war") || name.endsWith(".jar"));
|
||||
}
|
||||
|
||||
|
@ -73,7 +74,7 @@ public class FileID
|
|||
return false;
|
||||
}
|
||||
|
||||
String name = path.getName().toLowerCase();
|
||||
String name = path.getName().toLowerCase(Locale.ENGLISH);
|
||||
return name.endsWith(".xml");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -934,6 +934,9 @@ public class HttpFields
|
|||
QuotedStringTokenizer.quoteIfNeeded(buf, name, delim);
|
||||
buf.append('=');
|
||||
String start=buf.toString();
|
||||
boolean hasDomain = false;
|
||||
boolean hasPath = false;
|
||||
|
||||
if (value != null && value.length() > 0)
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf, value, delim);
|
||||
|
||||
|
@ -945,6 +948,7 @@ public class HttpFields
|
|||
|
||||
if (path != null && path.length() > 0)
|
||||
{
|
||||
hasPath = true;
|
||||
buf.append(";Path=");
|
||||
if (path.trim().startsWith("\""))
|
||||
buf.append(path);
|
||||
|
@ -953,8 +957,9 @@ public class HttpFields
|
|||
}
|
||||
if (domain != null && domain.length() > 0)
|
||||
{
|
||||
hasDomain = true;
|
||||
buf.append(";Domain=");
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(),delim);
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(Locale.ENGLISH),delim);
|
||||
}
|
||||
|
||||
if (maxAge >= 0)
|
||||
|
@ -985,14 +990,20 @@ public class HttpFields
|
|||
Field last=null;
|
||||
while (field!=null)
|
||||
{
|
||||
if (field._value!=null && field._value.toString().startsWith(start))
|
||||
String val = (field._value == null ? null : field._value.toString());
|
||||
if (val!=null && val.startsWith(start))
|
||||
{
|
||||
_fields.remove(field);
|
||||
if (last==null)
|
||||
_names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next);
|
||||
else
|
||||
last._next=field._next;
|
||||
break;
|
||||
//existing cookie has same name, does it also match domain and path?
|
||||
if (((!hasDomain && !val.contains("Domain")) || (hasDomain && val.contains("Domain="+domain))) &&
|
||||
((!hasPath && !val.contains("Path")) || (hasPath && val.contains("Path="+path))))
|
||||
{
|
||||
_fields.remove(field);
|
||||
if (last==null)
|
||||
_names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next);
|
||||
else
|
||||
last._next=field._next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
last=field;
|
||||
field=field._next;
|
||||
|
|
|
@ -94,7 +94,15 @@ public class HttpURI
|
|||
public HttpURI(String raw)
|
||||
{
|
||||
_rawString=raw;
|
||||
byte[] b = raw.getBytes();
|
||||
byte[] b;
|
||||
try
|
||||
{
|
||||
b = raw.getBytes(StringUtil.__UTF8);
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
parse(b,0,b.length);
|
||||
}
|
||||
|
||||
|
@ -700,7 +708,7 @@ public class HttpURI
|
|||
if (encoding==null || StringUtil.isUTF8(encoding))
|
||||
UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters);
|
||||
else
|
||||
UrlEncoded.decodeTo(toUtf8String(_query+1,_fragment-_query-1),parameters,encoding);
|
||||
UrlEncoded.decodeTo(StringUtil.toString(_raw,_query+1,_fragment-_query-1,encoding),parameters,encoding);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
|
|
|
@ -171,6 +171,7 @@ xhtml = application/xhtml+xml
|
|||
xls = application/vnd.ms-excel
|
||||
xml = application/xml
|
||||
xpm = image/x-xpixmap
|
||||
xsd = application/xml
|
||||
xsl = application/xml
|
||||
xslt = application/xslt+xml
|
||||
xul = application/vnd.mozilla.xul+xml
|
||||
|
|
|
@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
|
@ -312,8 +313,8 @@ public class HttpFieldsTest
|
|||
s=enum2set(fields.getFieldNames());
|
||||
assertEquals(3,s.size());
|
||||
assertTrue(s.contains("message-id"));
|
||||
assertEquals("value",fields.getStringField("message-id").toLowerCase());
|
||||
assertEquals("value",fields.getStringField("Message-ID").toLowerCase());
|
||||
assertEquals("value",fields.getStringField("message-id").toLowerCase(Locale.ENGLISH));
|
||||
assertEquals("value",fields.getStringField("Message-ID").toLowerCase(Locale.ENGLISH));
|
||||
|
||||
fields.clear();
|
||||
|
||||
|
@ -323,8 +324,8 @@ public class HttpFieldsTest
|
|||
s=enum2set(fields.getFieldNames());
|
||||
assertEquals(3,s.size());
|
||||
assertTrue(s.contains("message-id"));
|
||||
assertEquals("value",fields.getStringField("Message-ID").toLowerCase());
|
||||
assertEquals("value",fields.getStringField("message-id").toLowerCase());
|
||||
assertEquals("value",fields.getStringField("Message-ID").toLowerCase(Locale.ENGLISH));
|
||||
assertEquals("value",fields.getStringField("message-id").toLowerCase(Locale.ENGLISH));
|
||||
|
||||
fields.clear();
|
||||
|
||||
|
@ -334,8 +335,8 @@ public class HttpFieldsTest
|
|||
s=enum2set(fields.getFieldNames());
|
||||
assertEquals(3,s.size());
|
||||
assertTrue(s.contains("message-id"));
|
||||
assertEquals("value",fields.getStringField("message-id").toLowerCase());
|
||||
assertEquals("value",fields.getStringField("Message-ID").toLowerCase());
|
||||
assertEquals("value",fields.getStringField("message-id").toLowerCase(Locale.ENGLISH));
|
||||
assertEquals("value",fields.getStringField("Message-ID").toLowerCase(Locale.ENGLISH));
|
||||
|
||||
fields.clear();
|
||||
|
||||
|
@ -345,8 +346,8 @@ public class HttpFieldsTest
|
|||
s=enum2set(fields.getFieldNames());
|
||||
assertEquals(3,s.size());
|
||||
assertTrue(s.contains("message-id"));
|
||||
assertEquals("value",fields.getStringField("Message-ID").toLowerCase());
|
||||
assertEquals("value",fields.getStringField("message-id").toLowerCase());
|
||||
assertEquals("value",fields.getStringField("Message-ID").toLowerCase(Locale.ENGLISH));
|
||||
assertEquals("value",fields.getStringField("message-id").toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -364,7 +365,8 @@ public class HttpFieldsTest
|
|||
assertEquals("minimal=value",fields.getStringField("Set-Cookie"));
|
||||
|
||||
fields.clear();
|
||||
fields.addSetCookie("everything","wrong","wrong","wrong",0,"to be replaced",true,true,0);
|
||||
//test cookies with same name, domain and path, only 1 allowed
|
||||
fields.addSetCookie("everything","wrong","domain","path",0,"to be replaced",true,true,0);
|
||||
fields.addSetCookie("everything","value","domain","path",0,"comment",true,true,0);
|
||||
assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",fields.getStringField("Set-Cookie"));
|
||||
Enumeration<String> e =fields.getValues("Set-Cookie");
|
||||
|
@ -372,6 +374,61 @@ public class HttpFieldsTest
|
|||
assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires"));
|
||||
assertFalse(e.hasMoreElements());
|
||||
|
||||
//test cookies with same name, different domain
|
||||
fields.clear();
|
||||
fields.addSetCookie("everything","other","domain1","path",0,"blah",true,true,0);
|
||||
fields.addSetCookie("everything","value","domain2","path",0,"comment",true,true,0);
|
||||
e =fields.getValues("Set-Cookie");
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=other;Comment=blah;Path=path;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=value;Comment=comment;Path=path;Domain=domain2;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
|
||||
//test cookies with same name, same path, one with domain, one without
|
||||
fields.clear();
|
||||
fields.addSetCookie("everything","other","domain1","path",0,"blah",true,true,0);
|
||||
fields.addSetCookie("everything","value","","path",0,"comment",true,true,0);
|
||||
e =fields.getValues("Set-Cookie");
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=other;Comment=blah;Path=path;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=value;Comment=comment;Path=path;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
|
||||
|
||||
//test cookies with same name, different path
|
||||
fields.clear();
|
||||
fields.addSetCookie("everything","other","domain1","path1",0,"blah",true,true,0);
|
||||
fields.addSetCookie("everything","value","domain1","path2",0,"comment",true,true,0);
|
||||
e =fields.getValues("Set-Cookie");
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=other;Comment=blah;Path=path1;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=value;Comment=comment;Path=path2;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
|
||||
//test cookies with same name, same domain, one with path, one without
|
||||
fields.clear();
|
||||
fields.addSetCookie("everything","other","domain1","path1",0,"blah",true,true,0);
|
||||
fields.addSetCookie("everything","value","domain1","",0,"comment",true,true,0);
|
||||
e =fields.getValues("Set-Cookie");
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=other;Comment=blah;Path=path1;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=value;Comment=comment;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
|
||||
//test cookies same name only, no path, no domain
|
||||
fields.clear();
|
||||
fields.addSetCookie("everything","other","","",0,"blah",true,true,0);
|
||||
fields.addSetCookie("everything","value","","",0,"comment",true,true,0);
|
||||
e =fields.getValues("Set-Cookie");
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=value;Comment=comment;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
|
||||
fields.clear();
|
||||
fields.addSetCookie("ev erything","va lue","do main","pa th",1,"co mment",true,true,2);
|
||||
|
@ -402,7 +459,7 @@ public class HttpFieldsTest
|
|||
{
|
||||
Set<String> s=new HashSet<String>();
|
||||
while(e.hasMoreElements())
|
||||
s.add(e.nextElement().toLowerCase());
|
||||
s.add(e.nextElement().toLowerCase(Locale.ENGLISH));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.nio.channels.ClosedChannelException;
|
|||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
|
@ -42,7 +43,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
{
|
||||
public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
|
||||
|
||||
private final boolean WORK_AROUND_JVM_BUG_6346658 = System.getProperty("os.name").toLowerCase().contains("win");
|
||||
private final boolean WORK_AROUND_JVM_BUG_6346658 = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win");
|
||||
private final SelectorManager.SelectSet _selectSet;
|
||||
private final SelectorManager _manager;
|
||||
private SelectionKey _key;
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.eclipse.jetty.security.IdentityService;
|
|||
import org.eclipse.jetty.security.ServerAuthException;
|
||||
import org.eclipse.jetty.security.UserAuthentication;
|
||||
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
|
||||
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
|
||||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.eclipse.jetty.server.Authentication.User;
|
||||
|
@ -44,7 +45,7 @@ import org.eclipse.jetty.server.Authentication.User;
|
|||
/**
|
||||
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
|
||||
*/
|
||||
public class JaspiAuthenticator implements Authenticator
|
||||
public class JaspiAuthenticator extends LoginAuthenticator
|
||||
{
|
||||
private final ServerAuthConfig _authConfig;
|
||||
|
||||
|
@ -58,7 +59,7 @@ public class JaspiAuthenticator implements Authenticator
|
|||
|
||||
private final IdentityService _identityService;
|
||||
|
||||
private final DeferredAuthentication _deferred;
|
||||
|
||||
|
||||
public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler, Subject serviceSubject,
|
||||
boolean allowLazyAuthentication, IdentityService identityService)
|
||||
|
@ -72,11 +73,11 @@ public class JaspiAuthenticator implements Authenticator
|
|||
this._serviceSubject = serviceSubject;
|
||||
this._allowLazyAuthentication = allowLazyAuthentication;
|
||||
this._identityService = identityService;
|
||||
this._deferred = new DeferredAuthentication(this);
|
||||
}
|
||||
|
||||
public void setConfiguration(AuthConfiguration configuration)
|
||||
{
|
||||
super.setConfiguration(configuration);
|
||||
}
|
||||
|
||||
public String getAuthMethod()
|
||||
|
@ -93,7 +94,7 @@ public class JaspiAuthenticator implements Authenticator
|
|||
|
||||
//if its not mandatory to authenticate, and the authenticator returned UNAUTHENTICATED, we treat it as authentication deferred
|
||||
if (_allowLazyAuthentication && !info.isAuthMandatory() && a == Authentication.UNAUTHENTICATED)
|
||||
a =_deferred;
|
||||
a = new DeferredAuthentication(this);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
@ -251,7 +252,7 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
|
|||
//no override mbean object name, so make a generic one
|
||||
if (oname == null)
|
||||
{
|
||||
String type = obj.getClass().getName().toLowerCase();
|
||||
String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH);
|
||||
int dot = type.lastIndexOf('.');
|
||||
if (dot >= 0)
|
||||
type = type.substring(dot + 1);
|
||||
|
|
|
@ -564,7 +564,7 @@ public class ObjectMBean implements DynamicMBean
|
|||
}
|
||||
|
||||
|
||||
String uName = name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
String uName = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1);
|
||||
Class oClass = onMBean ? this.getClass() : _managed.getClass();
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -99,74 +99,41 @@ public class ContextFactory implements ObjectFactory
|
|||
return ctx;
|
||||
}
|
||||
|
||||
// Next, see if we are in a webapp context, if we are, use
|
||||
// the classloader of the webapp to find the right jndi comp context
|
||||
ClassLoader loader = null;
|
||||
if (ContextHandler.getCurrentContext() != null)
|
||||
|
||||
loader = Thread.currentThread().getContextClassLoader();
|
||||
if (__log.isDebugEnabled() && loader != null) __log.debug("Using thread context classloader");
|
||||
|
||||
if (loader == null && ContextHandler.getCurrentContext() != null)
|
||||
{
|
||||
loader = ContextHandler.getCurrentContext().getContextHandler().getClassLoader();
|
||||
if (__log.isDebugEnabled() && loader != null) __log.debug("Using classloader of current org.eclipse.jetty.server.handler.ContextHandler");
|
||||
}
|
||||
|
||||
|
||||
if (loader != null)
|
||||
{
|
||||
if (__log.isDebugEnabled()) __log.debug("Using classloader of current org.eclipse.jetty.server.handler.ContextHandler");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Not already in a webapp context, in that case, we try the
|
||||
//curren't thread's classloader instead
|
||||
loader = Thread.currentThread().getContextClassLoader();
|
||||
if (__log.isDebugEnabled()) __log.debug("Using thread context classloader");
|
||||
}
|
||||
|
||||
|
||||
//Get the context matching the classloader
|
||||
ctx = (Context)__contextMap.get(loader);
|
||||
|
||||
|
||||
//The map does not contain an entry for this classloader
|
||||
if (ctx == null)
|
||||
{
|
||||
//Check if a parent classloader has created the context
|
||||
ctx = getParentClassLoaderContext(loader);
|
||||
//Didn't find a context to match, make one
|
||||
Reference ref = (Reference)obj;
|
||||
StringRefAddr parserAddr = (StringRefAddr)ref.get("parser");
|
||||
String parserClassName = (parserAddr==null?null:(String)parserAddr.getContent());
|
||||
NameParser parser = (NameParser)(parserClassName==null?null:loader.loadClass(parserClassName).newInstance());
|
||||
|
||||
//Didn't find a context to match any of the ancestors
|
||||
//of the classloader, so make a context
|
||||
if (ctx == null)
|
||||
{
|
||||
Reference ref = (Reference)obj;
|
||||
StringRefAddr parserAddr = (StringRefAddr)ref.get("parser");
|
||||
String parserClassName = (parserAddr==null?null:(String)parserAddr.getContent());
|
||||
NameParser parser = (NameParser)(parserClassName==null?null:loader.loadClass(parserClassName).newInstance());
|
||||
|
||||
ctx = new NamingContext (env,
|
||||
name.get(0),
|
||||
(NamingContext)nameCtx,
|
||||
parser);
|
||||
if(__log.isDebugEnabled())__log.debug("No entry for classloader: "+loader);
|
||||
__contextMap.put (loader, ctx);
|
||||
}
|
||||
ctx = new NamingContext (env,
|
||||
name.get(0),
|
||||
(NamingContext)nameCtx,
|
||||
parser);
|
||||
if(__log.isDebugEnabled())__log.debug("Made context "+name.get(0)+" for classloader: "+loader);
|
||||
__contextMap.put (loader, ctx);
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep trying ancestors of the given classloader to find one to which
|
||||
* the context is bound.
|
||||
* @param loader
|
||||
* @return the context from the parent class loader
|
||||
*/
|
||||
public Context getParentClassLoaderContext (ClassLoader loader)
|
||||
{
|
||||
Context ctx = null;
|
||||
ClassLoader cl = loader;
|
||||
for (cl = cl.getParent(); (cl != null) && (ctx == null); cl = cl.getParent())
|
||||
{
|
||||
ctx = (Context)__contextMap.get(cl);
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,7 @@ import javax.naming.Reference;
|
|||
import javax.naming.StringRefAddr;
|
||||
import javax.naming.spi.ObjectFactory;
|
||||
|
||||
import org.eclipse.jetty.jndi.ContextFactory;
|
||||
import org.eclipse.jetty.jndi.NamingContext;
|
||||
import org.eclipse.jetty.jndi.NamingUtil;
|
||||
import org.eclipse.jetty.jndi.local.localContextRoot;
|
||||
|
@ -47,7 +48,8 @@ import org.junit.Test;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -74,14 +76,16 @@ public class TestJNDI
|
|||
@Test
|
||||
public void testIt() throws Exception
|
||||
{
|
||||
//set up some classloaders
|
||||
Thread currentThread = Thread.currentThread();
|
||||
ClassLoader currentLoader = currentThread.getContextClassLoader();
|
||||
ClassLoader childLoader1 = new URLClassLoader(new URL[0], currentLoader);
|
||||
ClassLoader childLoader2 = new URLClassLoader(new URL[0], currentLoader);
|
||||
|
||||
try
|
||||
{
|
||||
//set up some classloaders
|
||||
Thread currentThread = Thread.currentThread();
|
||||
ClassLoader currentLoader = currentThread.getContextClassLoader();
|
||||
ClassLoader childLoader1 = new URLClassLoader(new URL[0], currentLoader);
|
||||
ClassLoader childLoader2 = new URLClassLoader(new URL[0], currentLoader);
|
||||
|
||||
//Uncomment to aid with debug
|
||||
/*
|
||||
javaRootURLContext.getRoot().addListener(new NamingContext.Listener()
|
||||
{
|
||||
|
@ -119,7 +123,19 @@ public class TestJNDI
|
|||
InitialContext initCtxA = new InitialContext();
|
||||
initCtxA.bind ("blah", "123");
|
||||
assertEquals ("123", initCtxA.lookup("blah"));
|
||||
|
||||
|
||||
initCtxA.destroySubcontext("blah");
|
||||
try
|
||||
{
|
||||
initCtxA.lookup("blah");
|
||||
fail("context blah was not destroyed");
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
//expected
|
||||
}
|
||||
|
||||
|
||||
InitialContext initCtx = new InitialContext();
|
||||
Context sub0 = (Context)initCtx.lookup("java:");
|
||||
|
||||
|
@ -219,6 +235,7 @@ public class TestJNDI
|
|||
try
|
||||
{
|
||||
initCtx.lookup("java:comp/env/rubbish");
|
||||
fail("env should not exist for this classloader");
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
|
@ -287,18 +304,77 @@ public class TestJNDI
|
|||
{
|
||||
//expected failure to modify immutable context
|
||||
}
|
||||
|
||||
System.err.println("java:"+javaRootURLContext.getRoot().dump());
|
||||
System.err.println("local:"+localContextRoot.getRoot().dump());
|
||||
|
||||
//test what happens when you close an initial context that was used
|
||||
initCtx.close();
|
||||
}
|
||||
finally
|
||||
{
|
||||
//make some effort to clean up
|
||||
InitialContext ic = new InitialContext();
|
||||
Context java = (Context)ic.lookup("java:");
|
||||
java.destroySubcontext("zero");
|
||||
java.destroySubcontext("fee");
|
||||
currentThread.setContextClassLoader(childLoader1);
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
comp.destroySubcontext("env");
|
||||
comp.unbind("crud");
|
||||
comp.unbind("crud2");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParent()
|
||||
throws Exception
|
||||
{
|
||||
//set up some classloaders
|
||||
Thread currentThread = Thread.currentThread();
|
||||
ClassLoader parentLoader = currentThread.getContextClassLoader();
|
||||
ClassLoader childLoader1 = new URLClassLoader(new URL[0], parentLoader);
|
||||
|
||||
try
|
||||
{
|
||||
//Test creating a comp for the parent loader does not leak to child
|
||||
InitialContext initCtx = new InitialContext();
|
||||
Context comp = (Context)initCtx.lookup("java:comp");
|
||||
assertNotNull(comp);
|
||||
|
||||
Context env = (Context)comp.createSubcontext("env");
|
||||
assertNotNull(env);
|
||||
|
||||
env.bind("foo", "aaabbbcccddd");
|
||||
assertEquals("aaabbbcccddd", (String)initCtx.lookup("java:comp/env/foo"));
|
||||
|
||||
//Change to child loader
|
||||
currentThread.setContextClassLoader(childLoader1);
|
||||
comp = (Context)initCtx.lookup("java:comp");
|
||||
|
||||
Context childEnv = (Context)comp.createSubcontext("env");
|
||||
assertNotSame(env, childEnv);
|
||||
|
||||
childEnv.bind("foo", "eeefffggghhh");
|
||||
assertEquals("eeefffggghhh", (String)initCtx.lookup("java:comp/env/foo"));
|
||||
|
||||
//Change back to parent
|
||||
currentThread.setContextClassLoader(parentLoader);
|
||||
assertEquals("aaabbbcccddd", (String)initCtx.lookup("java:comp/env/foo"));
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
//make some effort to clean up
|
||||
InitialContext ic = new InitialContext();
|
||||
currentThread.setContextClassLoader(parentLoader);
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
comp.destroySubcontext("env");
|
||||
|
||||
currentThread.setContextClassLoader(childLoader1);
|
||||
comp = (Context)ic.lookup("java:comp");
|
||||
comp.destroySubcontext("env");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
BasicDBObject invalidQuery = new BasicDBObject();
|
||||
|
||||
invalidQuery.put(MongoSessionManager.__ACCESSED, new BasicDBObject("$lt",System.currentTimeMillis() - _purgeInvalidAge));
|
||||
invalidQuery.put(MongoSessionManager.__VALID, __valid_false);
|
||||
invalidQuery.put(MongoSessionManager.__VALID, false);
|
||||
|
||||
DBCursor oldSessions = _sessions.find(invalidQuery, new BasicDBObject(MongoSessionManager.__ID, 1));
|
||||
|
||||
|
@ -234,9 +234,9 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
BasicDBObject validQuery = new BasicDBObject();
|
||||
|
||||
validQuery.put(MongoSessionManager.__ACCESSED,new BasicDBObject("$lt",System.currentTimeMillis() - _purgeValidAge));
|
||||
validQuery.put(MongoSessionManager.__VALID, __valid_false);
|
||||
validQuery.put(MongoSessionManager.__VALID, true);
|
||||
|
||||
oldSessions = _sessions.find(invalidQuery,new BasicDBObject(MongoSessionManager.__ID,1));
|
||||
oldSessions = _sessions.find(validQuery,new BasicDBObject(MongoSessionManager.__ID,1));
|
||||
|
||||
for (DBObject session : oldSessions)
|
||||
{
|
||||
|
@ -410,7 +410,8 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
purge();
|
||||
}
|
||||
};
|
||||
_purgeTimer.schedule(_purgeTask,_purgeDelay);
|
||||
|
||||
_purgeTimer.schedule(_purgeTask,0,_purgeDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.plus.annotation;
|
|||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
|
@ -141,7 +142,7 @@ public class Injection
|
|||
_resourceClass = resourceType;
|
||||
|
||||
//first look for a javabeans style setter matching the targetName
|
||||
String setter = "set"+target.substring(0,1).toUpperCase()+target.substring(1);
|
||||
String setter = "set"+target.substring(0,1).toUpperCase(Locale.ENGLISH)+target.substring(1);
|
||||
try
|
||||
{
|
||||
LOG.debug("Looking for method for setter: "+setter+" with arg "+_resourceClass);
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
|
@ -653,12 +654,12 @@ public class LdapLoginModule extends AbstractLoginModule
|
|||
|
||||
public static String convertCredentialJettyToLdap(String encryptedPassword)
|
||||
{
|
||||
if ("MD5:".startsWith(encryptedPassword.toUpperCase()))
|
||||
if ("MD5:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "{MD5}" + encryptedPassword.substring("MD5:".length(), encryptedPassword.length());
|
||||
}
|
||||
|
||||
if ("CRYPT:".startsWith(encryptedPassword.toUpperCase()))
|
||||
if ("CRYPT:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "{CRYPT}" + encryptedPassword.substring("CRYPT:".length(), encryptedPassword.length());
|
||||
}
|
||||
|
@ -673,12 +674,12 @@ public class LdapLoginModule extends AbstractLoginModule
|
|||
return encryptedPassword;
|
||||
}
|
||||
|
||||
if ("{MD5}".startsWith(encryptedPassword.toUpperCase()))
|
||||
if ("{MD5}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "MD5:" + encryptedPassword.substring("{MD5}".length(), encryptedPassword.length());
|
||||
}
|
||||
|
||||
if ("{CRYPT}".startsWith(encryptedPassword.toUpperCase()))
|
||||
if ("{CRYPT}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "CRYPT:" + encryptedPassword.substring("{CRYPT}".length(), encryptedPassword.length());
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
|
@ -414,7 +415,7 @@ public class DataSourceLoginService extends MappedLoginService
|
|||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
//check if tables exist
|
||||
String tableName = (metaData.storesLowerCaseIdentifiers()? _userTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_userTableName.toUpperCase(): _userTableName));
|
||||
String tableName = (metaData.storesLowerCaseIdentifiers()? _userTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_userTableName.toUpperCase(Locale.ENGLISH): _userTableName));
|
||||
ResultSet result = metaData.getTables(null, null, tableName, null);
|
||||
if (!result.next())
|
||||
{
|
||||
|
@ -432,7 +433,7 @@ public class DataSourceLoginService extends MappedLoginService
|
|||
|
||||
result.close();
|
||||
|
||||
tableName = (metaData.storesLowerCaseIdentifiers()? _roleTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_roleTableName.toUpperCase(): _roleTableName));
|
||||
tableName = (metaData.storesLowerCaseIdentifiers()? _roleTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_roleTableName.toUpperCase(Locale.ENGLISH): _roleTableName));
|
||||
result = metaData.getTables(null, null, tableName, null);
|
||||
if (!result.next())
|
||||
{
|
||||
|
@ -449,7 +450,7 @@ public class DataSourceLoginService extends MappedLoginService
|
|||
|
||||
result.close();
|
||||
|
||||
tableName = (metaData.storesLowerCaseIdentifiers()? _userRoleTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_userRoleTableName.toUpperCase(): _userRoleTableName));
|
||||
tableName = (metaData.storesLowerCaseIdentifiers()? _userRoleTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_userRoleTableName.toUpperCase(Locale.ENGLISH): _userRoleTableName));
|
||||
result = metaData.getTables(null, null, tableName, null);
|
||||
if (!result.next())
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.io.OutputStream;
|
|||
import java.net.MalformedURLException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -229,7 +230,7 @@ public class ProxyRule extends PatternRule
|
|||
@Override
|
||||
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
String s = name.toString().toLowerCase();
|
||||
String s = name.toString().toLowerCase(Locale.ENGLISH);
|
||||
if (!_DontProxyHeaders.contains(s) || (HttpHeaders.CONNECTION_BUFFER.equals(name) && HttpHeaderValues.CLOSE_BUFFER.equals(value)))
|
||||
{
|
||||
if (debug != 0)
|
||||
|
@ -348,7 +349,7 @@ public class ProxyRule extends PatternRule
|
|||
String connectionHdr = request.getHeader("Connection");
|
||||
if (connectionHdr != null)
|
||||
{
|
||||
connectionHdr = connectionHdr.toLowerCase();
|
||||
connectionHdr = connectionHdr.toLowerCase(Locale.ENGLISH);
|
||||
if (connectionHdr.indexOf("keep-alive") < 0 && connectionHdr.indexOf("close") < 0)
|
||||
{
|
||||
connectionHdr = null;
|
||||
|
|
|
@ -77,6 +77,20 @@ public class RewriteHandlerTest extends AbstractRuleTestCase
|
|||
@Test
|
||||
public void test() throws Exception
|
||||
{
|
||||
_response.setStatus(200);
|
||||
_request.setHandled(false);
|
||||
_handler.setOriginalPathAttribute("/before");
|
||||
_handler.setRewriteRequestURI(true);
|
||||
_handler.setRewritePathInfo(true);
|
||||
_request.setRequestURI("/xxx/bar");
|
||||
_request.setPathInfo("/xxx/bar");
|
||||
_handler.handle("/xxx/bar",_request,_request, _response);
|
||||
assertEquals(201,_response.getStatus());
|
||||
assertEquals("/bar/zzz",_request.getAttribute("target"));
|
||||
assertEquals("/bar/zzz",_request.getAttribute("URI"));
|
||||
assertEquals("/bar/zzz",_request.getAttribute("info"));
|
||||
assertEquals(null,_request.getAttribute("before"));
|
||||
|
||||
_response.setStatus(200);
|
||||
_request.setHandled(false);
|
||||
_handler.setOriginalPathAttribute("/before");
|
||||
|
|
|
@ -525,8 +525,6 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
else if (authentication instanceof Authentication.Deferred)
|
||||
{
|
||||
DeferredAuthentication deferred= (DeferredAuthentication)authentication;
|
||||
deferred.setIdentityService(_identityService);
|
||||
deferred.setLoginService(_loginService);
|
||||
baseRequest.setAuthentication(authentication);
|
||||
|
||||
try
|
||||
|
@ -536,7 +534,6 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
finally
|
||||
{
|
||||
previousIdentity = deferred.getPreviousAssociation();
|
||||
deferred.setIdentityService(null);
|
||||
}
|
||||
|
||||
if (authenticator!=null)
|
||||
|
|
|
@ -67,8 +67,8 @@ public class BasicAuthenticator extends LoginAuthenticator
|
|||
try
|
||||
{
|
||||
if (!mandatory)
|
||||
return _deferred;
|
||||
|
||||
return new DeferredAuthentication(this);
|
||||
|
||||
if (credentials != null)
|
||||
{
|
||||
int space=credentials.indexOf(' ');
|
||||
|
@ -96,7 +96,7 @@ public class BasicAuthenticator extends LoginAuthenticator
|
|||
}
|
||||
}
|
||||
|
||||
if (_deferred.isDeferred(response))
|
||||
if (DeferredAuthentication.isDeferred(response))
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
|
||||
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "basic realm=\"" + _loginService.getName() + '"');
|
||||
|
|
|
@ -88,8 +88,8 @@ public class ClientCertAuthenticator extends LoginAuthenticator
|
|||
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
|
||||
{
|
||||
if (!mandatory)
|
||||
return _deferred;
|
||||
|
||||
return new DeferredAuthentication(this);
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest)req;
|
||||
HttpServletResponse response = (HttpServletResponse)res;
|
||||
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
|
||||
|
@ -129,8 +129,8 @@ public class ClientCertAuthenticator extends LoginAuthenticator
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_deferred.isDeferred(response))
|
||||
|
||||
if (!DeferredAuthentication.isDeferred(response))
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
return Authentication.SEND_FAILURE;
|
||||
|
|
|
@ -43,22 +43,9 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class DeferredAuthentication implements Authentication.Deferred
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(DeferredAuthentication.class);
|
||||
|
||||
protected final Authenticator _authenticator;
|
||||
|
||||
private LoginService _loginService;
|
||||
private IdentityService _identityService;
|
||||
protected final LoginAuthenticator _authenticator;
|
||||
private Object _previousAssociation;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public DeferredAuthentication(Authenticator authenticator)
|
||||
{
|
||||
if (authenticator == null)
|
||||
throw new NullPointerException("No Authenticator");
|
||||
this._authenticator = authenticator;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public DeferredAuthentication(LoginAuthenticator authenticator)
|
||||
{
|
||||
|
@ -66,36 +53,6 @@ public class DeferredAuthentication implements Authentication.Deferred
|
|||
throw new NullPointerException("No Authenticator");
|
||||
this._authenticator = authenticator;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the identityService.
|
||||
* @return the identityService
|
||||
*/
|
||||
public IdentityService getIdentityService()
|
||||
{
|
||||
return _identityService;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the identityService.
|
||||
* @param identityService the identityService to set
|
||||
*/
|
||||
public void setIdentityService(IdentityService identityService)
|
||||
{
|
||||
_identityService = identityService;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public LoginService getLoginService()
|
||||
{
|
||||
return _loginService;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setLoginService(LoginService loginService)
|
||||
{
|
||||
_loginService = loginService;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -109,8 +66,11 @@ public class DeferredAuthentication implements Authentication.Deferred
|
|||
|
||||
if (authentication!=null && (authentication instanceof Authentication.User) && !(authentication instanceof Authentication.ResponseSent))
|
||||
{
|
||||
if (_identityService!=null)
|
||||
_previousAssociation=_identityService.associate(((Authentication.User)authentication).getUserIdentity());
|
||||
LoginService login_service= _authenticator.getLoginService();
|
||||
IdentityService identity_service=login_service.getIdentityService();
|
||||
|
||||
if (identity_service!=null)
|
||||
_previousAssociation=identity_service.associate(((Authentication.User)authentication).getUserIdentity());
|
||||
return authentication;
|
||||
}
|
||||
}
|
||||
|
@ -129,9 +89,12 @@ public class DeferredAuthentication implements Authentication.Deferred
|
|||
{
|
||||
try
|
||||
{
|
||||
LoginService login_service= _authenticator.getLoginService();
|
||||
IdentityService identity_service=login_service.getIdentityService();
|
||||
|
||||
Authentication authentication = _authenticator.validateRequest(request,response,true);
|
||||
if (authentication instanceof Authentication.User && _identityService!=null)
|
||||
_previousAssociation=_identityService.associate(((Authentication.User)authentication).getUserIdentity());
|
||||
if (authentication instanceof Authentication.User && identity_service!=null)
|
||||
_previousAssociation=identity_service.associate(((Authentication.User)authentication).getUserIdentity());
|
||||
return authentication;
|
||||
}
|
||||
catch (ServerAuthException e)
|
||||
|
@ -147,14 +110,17 @@ public class DeferredAuthentication implements Authentication.Deferred
|
|||
*/
|
||||
public Authentication login(String username, String password)
|
||||
{
|
||||
if (_loginService!=null)
|
||||
LoginService login_service= _authenticator.getLoginService();
|
||||
IdentityService identity_service=login_service.getIdentityService();
|
||||
|
||||
if (login_service!=null)
|
||||
{
|
||||
UserIdentity user = _loginService.login(username,password);
|
||||
UserIdentity user = login_service.login(username,password);
|
||||
if (user!=null)
|
||||
{
|
||||
UserAuthentication authentication = new UserAuthentication("API",user);
|
||||
if (_identityService!=null)
|
||||
_previousAssociation=_identityService.associate(user);
|
||||
if (identity_service!=null)
|
||||
_previousAssociation=identity_service.associate(user);
|
||||
return authentication;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,8 +121,8 @@ public class DigestAuthenticator extends LoginAuthenticator
|
|||
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
|
||||
{
|
||||
if (!mandatory)
|
||||
return _deferred;
|
||||
|
||||
return new DeferredAuthentication(this);
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest)req;
|
||||
HttpServletResponse response = (HttpServletResponse)res;
|
||||
String credentials = request.getHeader(HttpHeaders.AUTHORIZATION);
|
||||
|
@ -197,7 +197,7 @@ public class DigestAuthenticator extends LoginAuthenticator
|
|||
|
||||
}
|
||||
|
||||
if (!_deferred.isDeferred(response))
|
||||
if (!DeferredAuthentication.isDeferred(response))
|
||||
{
|
||||
String domain = request.getContextPath();
|
||||
if (domain == null)
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.security.authentication;
|
|||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -191,11 +192,11 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
|
||||
mandatory|=isJSecurityCheck(uri);
|
||||
if (!mandatory)
|
||||
return _deferred;
|
||||
|
||||
return new DeferredAuthentication(this);
|
||||
|
||||
if (isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo())) &&!DeferredAuthentication.isDeferred(response))
|
||||
return _deferred;
|
||||
|
||||
return new DeferredAuthentication(this);
|
||||
|
||||
HttpSession session = request.getSession(true);
|
||||
|
||||
try
|
||||
|
@ -300,9 +301,12 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
}
|
||||
|
||||
// if we can't send challenge
|
||||
if (_deferred.isDeferred(response))
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
|
||||
if (DeferredAuthentication.isDeferred(response))
|
||||
{
|
||||
LOG.debug("auth deferred {}",session.getId());
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
}
|
||||
|
||||
// remember the current URI
|
||||
synchronized (session)
|
||||
{
|
||||
|
@ -387,7 +391,7 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
@Override
|
||||
public long getDateHeader(String name)
|
||||
{
|
||||
if (name.toLowerCase().startsWith("if-"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return -1;
|
||||
return super.getDateHeader(name);
|
||||
}
|
||||
|
@ -395,7 +399,7 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
@Override
|
||||
public String getHeader(String name)
|
||||
{
|
||||
if (name.toLowerCase().startsWith("if-"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return null;
|
||||
return super.getHeader(name);
|
||||
}
|
||||
|
@ -409,7 +413,7 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
@Override
|
||||
public Enumeration getHeaders(String name)
|
||||
{
|
||||
if (name.toLowerCase().startsWith("if-"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return Collections.enumeration(Collections.EMPTY_LIST);
|
||||
return super.getHeaders(name);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.eclipse.jetty.server.session.AbstractSessionManager;
|
|||
|
||||
public abstract class LoginAuthenticator implements Authenticator
|
||||
{
|
||||
protected final DeferredAuthentication _deferred=new DeferredAuthentication(this);
|
||||
protected LoginService _loginService;
|
||||
protected IdentityService _identityService;
|
||||
private boolean _renewSession;
|
||||
|
|
|
@ -69,7 +69,7 @@ public class SpnegoAuthenticator extends LoginAuthenticator
|
|||
|
||||
if (!mandatory)
|
||||
{
|
||||
return _deferred;
|
||||
return new DeferredAuthentication(this);
|
||||
}
|
||||
|
||||
// check to see if we have authorization headers required to continue
|
||||
|
@ -77,7 +77,7 @@ public class SpnegoAuthenticator extends LoginAuthenticator
|
|||
{
|
||||
try
|
||||
{
|
||||
if (_deferred.isDeferred(res))
|
||||
if (DeferredAuthentication.isDeferred(res))
|
||||
{
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
|
@ -286,7 +288,7 @@ public class CookieCutter
|
|||
{
|
||||
if (name.startsWith("$"))
|
||||
{
|
||||
String lowercaseName = name.toLowerCase();
|
||||
String lowercaseName = name.toLowerCase(Locale.ENGLISH);
|
||||
if ("$path".equals(lowercaseName))
|
||||
{
|
||||
if (cookie!=null)
|
||||
|
|
|
@ -1739,6 +1739,7 @@ public class Request implements HttpServletRequest
|
|||
public void setQueryString(String queryString)
|
||||
{
|
||||
_queryString = queryString;
|
||||
_queryEncoding = null; //assume utf-8
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -1922,7 +1923,7 @@ public class Request implements HttpServletRequest
|
|||
{
|
||||
// extract parameters from dispatch query
|
||||
MultiMap<String> parameters = new MultiMap<String>();
|
||||
UrlEncoded.decodeTo(query,parameters,getCharacterEncoding());
|
||||
UrlEncoded.decodeTo(query,parameters, StringUtil.__UTF8); //have to assume UTF-8 because we can't know otherwise
|
||||
|
||||
boolean merge_old_query = false;
|
||||
|
||||
|
@ -1957,10 +1958,11 @@ public class Request implements HttpServletRequest
|
|||
{
|
||||
StringBuilder overridden_query_string = new StringBuilder();
|
||||
MultiMap<String> overridden_old_query = new MultiMap<String>();
|
||||
UrlEncoded.decodeTo(_queryString,overridden_old_query,getCharacterEncoding());
|
||||
|
||||
UrlEncoded.decodeTo(_queryString,overridden_old_query,getQueryEncoding());//decode using any queryencoding set for the request
|
||||
|
||||
|
||||
MultiMap<String> overridden_new_query = new MultiMap<String>();
|
||||
UrlEncoded.decodeTo(query,overridden_new_query,getCharacterEncoding());
|
||||
UrlEncoded.decodeTo(query,overridden_new_query,StringUtil.__UTF8); //have to assume utf8 as we cannot know otherwise
|
||||
|
||||
Iterator<Entry<String, Object>> iter = overridden_old_query.entrySet().iterator();
|
||||
while (iter.hasNext())
|
||||
|
|
|
@ -386,7 +386,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
baseRequest.setRequestURI(null);
|
||||
baseRequest.setPathInfo(baseRequest.getRequestURI());
|
||||
if (uri.getQuery()!=null)
|
||||
baseRequest.mergeQueryString(uri.getQuery());
|
||||
baseRequest.mergeQueryString(uri.getQuery()); //we have to assume dispatch path and query are UTF8
|
||||
}
|
||||
|
||||
final String target=baseRequest.getPathInfo();
|
||||
|
|
|
@ -50,7 +50,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
<pre>
|
||||
public static void attemptShutdown(int port, String shutdownCookie) {
|
||||
try {
|
||||
URL url = new URL("http://localhost:" + port + "/shutdown?cookie=" + shutdownCookie);
|
||||
URL url = new URL("http://localhost:" + port + "/shutdown?token=" + shutdownCookie);
|
||||
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.getResponseCode();
|
||||
|
|
|
@ -65,8 +65,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
|
|||
private boolean _newSession;
|
||||
private int _requests;
|
||||
|
||||
// TODO remove this.
|
||||
protected final Map<String,Object> _jdbcAttributes=_attributes;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected AbstractSession(AbstractSessionManager abstractSessionManager, HttpServletRequest request)
|
||||
|
@ -255,6 +254,18 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
|
|||
return (String[])_attributes.keySet().toArray(a);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected Map<String,Object> getAttributeMap ()
|
||||
{
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void addAttributes(Map<String,Object> map)
|
||||
{
|
||||
_attributes.putAll(map);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected boolean access(long time)
|
||||
|
|
|
@ -482,32 +482,40 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
protected synchronized HashedSession restoreSession(String idInCuster)
|
||||
{
|
||||
File file = new File(_storeDir,idInCuster);
|
||||
FileInputStream in = null;
|
||||
Exception error = null;
|
||||
try
|
||||
{
|
||||
if (file.exists())
|
||||
{
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
in = new FileInputStream(file);
|
||||
HashedSession session = restoreSession(in, null);
|
||||
in.close();
|
||||
addSession(session, false);
|
||||
session.didActivate();
|
||||
file.delete();
|
||||
return session;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
if (isDeleteUnrestorableSessions())
|
||||
error = e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (in != null)
|
||||
try {in.close();} catch (Exception x) {__log.ignore(x);}
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
if (file.exists())
|
||||
if (isDeleteUnrestorableSessions() && file.exists())
|
||||
{
|
||||
file.delete();
|
||||
__log.warn("Deleting file for unrestorable session "+idInCuster, e);
|
||||
__log.warn("Deleting file for unrestorable session "+idInCuster, error);
|
||||
}
|
||||
else
|
||||
__log.warn("Problem restoring session "+idInCuster, error);
|
||||
}
|
||||
else
|
||||
__log.warn("Problem restoring session "+idInCuster, e);
|
||||
file.delete(); //delete successfully restored file
|
||||
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -30,8 +30,11 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
@ -81,7 +84,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
protected String _createSessionIdTable;
|
||||
protected String _createSessionTable;
|
||||
|
||||
protected String _selectExpiredSessions;
|
||||
protected String _selectBoundedExpiredSessions;
|
||||
protected String _deleteOldExpiredSessions;
|
||||
|
||||
protected String _insertId;
|
||||
|
@ -96,6 +99,8 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
|
||||
protected DatabaseAdaptor _dbAdaptor;
|
||||
|
||||
private String _selectExpiredSessions;
|
||||
|
||||
|
||||
/**
|
||||
* DatabaseAdaptor
|
||||
|
@ -114,16 +119,16 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
String _dbName;
|
||||
boolean _isLower;
|
||||
boolean _isUpper;
|
||||
|
||||
|
||||
|
||||
|
||||
public DatabaseAdaptor (DatabaseMetaData dbMeta)
|
||||
throws SQLException
|
||||
{
|
||||
_dbName = dbMeta.getDatabaseProductName().toLowerCase();
|
||||
_dbName = dbMeta.getDatabaseProductName().toLowerCase(Locale.ENGLISH);
|
||||
LOG.debug ("Using database {}",_dbName);
|
||||
_isLower = dbMeta.storesLowerCaseIdentifiers();
|
||||
_isUpper = dbMeta.storesUpperCaseIdentifiers();
|
||||
_isUpper = dbMeta.storesUpperCaseIdentifiers();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,9 +141,9 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
public String convertIdentifier (String identifier)
|
||||
{
|
||||
if (_isLower)
|
||||
return identifier.toLowerCase();
|
||||
return identifier.toLowerCase(Locale.ENGLISH);
|
||||
if (_isUpper)
|
||||
return identifier.toUpperCase();
|
||||
return identifier.toUpperCase(Locale.ENGLISH);
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
@ -455,6 +460,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
inUse = _sessionIds.contains(clusterId);
|
||||
}
|
||||
|
||||
|
||||
if (inUse)
|
||||
return true; //optimisation - if this session is one we've been managing, we can check locally
|
||||
|
||||
|
@ -514,7 +520,8 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
try
|
||||
{
|
||||
initializeDatabase();
|
||||
prepareTables();
|
||||
prepareTables();
|
||||
cleanExpiredSessions();
|
||||
super.doStart();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Scavenging interval = "+getScavengeInterval()+" sec");
|
||||
|
@ -542,6 +549,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
_timer.cancel();
|
||||
_timer=null;
|
||||
}
|
||||
_sessionIds.clear();
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
|
@ -559,31 +567,9 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
else
|
||||
return DriverManager.getConnection(_connectionUrl);
|
||||
}
|
||||
|
||||
|
||||
private void initializeDatabase ()
|
||||
throws Exception
|
||||
{
|
||||
if (_datasource != null)
|
||||
return; //already set up
|
||||
|
||||
if (_jndiName!=null)
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
_datasource = (DataSource)ic.lookup(_jndiName);
|
||||
}
|
||||
else if ( _driver != null && _connectionUrl != null )
|
||||
{
|
||||
DriverManager.registerDriver(_driver);
|
||||
}
|
||||
else if (_driverClassName != null && _connectionUrl != null)
|
||||
{
|
||||
Class.forName(_driverClassName);
|
||||
}
|
||||
else
|
||||
throw new IllegalStateException("No database configured for sessions");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -594,7 +580,8 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
throws SQLException
|
||||
{
|
||||
_createSessionIdTable = "create table "+_sessionIdTable+" (id varchar(120), primary key(id))";
|
||||
_selectExpiredSessions = "select * from "+_sessionTable+" where expiryTime >= ? and expiryTime <= ?";
|
||||
_selectBoundedExpiredSessions = "select * from "+_sessionTable+" where expiryTime >= ? and expiryTime <= ?";
|
||||
_selectExpiredSessions = "select * from "+_sessionTable+" where expiryTime >0 and expiryTime <= ?";
|
||||
_deleteOldExpiredSessions = "delete from "+_sessionTable+" where expiryTime >0 and expiryTime <= ?";
|
||||
|
||||
_insertId = "insert into "+_sessionIdTable+" (id) values (?)";
|
||||
|
@ -794,7 +781,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
connection = getConnection();
|
||||
connection.setAutoCommit(true);
|
||||
//"select sessionId from JettySessions where expiryTime > (lastScavengeTime - scanInterval) and expiryTime < lastScavengeTime";
|
||||
PreparedStatement statement = connection.prepareStatement(_selectExpiredSessions);
|
||||
PreparedStatement statement = connection.prepareStatement(_selectBoundedExpiredSessions);
|
||||
long lowerBound = (_lastScavengeTime - _scavengeIntervalMs);
|
||||
long upperBound = _lastScavengeTime;
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -833,7 +820,8 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
if (LOG.isDebugEnabled()) LOG.debug("Deleting old expired sessions expired before "+upperBound);
|
||||
statement = connection.prepareStatement(_deleteOldExpiredSessions);
|
||||
statement.setLong(1, upperBound);
|
||||
statement.executeUpdate();
|
||||
int rows = statement.executeUpdate();
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Deleted "+rows+" rows");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -861,4 +849,121 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rid of sessions and sessionids from sessions that have already expired
|
||||
* @throws Exception
|
||||
*/
|
||||
private void cleanExpiredSessions ()
|
||||
throws Exception
|
||||
{
|
||||
Connection connection = null;
|
||||
List<String> expiredSessionIds = new ArrayList<String>();
|
||||
try
|
||||
{
|
||||
connection = getConnection();
|
||||
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
|
||||
connection.setAutoCommit(false);
|
||||
|
||||
PreparedStatement statement = connection.prepareStatement(_selectExpiredSessions);
|
||||
long now = System.currentTimeMillis();
|
||||
if (LOG.isDebugEnabled()) LOG.debug ("Searching for sessions expired before {}", now);
|
||||
|
||||
statement.setLong(1, now);
|
||||
ResultSet result = statement.executeQuery();
|
||||
while (result.next())
|
||||
{
|
||||
String sessionId = result.getString("sessionId");
|
||||
expiredSessionIds.add(sessionId);
|
||||
if (LOG.isDebugEnabled()) LOG.debug ("Found expired sessionId={}", sessionId);
|
||||
}
|
||||
|
||||
Statement sessionsTableStatement = null;
|
||||
Statement sessionIdsTableStatement = null;
|
||||
|
||||
if (!expiredSessionIds.isEmpty())
|
||||
{
|
||||
sessionsTableStatement = connection.createStatement();
|
||||
sessionsTableStatement.executeUpdate(createCleanExpiredSessionsSql("delete from "+_sessionTable+" where sessionId in ", expiredSessionIds));
|
||||
sessionIdsTableStatement = connection.createStatement();
|
||||
sessionIdsTableStatement.executeUpdate(createCleanExpiredSessionsSql("delete from "+_sessionIdTable+" where id in ", expiredSessionIds));
|
||||
}
|
||||
connection.commit();
|
||||
|
||||
synchronized (_sessionIds)
|
||||
{
|
||||
_sessionIds.removeAll(expiredSessionIds); //in case they were in our local cache of session ids
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (connection != null)
|
||||
connection.rollback();
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (connection != null)
|
||||
connection.close();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sql
|
||||
* @param connection
|
||||
* @param expiredSessionIds
|
||||
* @throws Exception
|
||||
*/
|
||||
private String createCleanExpiredSessionsSql (String sql,Collection<String> expiredSessionIds)
|
||||
throws Exception
|
||||
{
|
||||
StringBuffer buff = new StringBuffer();
|
||||
buff.append(sql);
|
||||
buff.append("(");
|
||||
Iterator<String> itor = expiredSessionIds.iterator();
|
||||
while (itor.hasNext())
|
||||
{
|
||||
buff.append("'"+(itor.next())+"'");
|
||||
if (itor.hasNext())
|
||||
buff.append(",");
|
||||
}
|
||||
buff.append(")");
|
||||
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Cleaning expired sessions with: {}", buff);
|
||||
return buff.toString();
|
||||
}
|
||||
|
||||
private void initializeDatabase ()
|
||||
throws Exception
|
||||
{
|
||||
if (_datasource != null)
|
||||
return; //already set up
|
||||
|
||||
if (_jndiName!=null)
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
_datasource = (DataSource)ic.lookup(_jndiName);
|
||||
}
|
||||
else if ( _driver != null && _connectionUrl != null )
|
||||
{
|
||||
DriverManager.registerDriver(_driver);
|
||||
}
|
||||
else if (_driverClassName != null && _connectionUrl != null)
|
||||
{
|
||||
Class.forName(_driverClassName);
|
||||
}
|
||||
else
|
||||
throw new IllegalStateException("No database configured for sessions");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -265,7 +265,8 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
private static final long serialVersionUID = 5208464051134226143L;
|
||||
private final SessionData _data;
|
||||
private boolean _dirty=false;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Session from a request.
|
||||
*
|
||||
|
@ -274,7 +275,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
protected Session (HttpServletRequest request)
|
||||
{
|
||||
super(JDBCSessionManager.this,request);
|
||||
_data = new SessionData(getClusterId(),_jdbcAttributes);
|
||||
_data = new SessionData(getClusterId(),getAttributeMap());
|
||||
if (_dftMaxIdleSecs>0)
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000L);
|
||||
_data.setCanonicalContext(canonicalize(_context.getContextPath()));
|
||||
|
@ -284,18 +285,18 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
}
|
||||
|
||||
/**
|
||||
* Session restored in database.
|
||||
* @param data
|
||||
*/
|
||||
protected Session (long accessed, SessionData data)
|
||||
{
|
||||
super(JDBCSessionManager.this,data.getCreated(), accessed, data.getId());
|
||||
_data=data;
|
||||
if (_dftMaxIdleSecs>0)
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000L);
|
||||
_jdbcAttributes.putAll(_data.getAttributeMap());
|
||||
_data.setAttributeMap(_jdbcAttributes);
|
||||
}
|
||||
* Session restored in database.
|
||||
* @param data
|
||||
*/
|
||||
protected Session (long accessed, SessionData data)
|
||||
{
|
||||
super(JDBCSessionManager.this,data.getCreated(), accessed, data.getId());
|
||||
_data=data;
|
||||
if (_dftMaxIdleSecs>0)
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000L);
|
||||
addAttributes(_data.getAttributeMap());
|
||||
_data.setAttributeMap(getAttributeMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute (String name, Object value)
|
||||
|
@ -539,7 +540,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
//if the session has no expiry, or it is not already expired
|
||||
if (data._expiryTime <= 0 || data._expiryTime > now)
|
||||
{
|
||||
LOG.debug("getSession("+idInCluster+"): lastNode="+data.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName());
|
||||
if (LOG.isDebugEnabled()) LOG.debug("getSession("+idInCluster+"): lastNode="+data.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName());
|
||||
data.setLastNode(getSessionIdManager().getWorkerName());
|
||||
//session last used on a different node, or we don't have it in memory
|
||||
session = new Session(now,data);
|
||||
|
@ -550,18 +551,21 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
updateSessionNode(data);
|
||||
}
|
||||
else
|
||||
if (LOG.isDebugEnabled()) LOG.debug("getSession("+idInCluster+"): Session has expired");
|
||||
{
|
||||
LOG.debug("getSession ({}): Session has expired", idInCluster);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if (LOG.isDebugEnabled()) LOG.debug("getSession("+idInCluster+"): Session not stale "+session._data);
|
||||
LOG.debug("getSession({}): Session not stale {}", idInCluster,session._data);
|
||||
//session in db shares same id, but is not for this context
|
||||
}
|
||||
else
|
||||
{
|
||||
//No session in db with matching id and context path.
|
||||
session=null;
|
||||
if (LOG.isDebugEnabled()) LOG.debug("getSession("+idInCluster+"): No session in database matching id="+idInCluster);
|
||||
LOG.debug("getSession({}): No session in database matching id={}",idInCluster,idInCluster);
|
||||
}
|
||||
|
||||
return session;
|
||||
|
@ -605,6 +609,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
_jdbcSessionIdMgr = (JDBCSessionIdManager)_sessionIdManager;
|
||||
|
||||
_sessions = new ConcurrentHashMap<String, AbstractSession>();
|
||||
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
@ -26,12 +27,16 @@ import static org.junit.Assert.fail;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.http.EncodedHttpURI;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HttpURITest
|
||||
|
@ -205,6 +210,106 @@ public class HttpURITest
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNoPercentEncodingOfQueryUsingNonUTF8() throws Exception
|
||||
{
|
||||
|
||||
byte[] utf8_bytes = "/%D0%A1%D1%82%D1%80%D0%BE%D0%BD%D0%B3-%D1%84%D0%B8%D0%BB%D1%8C%D1%82%D1%80/%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3?".getBytes("UTF-8");
|
||||
byte[] cp1251_bytes = TypeUtil.fromHexString("e2fbe1f0e0edee3dd2e5ecefe5f0e0f2f3f0e0");
|
||||
String expectedCP1251String = new String(cp1251_bytes, "cp1251");
|
||||
String expectedCP1251Key = new String(cp1251_bytes, 0, 7, "cp1251");
|
||||
String expectedCP1251Value = new String(cp1251_bytes, 8, cp1251_bytes.length-8, "cp1251");
|
||||
|
||||
//paste both byte arrays together to form the uri
|
||||
byte[] allbytes = new byte[utf8_bytes.length+cp1251_bytes.length];
|
||||
int i=0;
|
||||
for (;i<utf8_bytes.length;i++) {
|
||||
allbytes[i] = utf8_bytes[i];
|
||||
}
|
||||
for (int j=0; j< cp1251_bytes.length;j++)
|
||||
allbytes[i+j] = cp1251_bytes[j];
|
||||
|
||||
//Test using a HttpUri that expects a particular charset encoding. See URIUtil.__CHARSET
|
||||
EncodedHttpURI uri = new EncodedHttpURI("cp1251");
|
||||
uri.parse(allbytes, 0, allbytes.length);
|
||||
assertEquals(expectedCP1251String, uri.getQuery("cp1251"));
|
||||
|
||||
//Test params decoded correctly
|
||||
MultiMap params = new MultiMap();
|
||||
uri.decodeQueryTo(params);
|
||||
String val = params.getString(expectedCP1251Key);
|
||||
assertNotNull(val);
|
||||
assertEquals(expectedCP1251Value, val);
|
||||
|
||||
//Test using HttpURI where you pass in the charset encoding.
|
||||
HttpURI httpuri = new HttpURI();
|
||||
httpuri.parse(allbytes,0,allbytes.length);
|
||||
assertNotNull(httpuri.getQuery("UTF-8")); //still get back a query string, just incorrectly encoded
|
||||
assertEquals(expectedCP1251String, httpuri.getQuery("cp1251"));
|
||||
|
||||
//Test params decoded correctly
|
||||
params.clear();
|
||||
httpuri.decodeQueryTo(params, "cp1251");
|
||||
val = params.getString(expectedCP1251Key);
|
||||
assertNotNull(val);
|
||||
assertEquals(expectedCP1251Value, val);
|
||||
|
||||
//test able to set the query encoding and call getQueryString multiple times
|
||||
Request request = new Request();
|
||||
request.setUri(httpuri);
|
||||
request.setAttribute("org.eclipse.jetty.server.Request.queryEncoding", "ISO-8859-1");
|
||||
assertNotNull (request.getQueryString()); //will be incorrect encoding but not null
|
||||
request.setAttribute("org.eclipse.jetty.server.Request.queryEncoding", "cp1251");
|
||||
assertEquals(expectedCP1251String, request.getQueryString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPercentEncodingOfQueryStringUsingNonUTF8() throws UnsupportedEncodingException
|
||||
{
|
||||
|
||||
byte[] utf8_bytes = "/%D0%A1%D1%82%D1%80%D0%BE%D0%BD%D0%B3-%D1%84%D0%B8%D0%BB%D1%8C%D1%82%D1%80/%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3?".getBytes("UTF-8");
|
||||
byte[] cp1251_bytes = "%e2%fb%e1%f0%e0%ed%ee=%d2%e5%ec%ef%e5%f0%e0%f2%f3%f0%e0".getBytes("cp1251");
|
||||
|
||||
byte[] key_bytes = TypeUtil.fromHexString("e2fbe1f0e0edee");
|
||||
byte[] val_bytes = TypeUtil.fromHexString("d2e5ecefe5f0e0f2f3f0e0");
|
||||
String expectedCP1251String = new String(cp1251_bytes, "cp1251");
|
||||
String expectedCP1251Key = new String(key_bytes, "cp1251");
|
||||
String expectedCP1251Value = new String(val_bytes, "cp1251");
|
||||
|
||||
byte[] allbytes = new byte[utf8_bytes.length+cp1251_bytes.length];
|
||||
|
||||
//stick both arrays together to form uri
|
||||
int i=0;
|
||||
for (;i<utf8_bytes.length;i++) {
|
||||
allbytes[i] = utf8_bytes[i];
|
||||
}
|
||||
for (int j=0; j< cp1251_bytes.length;j++)
|
||||
allbytes[i+j] = cp1251_bytes[j];
|
||||
|
||||
|
||||
HttpURI httpuri = new HttpURI();
|
||||
httpuri.parse(allbytes,0,allbytes.length);
|
||||
assertNotNull(httpuri.getQuery("UTF-8")); //will be incorrectly encoded, but no errors
|
||||
assertEquals(expectedCP1251String, httpuri.getQuery("cp1251"));
|
||||
|
||||
//test params decoded correctly
|
||||
MultiMap params = new MultiMap();
|
||||
httpuri.decodeQueryTo(params, "cp1251");
|
||||
String val = params.getString(expectedCP1251Key);
|
||||
assertNotNull(val);
|
||||
assertEquals(expectedCP1251Value, val);
|
||||
|
||||
//test able to set the query encoding and call getQueryString multiple times
|
||||
Request request = new Request();
|
||||
request.setUri(httpuri);
|
||||
request.setAttribute("org.eclipse.jetty.server.Request.queryEncoding", "ISO-8859-1");
|
||||
assertNotNull (request.getQueryString()); //will be incorrect encoding but not null
|
||||
request.setAttribute("org.eclipse.jetty.server.Request.queryEncoding", "cp1251");
|
||||
assertEquals(expectedCP1251String, request.getQueryString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnicodeErrors() throws UnsupportedEncodingException
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Socket;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
|
@ -54,7 +55,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setResumeAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("RESUMED"));
|
||||
assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("RESUMED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -68,7 +69,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
_server.start();
|
||||
|
||||
_handler.setSuspendFor(50);
|
||||
assertTrue(process(null).toUpperCase().contains("TIMEOUT"));
|
||||
assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("TIMEOUT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -83,7 +84,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setCompleteAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("COMPLETED"));
|
||||
assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("COMPLETED"));
|
||||
}
|
||||
|
||||
private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.io.IOException;
|
|||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -104,7 +105,7 @@ public abstract class AbstractConnectHandlerTest
|
|||
assertTrue(header.lookingAt());
|
||||
String headerName = header.group(1);
|
||||
String headerValue = header.group(2);
|
||||
headers.put(headerName.toLowerCase(), headerValue.toLowerCase());
|
||||
headers.put(headerName.toLowerCase(Locale.ENGLISH), headerValue.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
StringBuilder body;
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.net.Socket;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -152,7 +153,7 @@ public class IPAccessHandlerTest
|
|||
assertTrue(header.lookingAt());
|
||||
String headerName = header.group(1);
|
||||
String headerValue = header.group(2);
|
||||
headers.put(headerName.toLowerCase(), headerValue.toLowerCase());
|
||||
headers.put(headerName.toLowerCase(Locale.ENGLISH), headerValue.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
StringBuilder body = new StringBuilder();
|
||||
|
|
|
@ -50,6 +50,7 @@ public class ErrorPageErrorHandler extends ErrorHandler
|
|||
private static final Logger LOG = Log.getLogger(ErrorPageErrorHandler.class);
|
||||
|
||||
public final static String ERROR_PAGE="org.eclipse.jetty.server.error_page";
|
||||
public final static String GLOBAL_ERROR_PAGE = "org.eclipse.jetty.server.error_page.global";
|
||||
|
||||
protected ServletContext _servletContext;
|
||||
private final Map<String,String> _errorPages= new HashMap<String,String>(); // code or exception to URL
|
||||
|
@ -120,6 +121,12 @@ public class ErrorPageErrorHandler extends ErrorHandler
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//try new servlet 3.0 global error page
|
||||
if (error_page == null)
|
||||
{
|
||||
error_page = _errorPages.get(GLOBAL_ERROR_PAGE);
|
||||
}
|
||||
|
||||
if (error_page!=null)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.servlet;
|
|||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -91,7 +92,7 @@ public class Invoker extends HttpServlet
|
|||
{
|
||||
String param=(String)e.nextElement();
|
||||
String value=getInitParameter(param);
|
||||
String lvalue=value.toLowerCase();
|
||||
String lvalue=value.toLowerCase(Locale.ENGLISH);
|
||||
if ("nonContextServlets".equals(param))
|
||||
{
|
||||
_nonContextServlets=value.length()>0 && lvalue.startsWith("t");
|
||||
|
|
|
@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue;
|
|||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
@ -53,6 +54,7 @@ import org.eclipse.jetty.server.handler.ContextHandler;
|
|||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.ResourceHandler;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -111,6 +113,23 @@ public class DispatcherTest
|
|||
assertEquals(expected, responses);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test public void testForwardNonUTF8() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(ForwardNonUTF8Servlet.class, "/ForwardServlet/*");
|
||||
_contextHandler.addServlet(AssertNonUTF8ForwardServlet.class, "/AssertForwardServlet/*");
|
||||
|
||||
String expected=
|
||||
"HTTP/1.1 200 OK\r\n"+
|
||||
"Content-Type: text/html\r\n"+
|
||||
"Content-Length: 0\r\n"+
|
||||
"\r\n";
|
||||
String responses = _connector.getResponses("GET /context/ForwardServlet?do=assertforward&foreign=%d2%e5%ec%ef%e5%f0%e0%f2%f3%f0%e0&test=1 HTTP/1.1\n" + "Host: localhost\n\n");
|
||||
|
||||
assertEquals(expected, responses);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForwardWithParam() throws Exception
|
||||
{
|
||||
|
@ -303,6 +322,7 @@ public class DispatcherTest
|
|||
dispatcher = getServletContext().getRequestDispatcher("/IncludeServlet/includepath?do=assertforwardinclude");
|
||||
else if(request.getParameter("do").equals("assertincludeforward"))
|
||||
dispatcher = getServletContext().getRequestDispatcher("/AssertIncludeForwardServlet/assertpath?do=end");
|
||||
|
||||
else if(request.getParameter("do").equals("assertforward"))
|
||||
dispatcher = getServletContext().getRequestDispatcher("/AssertForwardServlet?do=end&do=the");
|
||||
else if(request.getParameter("do").equals("ctx.echo"))
|
||||
|
@ -313,6 +333,18 @@ public class DispatcherTest
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ForwardNonUTF8Servlet extends HttpServlet implements Servlet
|
||||
{
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
RequestDispatcher dispatcher = null;
|
||||
request.setAttribute("org.eclipse.jetty.server.Request.queryEncoding", "cp1251");
|
||||
dispatcher = getServletContext().getRequestDispatcher("/AssertForwardServlet?do=end&else=%D0%B2%D1%8B%D0%B1%D1%80%D0%B0%D0%BD%D0%BE%3D%D0%A2%D0%B5%D0%BC%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D1%83%D1%80%D0%B0");
|
||||
dispatcher.forward(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Forward filter works with roger, echo and reverse echo servlets to test various
|
||||
* forwarding bits using filters.
|
||||
|
@ -531,6 +563,45 @@ public class DispatcherTest
|
|||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class AssertNonUTF8ForwardServlet extends HttpServlet implements Servlet
|
||||
{
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
byte[] cp1251_bytes = TypeUtil.fromHexString("d2e5ecefe5f0e0f2f3f0e0");
|
||||
String expectedCP1251String = new String(cp1251_bytes, "cp1251");
|
||||
|
||||
assertEquals( "/context/ForwardServlet", request.getAttribute(Dispatcher.FORWARD_REQUEST_URI));
|
||||
assertEquals( "/context", request.getAttribute(Dispatcher.FORWARD_CONTEXT_PATH) );
|
||||
assertEquals( "/ForwardServlet", request.getAttribute(Dispatcher.FORWARD_SERVLET_PATH));
|
||||
assertEquals( null, request.getAttribute(Dispatcher.FORWARD_PATH_INFO));
|
||||
assertEquals( "do=assertforward&foreign=%d2%e5%ec%ef%e5%f0%e0%f2%f3%f0%e0&test=1", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING) );
|
||||
|
||||
List<String> expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH,
|
||||
Dispatcher.FORWARD_SERVLET_PATH, Dispatcher.FORWARD_QUERY_STRING);
|
||||
List<String> requestAttributeNames = Collections.list(request.getAttributeNames());
|
||||
assertTrue(requestAttributeNames.containsAll(expectedAttributeNames));
|
||||
|
||||
assertEquals(null, request.getPathInfo());
|
||||
assertEquals(null, request.getPathTranslated());
|
||||
assertTrue(request.getQueryString().startsWith("do=end&else=%D0%B2%D1%8B%D0%B1%D1%80%D0%B0%D0%BD%D0%BE%3D%D0%A2%D0%B5%D0%BC%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D1%83%D1%80%D0%B0&test=1&foreign="));
|
||||
|
||||
String[] vals = request.getParameterValues("foreign");
|
||||
assertTrue(vals!=null);
|
||||
assertEquals(1, vals.length);
|
||||
assertEquals(expectedCP1251String, vals[0]);
|
||||
|
||||
assertEquals("/context/AssertForwardServlet", request.getRequestURI());
|
||||
assertEquals("/context", request.getContextPath());
|
||||
assertEquals("/AssertForwardServlet", request.getServletPath());
|
||||
|
||||
response.setContentType("text/html");
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AssertIncludeServlet extends HttpServlet implements Servlet
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.io.InputStream;
|
|||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -139,7 +140,7 @@ public class CGI extends HttpServlet
|
|||
if (!_env.envMap.containsKey("SystemRoot"))
|
||||
{
|
||||
String os = System.getProperty("os.name");
|
||||
if (os != null && os.toLowerCase().indexOf("windows") != -1)
|
||||
if (os != null && os.toLowerCase(Locale.ENGLISH).indexOf("windows") != -1)
|
||||
{
|
||||
_env.set("SystemRoot","C:\\WINDOWS");
|
||||
}
|
||||
|
@ -256,7 +257,7 @@ public class CGI extends HttpServlet
|
|||
{
|
||||
String name = (String)enm.nextElement();
|
||||
String value = req.getHeader(name);
|
||||
env.set("HTTP_" + name.toUpperCase().replace('-','_'),value);
|
||||
env.set("HTTP_" + name.toUpperCase(Locale.ENGLISH).replace('-','_'),value);
|
||||
}
|
||||
|
||||
// these extra ones were from printenv on www.dev.nomura.co.uk
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.servlets;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -278,7 +279,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
{
|
||||
for (int i=0; i< encodings.length; i++)
|
||||
{
|
||||
if (encodings[i].toLowerCase().contains(GZIP))
|
||||
if (encodings[i].toLowerCase(Locale.ENGLISH).contains(GZIP))
|
||||
{
|
||||
if (isEncodingAcceptable(encodings[i]))
|
||||
{
|
||||
|
@ -287,7 +288,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
}
|
||||
|
||||
if (encodings[i].toLowerCase().contains(DEFLATE))
|
||||
if (encodings[i].toLowerCase(Locale.ENGLISH).contains(DEFLATE))
|
||||
{
|
||||
if (isEncodingAcceptable(encodings[i]))
|
||||
{
|
||||
|
|
|
@ -36,6 +36,7 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
@ -172,7 +173,7 @@ public class MultiPartFilter implements Filter
|
|||
int c=line.indexOf(':',0);
|
||||
if(c>0)
|
||||
{
|
||||
String key=line.substring(0,c).trim().toLowerCase();
|
||||
String key=line.substring(0,c).trim().toLowerCase(Locale.ENGLISH);
|
||||
String value=line.substring(c+1,line.length()).trim();
|
||||
if(key.equals("content-disposition"))
|
||||
content_disposition=value;
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.Collections;
|
|||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
|
@ -489,7 +490,7 @@ public class ProxyServlet implements Servlet
|
|||
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
String nameString = name.toString();
|
||||
String s = nameString.toLowerCase();
|
||||
String s = nameString.toLowerCase(Locale.ENGLISH);
|
||||
if (!_DontProxyHeaders.contains(s) || (HttpHeaders.CONNECTION_BUFFER.equals(name) && HttpHeaderValues.CLOSE_BUFFER.equals(value)))
|
||||
{
|
||||
if (debug != 0)
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.net.Socket;
|
|||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -61,7 +62,7 @@ public class PutFilterTest
|
|||
FilterHolder holder = tester.addFilter(PutFilter.class,"/*",0);
|
||||
holder.setInitParameter("delAllowed","true");
|
||||
// Bloody Windows does not allow file renaming
|
||||
if (!System.getProperty("os.name").toLowerCase().contains("windows"))
|
||||
if (!System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows"))
|
||||
holder.setInitParameter("putAtomic","true");
|
||||
tester.start();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -93,7 +94,7 @@ public class Headers implements Iterable<Headers.Header>
|
|||
*/
|
||||
public Header get(String name)
|
||||
{
|
||||
return headers.get(name.trim().toLowerCase());
|
||||
return headers.get(name.trim().toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,7 +107,7 @@ public class Headers implements Iterable<Headers.Header>
|
|||
{
|
||||
name = name.trim();
|
||||
Header header = new Header(name, value.trim());
|
||||
headers.put(name.toLowerCase(), header);
|
||||
headers.put(name.toLowerCase(Locale.ENGLISH), header);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,7 +118,7 @@ public class Headers implements Iterable<Headers.Header>
|
|||
public void put(Header header)
|
||||
{
|
||||
if (header != null)
|
||||
headers.put(header.name().toLowerCase(), header);
|
||||
headers.put(header.name().toLowerCase(Locale.ENGLISH), header);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,16 +131,16 @@ public class Headers implements Iterable<Headers.Header>
|
|||
public void add(String name, String value)
|
||||
{
|
||||
name = name.trim();
|
||||
Header header = headers.get(name.toLowerCase());
|
||||
Header header = headers.get(name.toLowerCase(Locale.ENGLISH));
|
||||
if (header == null)
|
||||
{
|
||||
header = new Header(name, value.trim());
|
||||
headers.put(name.toLowerCase(), header);
|
||||
headers.put(name.toLowerCase(Locale.ENGLISH), header);
|
||||
}
|
||||
else
|
||||
{
|
||||
header = new Header(header.name(), header.value() + "," + value.trim());
|
||||
headers.put(name.toLowerCase(), header);
|
||||
headers.put(name.toLowerCase(Locale.ENGLISH), header);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +153,7 @@ public class Headers implements Iterable<Headers.Header>
|
|||
public Header remove(String name)
|
||||
{
|
||||
name = name.trim();
|
||||
return headers.remove(name.toLowerCase());
|
||||
return headers.remove(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,7 +230,7 @@ public class Headers implements Iterable<Headers.Header>
|
|||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = name.toLowerCase().hashCode();
|
||||
int result = name.toLowerCase(Locale.ENGLISH).hashCode();
|
||||
result = 31 * result + Arrays.hashCode(values);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.spdy.generator;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.spdy.CompressionDictionary;
|
||||
import org.eclipse.jetty.spdy.CompressionFactory;
|
||||
|
@ -45,7 +46,7 @@ public class HeadersBlockGenerator
|
|||
writeCount(version, buffer, headers.size());
|
||||
for (Headers.Header header : headers)
|
||||
{
|
||||
String name = header.name().toLowerCase();
|
||||
String name = header.name().toLowerCase(Locale.ENGLISH);
|
||||
byte[] nameBytes = name.getBytes(iso1);
|
||||
writeNameLength(version, buffer, nameBytes.length);
|
||||
buffer.write(nameBytes, 0, nameBytes.length);
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
@ -205,7 +206,7 @@ public class ReferrerPushStrategy implements PushStrategy
|
|||
if (header == null)
|
||||
return true;
|
||||
|
||||
String contentType = header.value().toLowerCase();
|
||||
String contentType = header.value().toLowerCase(Locale.ENGLISH);
|
||||
for (String pushContentType : pushContentTypes)
|
||||
if (contentType.startsWith(pushContentType))
|
||||
return true;
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.io.IOException;
|
|||
import java.io.InterruptedIOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
@ -664,7 +665,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
|
|||
for (int i = 0; i < fields.size(); ++i)
|
||||
{
|
||||
HttpFields.Field field = fields.getField(i);
|
||||
String name = field.getName().toLowerCase();
|
||||
String name = field.getName().toLowerCase(Locale.ENGLISH);
|
||||
String value = field.getValue();
|
||||
headers.put(name, value);
|
||||
logger.debug("HTTP < {}: {}", name, value);
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.spdy.proxy;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -95,7 +96,7 @@ public class ProxyHTTPSPDYAsyncConnection extends AsyncHttpConnection
|
|||
@Override
|
||||
protected void parsedHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
String headerName = name.toString("UTF-8").toLowerCase();
|
||||
String headerName = name.toString("UTF-8").toLowerCase(Locale.ENGLISH);
|
||||
String headerValue = value.toString("UTF-8");
|
||||
switch (headerName)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
@ -269,7 +270,7 @@ public class Config
|
|||
}
|
||||
else
|
||||
{
|
||||
String name = entry.getName().toLowerCase();
|
||||
String name = entry.getName().toLowerCase(Locale.ENGLISH);
|
||||
if (name.endsWith(".jar") || name.endsWith(".zip"))
|
||||
{
|
||||
String jar = entry.getCanonicalPath();
|
||||
|
@ -796,7 +797,7 @@ public class Config
|
|||
}
|
||||
|
||||
// Add XML configuration
|
||||
if (subject.toLowerCase().endsWith(".xml"))
|
||||
if (subject.toLowerCase(Locale.ENGLISH).endsWith(".xml"))
|
||||
{
|
||||
// Config file
|
||||
File f = new File(fixPath(file));
|
||||
|
@ -807,7 +808,7 @@ public class Config
|
|||
}
|
||||
|
||||
// Set the main class to execute (overrides any previously set)
|
||||
if (subject.toLowerCase().endsWith(".class"))
|
||||
if (subject.toLowerCase(Locale.ENGLISH).endsWith(".class"))
|
||||
{
|
||||
// Class
|
||||
String cn = expand(subject.substring(0,subject.length() - 6));
|
||||
|
@ -820,7 +821,7 @@ public class Config
|
|||
}
|
||||
|
||||
// Add raw classpath entry
|
||||
if (subject.toLowerCase().endsWith(".path"))
|
||||
if (subject.toLowerCase(Locale.ENGLISH).endsWith(".path"))
|
||||
{
|
||||
// classpath (jetty.class.path?) to add to runtime classpath
|
||||
String cn = expand(subject.substring(0,subject.length() - 5));
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.io.FilenameFilter;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
@ -37,6 +38,7 @@ import java.lang.reflect.Method;
|
|||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -44,6 +46,7 @@ import java.util.Collections;
|
|||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -152,7 +155,7 @@ public class Main
|
|||
{
|
||||
public boolean accept(File dir, String name)
|
||||
{
|
||||
return name.toLowerCase().endsWith(".ini");
|
||||
return name.toLowerCase(Locale.ENGLISH).endsWith(".ini");
|
||||
}
|
||||
});
|
||||
Arrays.sort(inis);
|
||||
|
@ -184,6 +187,15 @@ public class Main
|
|||
stop(port,key);
|
||||
return null;
|
||||
}
|
||||
|
||||
if ("--stop-wait".equals(arg))
|
||||
{
|
||||
int port = Integer.parseInt(Config.getProperty("STOP.PORT","-1"));
|
||||
String key = Config.getProperty("STOP.KEY",null);
|
||||
int timeout = Integer.parseInt(Config.getProperty("STOP.WAIT", "0"));
|
||||
stop(port,key, true, timeout);
|
||||
return null;
|
||||
}
|
||||
|
||||
if ("--version".equals(arg) || "-v".equals(arg) || "--info".equals(arg))
|
||||
{
|
||||
|
@ -288,7 +300,7 @@ public class Main
|
|||
{
|
||||
String opts[] = assign[1].split(",");
|
||||
for (String opt : opts)
|
||||
_config.addActiveOption(opt);
|
||||
_config.addActiveOption(opt.trim());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -374,7 +386,7 @@ public class Main
|
|||
return false;
|
||||
}
|
||||
|
||||
String name = path.getName().toLowerCase();
|
||||
String name = path.getName().toLowerCase(Locale.ENGLISH);
|
||||
return (name.startsWith("jetty") && name.endsWith(".xml"));
|
||||
}
|
||||
});
|
||||
|
@ -648,7 +660,7 @@ public class Main
|
|||
|
||||
private String resolveXmlConfig(String xmlFilename) throws FileNotFoundException
|
||||
{
|
||||
if (!xmlFilename.toLowerCase().endsWith(".xml"))
|
||||
if (!xmlFilename.toLowerCase(Locale.ENGLISH).endsWith(".xml"))
|
||||
{
|
||||
// Nothing to resolve.
|
||||
return xmlFilename;
|
||||
|
@ -862,7 +874,7 @@ public class Main
|
|||
|
||||
if (element.isFile())
|
||||
{
|
||||
String name = element.getName().toLowerCase();
|
||||
String name = element.getName().toLowerCase(Locale.ENGLISH);
|
||||
if (name.endsWith(".jar"))
|
||||
{
|
||||
return JarVersion.getVersion(element);
|
||||
|
@ -1002,6 +1014,12 @@ public class Main
|
|||
* Stop a running jetty instance.
|
||||
*/
|
||||
public void stop(int port, String key)
|
||||
{
|
||||
stop (port,key,false, 0);
|
||||
}
|
||||
|
||||
|
||||
public void stop (int port, String key, boolean wait, int timeout)
|
||||
{
|
||||
int _port = port;
|
||||
String _key = key;
|
||||
|
@ -1020,17 +1038,33 @@ public class Main
|
|||
}
|
||||
|
||||
Socket s = new Socket(InetAddress.getByName("127.0.0.1"),_port);
|
||||
if (wait && timeout > 0)
|
||||
s.setSoTimeout(timeout*1000);
|
||||
try
|
||||
{
|
||||
OutputStream out = s.getOutputStream();
|
||||
out.write((_key + "\r\nstop\r\n").getBytes());
|
||||
out.flush();
|
||||
|
||||
if (wait)
|
||||
{
|
||||
System.err.println("Waiting"+(timeout > 0 ? (" "+timeout+"sec") : "")+" for jetty to stop");
|
||||
LineNumberReader lin = new LineNumberReader(new InputStreamReader(s.getInputStream()));
|
||||
String response=lin.readLine();
|
||||
if ("Stopped".equals(response))
|
||||
System.err.println("Stopped");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
catch (SocketTimeoutException e)
|
||||
{
|
||||
System.err.println("Timed out waiting for stop confirmation");
|
||||
System.exit(ERR_UNKNOWN);
|
||||
}
|
||||
catch (ConnectException e)
|
||||
{
|
||||
usageExit(e,ERR_NOT_STOPPED);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
//
|
||||
|
||||
package org.eclipse.jetty.start;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.net.InetAddress;
|
||||
|
@ -113,21 +114,23 @@ public class Monitor extends Thread
|
|||
Config.debug("command=" + cmd);
|
||||
if ("stop".equals(cmd))
|
||||
{
|
||||
try {socket.close();}catch(Exception e){e.printStackTrace();}
|
||||
try {_socket.close();}catch(Exception e){e.printStackTrace();}
|
||||
if (_process!=null)
|
||||
{
|
||||
//if we have a child process, wait for it to finish before we stop
|
||||
try
|
||||
{
|
||||
_process.destroy();
|
||||
_process.waitFor();
|
||||
_process.destroy();
|
||||
_process.waitFor();
|
||||
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
System.err.println("Interrupted waiting for child to terminate");
|
||||
}
|
||||
}
|
||||
socket.getOutputStream().write("Stopped\r\n".getBytes());
|
||||
try {socket.close();}catch(Exception e){e.printStackTrace();}
|
||||
try {_socket.close();}catch(Exception e){e.printStackTrace();}
|
||||
System.exit(0);
|
||||
}
|
||||
else if ("status".equals(cmd))
|
||||
|
|
|
@ -24,7 +24,10 @@ Command Line Options:
|
|||
contains -X or -D arguments, but creates an extra
|
||||
JVM instance.
|
||||
|
||||
--stop Stop the running Jetty instance.
|
||||
--stop Send a stop signal to the running Jetty instance.
|
||||
|
||||
--stop-wait Send a stop signal to the running Jetty instance, waiting for
|
||||
confirmation that it is stopping.
|
||||
|
||||
--daemon Start in daemon mode with stderr and stdout
|
||||
redirected to ${jetty.log}/start.log
|
||||
|
@ -92,6 +95,11 @@ Properties:
|
|||
STOP.KEY=[alphanumeric]
|
||||
The passphrase defined to stop the server.
|
||||
Requried along with STOP.PORT if you want to use the --stop option above.
|
||||
|
||||
STOP.WAIT=[number]
|
||||
The time (in seconds) to wait for confirmation that the running Jetty server
|
||||
has stopped. If not specified, the stopper will wait indefinitely. Use in
|
||||
conjunction with the --stop-wait option.
|
||||
|
||||
DEBUG=true
|
||||
Enable debug on the start mechanism and sets the
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
@ -221,7 +222,7 @@ public class RolloverFileOutputStream extends FilterOutputStream
|
|||
|
||||
// Is this a rollover file?
|
||||
String filename=file.getName();
|
||||
int i=filename.toLowerCase().indexOf(YYYY_MM_DD);
|
||||
int i=filename.toLowerCase(Locale.ENGLISH).indexOf(YYYY_MM_DD);
|
||||
if (i>=0)
|
||||
{
|
||||
file=new File(dir,
|
||||
|
@ -258,7 +259,7 @@ public class RolloverFileOutputStream extends FilterOutputStream
|
|||
File file= new File(_filename);
|
||||
File dir = new File(file.getParent());
|
||||
String fn=file.getName();
|
||||
int s=fn.toLowerCase().indexOf(YYYY_MM_DD);
|
||||
int s=fn.toLowerCase(Locale.ENGLISH).indexOf(YYYY_MM_DD);
|
||||
if (s<0)
|
||||
return;
|
||||
String prefix=fn.substring(0,s);
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -89,9 +90,9 @@ public class JSONObjectConvertor implements JSON.Convertor
|
|||
{
|
||||
String name=m.getName();
|
||||
if (name.startsWith("is"))
|
||||
name=name.substring(2,3).toLowerCase()+name.substring(3);
|
||||
name=name.substring(2,3).toLowerCase(Locale.ENGLISH)+name.substring(3);
|
||||
else if (name.startsWith("get"))
|
||||
name=name.substring(3,4).toLowerCase()+name.substring(4);
|
||||
name=name.substring(3,4).toLowerCase(Locale.ENGLISH)+name.substring(4);
|
||||
else
|
||||
continue;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.Arrays;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -122,9 +123,9 @@ public class JSONPojoConvertor implements JSON.Convertor
|
|||
if(m.getReturnType()!=null)
|
||||
{
|
||||
if (name.startsWith("is") && name.length()>2)
|
||||
name=name.substring(2,3).toLowerCase()+name.substring(3);
|
||||
name=name.substring(2,3).toLowerCase(Locale.ENGLISH)+name.substring(3);
|
||||
else if (name.startsWith("get") && name.length()>3)
|
||||
name=name.substring(3,4).toLowerCase()+name.substring(4);
|
||||
name=name.substring(3,4).toLowerCase(Locale.ENGLISH)+name.substring(4);
|
||||
else
|
||||
break;
|
||||
if(includeField(name, m))
|
||||
|
|
|
@ -31,12 +31,11 @@ import org.eclipse.jetty.util.DateCache;
|
|||
* the eclipse jetty root level logger level to that specified level. (Default level is INFO)
|
||||
* <p>
|
||||
* If the system property "org.eclipse.jetty.util.log.SOURCE" is set, then the source method/file of a log is logged.
|
||||
* For named debuggers, the system property name+".SOURCE" is checked. If it is not not set, then
|
||||
* "org.eclipse.jetty.util.log.SOURCE" is used as the default.
|
||||
* For named debuggers, the system property name+".SOURCE" is checked, eg "org.eclipse.jetty.util.log.stderr.SOURCE".
|
||||
* If it is not not set, then "org.eclipse.jetty.util.log.SOURCE" is used as the default.
|
||||
* <p>
|
||||
* If the system property "org.eclipse.jetty.util.log.LONG" is set, then the full, unabbreviated name of the logger is
|
||||
* used for logging. For named debuggers, the system property name+".LONG" is checked. If it is not not set, then
|
||||
* "org.eclipse.jetty.util.log.LONG" is used as the default.
|
||||
* If the system property "org.eclipse.jetty.util.log.stderr.LONG" is set, then the full, unabbreviated name of the logger is
|
||||
* used for logging.
|
||||
*/
|
||||
public class StdErrLog extends AbstractLogger
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.io.InputStream;
|
|||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Locale;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -144,7 +145,7 @@ public abstract class JarScanner extends org.eclipse.jetty.util.PatternMatcher
|
|||
throws Exception
|
||||
{
|
||||
LOG.debug("Search of {}",uri);
|
||||
if (uri.toString().toLowerCase().endsWith(".jar"))
|
||||
if (uri.toString().toLowerCase(Locale.ENGLISH).endsWith(".jar"))
|
||||
{
|
||||
|
||||
InputStream in = Resource.newResource(uri).getInputStream();
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.eclipse.jetty.webapp;
|
|||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -125,7 +126,7 @@ public class MetaInfConfiguration extends AbstractConfiguration
|
|||
}
|
||||
else
|
||||
{
|
||||
String lcname = name.toLowerCase();
|
||||
String lcname = name.toLowerCase(Locale.ENGLISH);
|
||||
if (lcname.endsWith(".tld"))
|
||||
{
|
||||
addResource(context,METAINF_TLDS,Resource.newResource("jar:"+jarUri+"!/"+name));
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.EnumSet;
|
|||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -320,7 +321,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
|
|||
XmlParser.Node startup = node.get("load-on-startup");
|
||||
if (startup != null)
|
||||
{
|
||||
String s = startup.toString(false, true).toLowerCase();
|
||||
String s = startup.toString(false, true).toLowerCase(Locale.ENGLISH);
|
||||
int order = 0;
|
||||
if (s.startsWith("t"))
|
||||
{
|
||||
|
@ -679,16 +680,18 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
|
|||
String error = node.getString("error-code", false, true);
|
||||
int code=0;
|
||||
if (error == null || error.length() == 0)
|
||||
{
|
||||
error = node.getString("exception-type", false, true);
|
||||
if (error == null || error.length() == 0)
|
||||
error = ErrorPageErrorHandler.GLOBAL_ERROR_PAGE;
|
||||
}
|
||||
else
|
||||
code=Integer.valueOf(error);
|
||||
|
||||
String location = node.getString("location", false, true);
|
||||
|
||||
|
||||
ErrorPageErrorHandler handler = (ErrorPageErrorHandler)context.getErrorHandler();
|
||||
|
||||
|
||||
Origin o = context.getMetaData().getOrigin("error."+error);
|
||||
|
||||
switch (o)
|
||||
{
|
||||
case NotSet:
|
||||
|
@ -708,11 +711,16 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
|
|||
//an error page setup was set in web.xml, only allow other web xml descriptors to override it
|
||||
if (!(descriptor instanceof FragmentDescriptor))
|
||||
{
|
||||
if (code>0)
|
||||
handler.addErrorPage(code,location);
|
||||
if (descriptor instanceof OverrideDescriptor || descriptor instanceof DefaultsDescriptor)
|
||||
{
|
||||
if (code>0)
|
||||
handler.addErrorPage(code,location);
|
||||
else
|
||||
handler.addErrorPage(error,location);
|
||||
context.getMetaData().setOrigin("error."+error, descriptor);
|
||||
}
|
||||
else
|
||||
handler.addErrorPage(error,location);
|
||||
context.getMetaData().setOrigin("error."+error, descriptor);
|
||||
throw new IllegalStateException("Duplicate global error-page "+location);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -909,7 +917,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
|
|||
if (data != null)
|
||||
{
|
||||
data = data.get("transport-guarantee");
|
||||
String guarantee = data.toString(false, true).toUpperCase();
|
||||
String guarantee = data.toString(false, true).toUpperCase(Locale.ENGLISH);
|
||||
if (guarantee == null || guarantee.length() == 0 || "NONE".equals(guarantee))
|
||||
scBase.setDataConstraint(Constraint.DC_NONE);
|
||||
else if ("INTEGRAL".equals(guarantee))
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -217,7 +218,7 @@ public class TagLibConfiguration extends AbstractConfiguration
|
|||
while(iter.hasNext())
|
||||
{
|
||||
String location = iter.next();
|
||||
if (location!=null && location.toLowerCase().endsWith(".tld"))
|
||||
if (location!=null && location.toLowerCase(Locale.ENGLISH).endsWith(".tld"))
|
||||
{
|
||||
if (!location.startsWith("/"))
|
||||
location="/WEB-INF/"+location;
|
||||
|
@ -234,7 +235,7 @@ public class TagLibConfiguration extends AbstractConfiguration
|
|||
String[] contents = web_inf.list();
|
||||
for (int i=0;contents!=null && i<contents.length;i++)
|
||||
{
|
||||
if (contents[i]!=null && contents[i].toLowerCase().endsWith(".tld"))
|
||||
if (contents[i]!=null && contents[i].toLowerCase(Locale.ENGLISH).endsWith(".tld"))
|
||||
{
|
||||
Resource l=web_inf.addPath(contents[i]);
|
||||
tlds.add(l);
|
||||
|
@ -249,7 +250,7 @@ public class TagLibConfiguration extends AbstractConfiguration
|
|||
String[] contents = web_inf_tlds.list();
|
||||
for (int i=0;contents!=null && i<contents.length;i++)
|
||||
{
|
||||
if (contents[i]!=null && contents[i].toLowerCase().endsWith(".tld"))
|
||||
if (contents[i]!=null && contents[i].toLowerCase(Locale.ENGLISH).endsWith(".tld"))
|
||||
{
|
||||
Resource l=web_inf_tlds.addPath(contents[i]);
|
||||
tlds.add(l);
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Collections;
|
|||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
|
@ -271,7 +272,7 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
try
|
||||
{
|
||||
Resource fn=lib.addPath(files[f]);
|
||||
String fnlc=fn.getName().toLowerCase();
|
||||
String fnlc=fn.getName().toLowerCase(Locale.ENGLISH);
|
||||
// don't check if this is a directory, see Bug 353165
|
||||
if (isFileSupported(fnlc))
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.net.URL;
|
|||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
|
@ -442,7 +443,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
{
|
||||
// look for a sibling like "foo/" to a "foo.war"
|
||||
File warfile=Resource.newResource(war).getFile();
|
||||
if (warfile!=null && warfile.getName().toLowerCase().endsWith(".war"))
|
||||
if (warfile!=null && warfile.getName().toLowerCase(Locale.ENGLISH).endsWith(".war"))
|
||||
{
|
||||
File sibling = new File(warfile.getParent(),warfile.getName().substring(0,warfile.getName().length()-4));
|
||||
if (sibling.exists() && sibling.isDirectory() && sibling.canWrite())
|
||||
|
@ -709,7 +710,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
try
|
||||
{
|
||||
Resource file = web_inf_lib.addPath(files[f]);
|
||||
String fnlc = file.getName().toLowerCase();
|
||||
String fnlc = file.getName().toLowerCase(Locale.ENGLISH);
|
||||
int dot = fnlc.lastIndexOf('.');
|
||||
String extension = (dot < 0 ? null : fnlc.substring(dot));
|
||||
if (extension != null && (extension.equals(".jar") || extension.equals(".zip")))
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Map;
|
|||
import java.util.Queue;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
|
@ -389,7 +390,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
_accept = value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TODO simone says shouldn't be needed
|
||||
public void startRequest(Buffer method, Buffer url, Buffer version) throws IOException
|
||||
{
|
||||
if (_error == null)
|
||||
|
@ -397,7 +398,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
_endp.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TODO simone says shouldn't be needed
|
||||
public void content(Buffer ref) throws IOException
|
||||
{
|
||||
if (_error == null)
|
||||
|
@ -515,6 +516,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
|
||||
private WebSocketConnection newWebSocketConnection() throws IOException
|
||||
{
|
||||
__log.debug("newWebSocketConnection()");
|
||||
return new WebSocketClientConnection(
|
||||
_future._client.getFactory(),
|
||||
_future.getWebSocket(),
|
||||
|
|
|
@ -123,6 +123,8 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
_endp.close();
|
||||
break;
|
||||
}
|
||||
else if (filled==0)
|
||||
return this;
|
||||
}
|
||||
|
||||
if (_websocket instanceof OnFrame)
|
||||
|
|
|
@ -323,13 +323,13 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
|
|||
|
||||
try
|
||||
{
|
||||
if (tell_app)
|
||||
_webSocket.onClose(code,message);
|
||||
if (!closed_out)
|
||||
closeOut(code,message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!closed_out)
|
||||
closeOut(code,message);
|
||||
if (tell_app)
|
||||
_webSocket.onClose(code,message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,7 +353,7 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
|
|||
}
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
if (tell_app)
|
||||
_webSocket.onClose(code,message);
|
||||
}
|
||||
|
|
|
@ -81,16 +81,37 @@ public class WebSocketFactory extends AbstractLifeCycle
|
|||
private int _maxIdleTime = 300000;
|
||||
private int _maxTextMessageSize = 16 * 1024;
|
||||
private int _maxBinaryMessageSize = -1;
|
||||
private int _minVersion;
|
||||
|
||||
public WebSocketFactory(Acceptor acceptor)
|
||||
{
|
||||
this(acceptor, 64 * 1024);
|
||||
this(acceptor, 64 * 1024, WebSocketConnectionRFC6455.VERSION);
|
||||
}
|
||||
|
||||
public WebSocketFactory(Acceptor acceptor, int bufferSize)
|
||||
{
|
||||
this(acceptor, bufferSize, WebSocketConnectionRFC6455.VERSION);
|
||||
}
|
||||
|
||||
public WebSocketFactory(Acceptor acceptor, int bufferSize, int minVersion)
|
||||
{
|
||||
_buffers = new WebSocketBuffers(bufferSize);
|
||||
_acceptor = acceptor;
|
||||
_minVersion=WebSocketConnectionRFC6455.VERSION;
|
||||
}
|
||||
|
||||
public int getMinVersion()
|
||||
{
|
||||
return _minVersion;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param minVersion The minimum support version (default RCF6455.VERSION == 13 )
|
||||
*/
|
||||
public void setMinVersion(int minVersion)
|
||||
{
|
||||
_minVersion = minVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,6 +248,8 @@ public class WebSocketFactory extends AbstractLifeCycle
|
|||
}
|
||||
|
||||
final WebSocketServletConnection connection;
|
||||
if (draft<_minVersion)
|
||||
draft=Integer.MAX_VALUE;
|
||||
switch (draft)
|
||||
{
|
||||
case -1: // unspecified draft/version
|
||||
|
@ -263,7 +286,15 @@ public class WebSocketFactory extends AbstractLifeCycle
|
|||
LOG.warn("Unsupported Websocket version: " + draft);
|
||||
// Per RFC 6455 - 4.4 - Supporting Multiple Versions of WebSocket Protocol
|
||||
// Using the examples as outlined
|
||||
response.setHeader("Sec-WebSocket-Version", "13, 8, 6, 0");
|
||||
String versions="13";
|
||||
if (_minVersion<=8)
|
||||
versions+=", 8";
|
||||
if (_minVersion<=6)
|
||||
versions+=", 6";
|
||||
if (_minVersion<=0)
|
||||
versions+=", 0";
|
||||
|
||||
response.setHeader("Sec-WebSocket-Version", versions);
|
||||
throw new HttpException(400, "Unsupported websocket version specification: " + draft);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,9 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* <p/>
|
||||
* The initParameter "maxBinaryMessagesSize" can be used to set the size in bytes
|
||||
* that a websocket may be accept before closing.
|
||||
* <p/>
|
||||
* The initParameter "minVersion" can be used to set the minimum protocol version
|
||||
* accepted. Default is the RFC6455 version (13)
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class WebSocketServlet extends HttpServlet implements WebSocketFactory.Acceptor
|
||||
|
@ -76,6 +79,10 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
|
|||
max = getInitParameter("maxBinaryMessageSize");
|
||||
if (max != null)
|
||||
_webSocketFactory.setMaxBinaryMessageSize(Integer.parseInt(max));
|
||||
|
||||
String min = getInitParameter("minVersion");
|
||||
if (min != null)
|
||||
_webSocketFactory.setMinVersion(Integer.parseInt(min));
|
||||
}
|
||||
catch (ServletException x)
|
||||
{
|
||||
|
|
|
@ -62,7 +62,9 @@ public class SafariWebsocketDraft0Test
|
|||
|
||||
// Serve capture servlet
|
||||
servlet = new WebSocketCaptureServlet();
|
||||
context.addServlet(new ServletHolder(servlet),"/");
|
||||
ServletHolder holder = new ServletHolder(servlet);
|
||||
holder.setInitParameter("minVersion","-1");
|
||||
context.addServlet(holder,"/");
|
||||
|
||||
// Start Server
|
||||
server.start();
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.websocket.dummy.DummyServer;
|
||||
import org.eclipse.jetty.websocket.dummy.DummyServer.ServerConnection;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TomcatServerQuirksTest
|
||||
{
|
||||
/**
|
||||
* Test for when encountering a "Transfer-Encoding: chunked" on a Upgrade Response header.
|
||||
* <ul>
|
||||
* <li><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=393075">Eclipse Jetty Bug #393075</a></li>
|
||||
* <li><a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=54067">Apache Tomcat Bug #54067</a></li>
|
||||
* </ul>
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
@Ignore("Bug with Transfer-Encoding")
|
||||
public void testTomcat7_0_32_WithTransferEncoding() throws Exception {
|
||||
DummyServer server = new DummyServer();
|
||||
int bufferSize = 512;
|
||||
QueuedThreadPool threadPool = new QueuedThreadPool();
|
||||
WebSocketClientFactory factory = new WebSocketClientFactory(threadPool, new ZeroMaskGen(), bufferSize);
|
||||
|
||||
try {
|
||||
server.start();
|
||||
|
||||
// Setup Client Factory
|
||||
threadPool.start();
|
||||
factory.start();
|
||||
|
||||
// Create Client
|
||||
WebSocketClient client = new WebSocketClient(factory);
|
||||
|
||||
// Create End User WebSocket Class
|
||||
final CountDownLatch openLatch = new CountDownLatch(1);
|
||||
final CountDownLatch dataLatch = new CountDownLatch(1);
|
||||
WebSocket.OnTextMessage websocket = new WebSocket.OnTextMessage()
|
||||
{
|
||||
public void onOpen(Connection connection)
|
||||
{
|
||||
openLatch.countDown();
|
||||
}
|
||||
|
||||
public void onMessage(String data)
|
||||
{
|
||||
// System.out.println("data = " + data);
|
||||
dataLatch.countDown();
|
||||
}
|
||||
|
||||
public void onClose(int closeCode, String message)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Open connection
|
||||
URI wsURI = server.getWsUri();
|
||||
client.open(wsURI, websocket);
|
||||
|
||||
// Accept incoming connection
|
||||
ServerConnection socket = server.accept();
|
||||
socket.setSoTimeout(2000); // timeout
|
||||
|
||||
// Issue upgrade
|
||||
Map<String,String> extraResponseHeaders = new HashMap<String, String>();
|
||||
extraResponseHeaders.put("Transfer-Encoding", "chunked"); // !! The problem !!
|
||||
socket.upgrade(extraResponseHeaders);
|
||||
|
||||
// Wait for proper upgrade
|
||||
Assert.assertTrue("Timed out waiting for Client side WebSocket open event", openLatch.await(1, TimeUnit.SECONDS));
|
||||
|
||||
// Have server write frame.
|
||||
int length = bufferSize / 2;
|
||||
ByteBuffer serverFrame = ByteBuffer.allocate(bufferSize);
|
||||
serverFrame.put((byte)(0x80 | 0x01)); // FIN + TEXT
|
||||
serverFrame.put((byte)0x7E); // No MASK and 2 bytes length
|
||||
serverFrame.put((byte)(length >> 8)); // first length byte
|
||||
serverFrame.put((byte)(length & 0xFF)); // second length byte
|
||||
for (int i = 0; i < length; ++i)
|
||||
serverFrame.put((byte)'x');
|
||||
serverFrame.flip();
|
||||
byte buf[] = serverFrame.array();
|
||||
socket.write(buf,0,buf.length);
|
||||
socket.flush();
|
||||
|
||||
Assert.assertTrue(dataLatch.await(1000, TimeUnit.SECONDS));
|
||||
} finally {
|
||||
factory.stop();
|
||||
threadPool.stop();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -47,9 +49,6 @@ import org.junit.Assert;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class WebSocketClientTest
|
||||
{
|
||||
private WebSocketClientFactory _factory = new WebSocketClientFactory();
|
||||
|
@ -103,6 +102,7 @@ public class WebSocketClientTest
|
|||
{
|
||||
}
|
||||
};
|
||||
|
||||
client.open(new URI("ws://127.0.0.1:" + _serverPort + "/"), websocket);
|
||||
|
||||
Socket socket = _server.accept();
|
||||
|
|
|
@ -72,6 +72,7 @@ public class WebSocketLoadD08Test
|
|||
return new EchoWebSocket();
|
||||
}
|
||||
};
|
||||
wsHandler.getWebSocketFactory().setMinVersion(8);
|
||||
wsHandler.setHandler(new DefaultHandler());
|
||||
_server.setHandler(wsHandler);
|
||||
|
||||
|
@ -196,7 +197,7 @@ public class WebSocketLoadD08Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: onConnect\r\n" +
|
||||
"Sec-WebSocket-Version: 7\r\n"+
|
||||
"Sec-WebSocket-Version: 8\r\n"+
|
||||
"\r\n");
|
||||
output.flush();
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ public class WebSocketLoadRFC6455Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: onConnect\r\n" +
|
||||
"Sec-WebSocket-Version: 7\r\n"+
|
||||
"Sec-WebSocket-Version: 13\r\n"+
|
||||
"\r\n");
|
||||
output.flush();
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ public class WebSocketMessageD00Test
|
|||
return __serverWebSocket;
|
||||
}
|
||||
};
|
||||
wsHandler.getWebSocketFactory().setMinVersion(-1);
|
||||
wsHandler.setHandler(new DefaultHandler());
|
||||
__server.setHandler(wsHandler);
|
||||
__server.start();
|
||||
|
|
|
@ -66,6 +66,7 @@ public class WebSocketMessageD06Test
|
|||
return _serverWebSocket;
|
||||
}
|
||||
};
|
||||
wsHandler.getWebSocketFactory().setMinVersion(6);
|
||||
wsHandler.getWebSocketFactory().setBufferSize(8192);
|
||||
wsHandler.getWebSocketFactory().setMaxIdleTime(1000);
|
||||
wsHandler.setHandler(new DefaultHandler());
|
||||
|
|
|
@ -77,6 +77,7 @@ public class WebSocketMessageD08Test
|
|||
return __serverWebSocket;
|
||||
}
|
||||
};
|
||||
wsHandler.getWebSocketFactory().setMinVersion(8);
|
||||
wsHandler.getWebSocketFactory().setBufferSize(8192);
|
||||
wsHandler.getWebSocketFactory().setMaxIdleTime(1000);
|
||||
wsHandler.setHandler(new DefaultHandler());
|
||||
|
|
|
@ -1337,7 +1337,7 @@ public class WebSocketMessageRFC6455Test
|
|||
output.flush();
|
||||
|
||||
// Make sure the read times out if there are problems with the implementation
|
||||
socket.setSoTimeout(1000);
|
||||
socket.setSoTimeout(10000);
|
||||
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
@ -1347,7 +1347,7 @@ public class WebSocketMessageRFC6455Test
|
|||
skipTo("\r\n\r\n",input);
|
||||
|
||||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertTrue(__serverWebSocket.awaitConnected(10000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
assertEquals(0x81,input.read());
|
||||
|
@ -1355,7 +1355,7 @@ public class WebSocketMessageRFC6455Test
|
|||
lookFor("sent on connect",input);
|
||||
socket.close();
|
||||
|
||||
assertTrue(__serverWebSocket.awaitDisconnected(500));
|
||||
assertTrue(__serverWebSocket.awaitDisconnected(10000));
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -80,6 +80,8 @@ public class WebSocketServletRFCTest
|
|||
try
|
||||
{
|
||||
conn.sendMessage(data);
|
||||
|
||||
conn.close(1000, data);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
@ -178,7 +180,7 @@ public class WebSocketServletRFCTest
|
|||
// System.out.println("RESPONSE: " + respHeader);
|
||||
|
||||
Assert.assertThat("Response Code",respHeader,startsWith("HTTP/1.1 400 Unsupported websocket version specification"));
|
||||
Assert.assertThat("Response Header Versions",respHeader,containsString("Sec-WebSocket-Version: 13, 8, 6, 0\r\n"));
|
||||
Assert.assertThat("Response Header Versions",respHeader,containsString("Sec-WebSocket-Version: 13\r\n"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -240,4 +242,44 @@ public class WebSocketServletRFCTest
|
|||
sender.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the requirement of responding with server terminated close code 1011 when there is an unhandled (internal
|
||||
* server error) being produced by the extended WebSocketServlet.
|
||||
*/
|
||||
@Test
|
||||
public void testResponseOfHttpKeyword() throws Exception
|
||||
{
|
||||
WebSocketClientFactory clientFactory = new WebSocketClientFactory();
|
||||
clientFactory.start();
|
||||
|
||||
WebSocketClient wsc = clientFactory.newWebSocketClient();
|
||||
MessageSender sender = new MessageSender();
|
||||
wsc.open(serverUri,sender);
|
||||
|
||||
String message = "GET";
|
||||
|
||||
try
|
||||
{
|
||||
sender.awaitConnect();
|
||||
|
||||
// echo back a http keyword
|
||||
sender.sendMessage(message);
|
||||
|
||||
// Give servlet 500 millisecond to process messages
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
|
||||
sender.awaitMessage();
|
||||
|
||||
Assert.assertEquals("Message should match",message, sender.getMessage());
|
||||
Assert.assertThat("WebSocket should be closed",sender.isConnected(),is(false));
|
||||
Assert.assertThat("WebSocket close clode",sender.getCloseCode(),is(1000));
|
||||
Assert.assertEquals("WebSocket close message",message, sender.getCloseMessage());
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
sender.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,308 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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.websocket.dummy;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.WebSocketConnectionRFC6455;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
* Simple ServerSocket server used to test oddball server scenarios encountered in the real world.
|
||||
*/
|
||||
public class DummyServer
|
||||
{
|
||||
public static class ServerConnection
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ServerConnection.class);
|
||||
private final Socket socket;
|
||||
private InputStream in;
|
||||
private OutputStream out;
|
||||
|
||||
public ServerConnection(Socket socket)
|
||||
{
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
public int read(ByteBuffer buf) throws IOException
|
||||
{
|
||||
int len = 0;
|
||||
while ((in.available() > 0) && (buf.remaining() > 0))
|
||||
{
|
||||
buf.put((byte)in.read());
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
public void disconnect()
|
||||
{
|
||||
LOG.debug("disconnect");
|
||||
IO.close(in);
|
||||
IO.close(out);
|
||||
if (socket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
catch (IOException ignore)
|
||||
{
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException
|
||||
{
|
||||
if (in == null)
|
||||
{
|
||||
in = socket.getInputStream();
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() throws IOException
|
||||
{
|
||||
if (out == null)
|
||||
{
|
||||
out = socket.getOutputStream();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public void flush() throws IOException
|
||||
{
|
||||
LOG.debug("flush()");
|
||||
getOutputStream().flush();
|
||||
}
|
||||
|
||||
public String readRequest() throws IOException
|
||||
{
|
||||
LOG.debug("Reading client request");
|
||||
StringBuilder request = new StringBuilder();
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream()));
|
||||
for (String line = in.readLine(); line != null; line = in.readLine())
|
||||
{
|
||||
if (line.length() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
request.append(line).append("\r\n");
|
||||
LOG.debug("read line: {}",line);
|
||||
}
|
||||
|
||||
LOG.debug("Client Request:{}{}","\n",request);
|
||||
return request.toString();
|
||||
}
|
||||
|
||||
public void respond(String rawstr) throws IOException
|
||||
{
|
||||
LOG.debug("respond(){}{}","\n",rawstr);
|
||||
getOutputStream().write(rawstr.getBytes());
|
||||
flush();
|
||||
}
|
||||
|
||||
public void setSoTimeout(int ms) throws SocketException
|
||||
{
|
||||
socket.setSoTimeout(ms);
|
||||
}
|
||||
|
||||
public void upgrade(Map<String, String> extraResponseHeaders) throws IOException
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
Pattern patExts = Pattern.compile("^Sec-WebSocket-Extensions: (.*)$",Pattern.CASE_INSENSITIVE);
|
||||
Pattern patKey = Pattern.compile("^Sec-WebSocket-Key: (.*)$",Pattern.CASE_INSENSITIVE);
|
||||
|
||||
LOG.debug("(Upgrade) Reading HTTP Request");
|
||||
Matcher mat;
|
||||
String key = "not sent";
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream()));
|
||||
for (String line = in.readLine(); line != null; line = in.readLine())
|
||||
{
|
||||
if (line.length() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Check for extensions
|
||||
// mat = patExts.matcher(line);
|
||||
// if (mat.matches())
|
||||
|
||||
// Check for Key
|
||||
mat = patKey.matcher(line);
|
||||
if (mat.matches())
|
||||
{
|
||||
key = mat.group(1);
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug("(Upgrade) Writing HTTP Response");
|
||||
// TODO: handle extensions?
|
||||
|
||||
// Setup Response
|
||||
StringBuilder resp = new StringBuilder();
|
||||
resp.append("HTTP/1.1 101 Upgrade\r\n");
|
||||
resp.append("Upgrade: websocket\r\n");
|
||||
resp.append("Connection: upgrade\r\n");
|
||||
resp.append("Sec-WebSocket-Accept: ");
|
||||
resp.append(WebSocketConnectionRFC6455.hashKey(key)).append("\r\n");
|
||||
// extra response headers.
|
||||
if (extraResponseHeaders != null)
|
||||
{
|
||||
for (Map.Entry<String,String> header : extraResponseHeaders.entrySet())
|
||||
{
|
||||
resp.append(header.getKey());
|
||||
resp.append(": ");
|
||||
resp.append(header.getValue());
|
||||
resp.append("\r\n");
|
||||
}
|
||||
}
|
||||
resp.append("\r\n");
|
||||
|
||||
// Write Response
|
||||
getOutputStream().write(resp.toString().getBytes());
|
||||
flush();
|
||||
}
|
||||
|
||||
public void write(byte[] bytes) throws IOException
|
||||
{
|
||||
LOG.debug("Writing {} bytes", bytes.length);
|
||||
getOutputStream().write(bytes);
|
||||
}
|
||||
|
||||
public void write(byte[] buf, int offset, int length) throws IOException
|
||||
{
|
||||
LOG.debug("Writing bytes[{}], offset={}, length={}", buf.length, offset, length);
|
||||
getOutputStream().write(buf,offset,length);
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
LOG.debug("Writing int={}", b);
|
||||
getOutputStream().write(b);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOG = Log.getLogger(DummyServer.class);
|
||||
private ServerSocket serverSocket;
|
||||
private URI wsUri;
|
||||
|
||||
public ServerConnection accept() throws IOException
|
||||
{
|
||||
LOG.debug(".accept()");
|
||||
assertIsStarted();
|
||||
Socket socket = serverSocket.accept();
|
||||
return new ServerConnection(socket);
|
||||
}
|
||||
|
||||
private void assertIsStarted()
|
||||
{
|
||||
Assert.assertThat("ServerSocket",serverSocket,notNullValue());
|
||||
Assert.assertThat("ServerSocket.isBound",serverSocket.isBound(),is(true));
|
||||
Assert.assertThat("ServerSocket.isClosed",serverSocket.isClosed(),is(false));
|
||||
|
||||
Assert.assertThat("WsUri",wsUri,notNullValue());
|
||||
}
|
||||
|
||||
public URI getWsUri()
|
||||
{
|
||||
return wsUri;
|
||||
}
|
||||
|
||||
public void respondToClient(Socket connection, String serverResponse) throws IOException
|
||||
{
|
||||
InputStream in = null;
|
||||
InputStreamReader isr = null;
|
||||
BufferedReader buf = null;
|
||||
OutputStream out = null;
|
||||
try
|
||||
{
|
||||
in = connection.getInputStream();
|
||||
isr = new InputStreamReader(in);
|
||||
buf = new BufferedReader(isr);
|
||||
String line;
|
||||
while ((line = buf.readLine()) != null)
|
||||
{
|
||||
// System.err.println(line);
|
||||
if (line.length() == 0)
|
||||
{
|
||||
// Got the "\r\n" line.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// System.out.println("[Server-Out] " + serverResponse);
|
||||
out = connection.getOutputStream();
|
||||
out.write(serverResponse.getBytes());
|
||||
out.flush();
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(buf);
|
||||
IO.close(isr);
|
||||
IO.close(in);
|
||||
IO.close(out);
|
||||
}
|
||||
}
|
||||
|
||||
public void start() throws IOException
|
||||
{
|
||||
serverSocket = new ServerSocket();
|
||||
InetAddress addr = InetAddress.getByName("localhost");
|
||||
InetSocketAddress endpoint = new InetSocketAddress(addr,0);
|
||||
serverSocket.bind(endpoint);
|
||||
int port = serverSocket.getLocalPort();
|
||||
String uri = String.format("ws://%s:%d/",addr.getHostAddress(),port);
|
||||
wsUri = URI.create(uri);
|
||||
LOG.debug("Server Started on {} -> {}",endpoint,wsUri);
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
LOG.debug("Stopping Server");
|
||||
try
|
||||
{
|
||||
serverSocket.close();
|
||||
}
|
||||
catch (IOException ignore)
|
||||
{
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -24,13 +24,17 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.eclipse.jetty.websocket.WebSocket;
|
||||
|
||||
public class MessageSender implements WebSocket
|
||||
public class MessageSender implements WebSocket, WebSocket.OnTextMessage
|
||||
{
|
||||
private Connection conn;
|
||||
private CountDownLatch connectLatch = new CountDownLatch(1);
|
||||
private CountDownLatch messageLatch = new CountDownLatch(1);
|
||||
|
||||
private int closeCode = -1;
|
||||
private String closeMessage = null;
|
||||
|
||||
private String message = null;
|
||||
|
||||
|
||||
public void onOpen(Connection connection)
|
||||
{
|
||||
this.conn = connection;
|
||||
|
@ -43,6 +47,12 @@ public class MessageSender implements WebSocket
|
|||
this.closeCode = closeCode;
|
||||
this.closeMessage = message;
|
||||
}
|
||||
|
||||
|
||||
public void onMessage(String data)
|
||||
{
|
||||
message = data;
|
||||
}
|
||||
|
||||
public boolean isConnected()
|
||||
{
|
||||
|
@ -62,6 +72,11 @@ public class MessageSender implements WebSocket
|
|||
{
|
||||
return closeMessage;
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
public void sendMessage(String format, Object... args) throws IOException
|
||||
{
|
||||
|
@ -72,6 +87,11 @@ public class MessageSender implements WebSocket
|
|||
{
|
||||
connectLatch.await(1,TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void awaitMessage() throws InterruptedException
|
||||
{
|
||||
messageLatch.await(1,TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Setup default logging implementation for during testing
|
||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
org.eclipse.jetty.LEVEL=INFO
|
||||
org.eclipse.jetty.websocket.LEVEL=DEBUG
|
|
@ -39,6 +39,7 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Queue;
|
||||
|
@ -424,7 +425,7 @@ public class XmlConfiguration
|
|||
private void set(Object obj, XmlParser.Node node) throws Exception
|
||||
{
|
||||
String attr = node.getAttribute("name");
|
||||
String name = "set" + attr.substring(0,1).toUpperCase() + attr.substring(1);
|
||||
String name = "set" + attr.substring(0,1).toUpperCase(Locale.ENGLISH) + attr.substring(1);
|
||||
Object value = value(obj,node);
|
||||
Object[] arg =
|
||||
{ value };
|
||||
|
@ -663,7 +664,7 @@ public class XmlConfiguration
|
|||
try
|
||||
{
|
||||
// try calling a getXxx method.
|
||||
Method method = oClass.getMethod("get" + name.substring(0,1).toUpperCase() + name.substring(1),(java.lang.Class[])null);
|
||||
Method method = oClass.getMethod("get" + name.substring(0,1).toUpperCase(Locale.ENGLISH) + name.substring(1),(java.lang.Class[])null);
|
||||
obj = method.invoke(obj,(java.lang.Object[])null);
|
||||
configure(obj,node,0);
|
||||
}
|
||||
|
@ -1232,7 +1233,7 @@ public class XmlConfiguration
|
|||
Object[] obj = new Object[args.length];
|
||||
for (int i = 0; i < args.length; i++)
|
||||
{
|
||||
if (args[i].toLowerCase().endsWith(".properties"))
|
||||
if (args[i].toLowerCase(Locale.ENGLISH).endsWith(".properties"))
|
||||
{
|
||||
properties.load(Resource.newResource(args[i]).getInputStream());
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ public class Dump extends HttpServlet
|
|||
final boolean flush= request.getParameter("flush")!=null?Boolean.parseBoolean(request.getParameter("flush")):false;
|
||||
|
||||
|
||||
if(request.getPathInfo()!=null && request.getPathInfo().toLowerCase().indexOf("script")!=-1)
|
||||
if(request.getPathInfo()!=null && request.getPathInfo().toLowerCase(Locale.ENGLISH).indexOf("script")!=-1)
|
||||
{
|
||||
response.sendRedirect(response.encodeRedirectURL(getServletContext().getContextPath() + "/dump/info"));
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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.server.session;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* SessionExpiryTest
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class SessionExpiryTest extends AbstractSessionExpiryTest
|
||||
{
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionExpiryTest#createServer(int, int, int)
|
||||
*/
|
||||
@Override
|
||||
public AbstractTestServer createServer(int port, int max, int scavenge)
|
||||
{
|
||||
return new JdbcTestServer(port,max,scavenge);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionExpiry() throws Exception
|
||||
{
|
||||
super.testSessionExpiry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionNotExpired() throws Exception
|
||||
{
|
||||
super.testSessionNotExpired();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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.nosql.mongodb;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.eclipse.jetty.client.ContentExchange;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* PurgeInvalidSessionTest
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class PurgeInvalidSessionTest
|
||||
{
|
||||
public MongoTestServer createServer(int port, int max, int scavenge)
|
||||
{
|
||||
MongoTestServer server = new MongoTestServer(port,max,scavenge);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testPurgeInvalidSession() throws Exception
|
||||
{
|
||||
String contextPath = "";
|
||||
String servletMapping = "/server";
|
||||
long purgeDelay = 1000; //1 sec
|
||||
long purgeInvalidAge = 1000; //1 sec
|
||||
long purgeValidAge = 1000;
|
||||
|
||||
//ensure scavenging is turned off so the purger gets a chance to find the session
|
||||
MongoTestServer server = createServer(0, 1, 0);
|
||||
ServletContextHandler context = server.addContext(contextPath);
|
||||
context.addServlet(TestServlet.class, servletMapping);
|
||||
|
||||
MongoSessionManager sessionManager = (MongoSessionManager)context.getSessionHandler().getSessionManager();
|
||||
MongoSessionIdManager idManager = (MongoSessionIdManager)server.getServer().getSessionIdManager();
|
||||
idManager.setPurge(true);
|
||||
idManager.setPurgeDelay(purgeDelay);
|
||||
idManager.setPurgeInvalidAge(purgeInvalidAge); //purge invalid sessions older than
|
||||
idManager.setPurgeValidAge(purgeValidAge); //purge valid sessions older than
|
||||
|
||||
|
||||
|
||||
server.start();
|
||||
int port=server.getPort();
|
||||
try
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
|
||||
client.start();
|
||||
try
|
||||
{
|
||||
//Create a session
|
||||
ContentExchange exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
exchange.setURL("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
client.send(exchange);
|
||||
exchange.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
|
||||
String sessionCookie = exchange.getResponseFields().getStringField("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
||||
//make a request to invalidate the session
|
||||
exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
exchange.setURL("http://localhost:" + port + contextPath + servletMapping + "?action=invalidate");
|
||||
exchange.getRequestFields().add("Cookie", sessionCookie);
|
||||
client.send(exchange);
|
||||
exchange.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
|
||||
|
||||
Thread.currentThread().sleep(3*purgeDelay); //sleep long enough for purger to have run
|
||||
|
||||
//make a request using previous session to test if its still there
|
||||
exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
exchange.setURL("http://localhost:" + port + contextPath + servletMapping + "?action=test");
|
||||
exchange.getRequestFields().add("Cookie", sessionCookie);
|
||||
client.send(exchange);
|
||||
exchange.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class TestServlet extends HttpServlet
|
||||
{
|
||||
DBCollection _sessions;
|
||||
|
||||
|
||||
public TestServlet() throws UnknownHostException, MongoException
|
||||
{
|
||||
super();
|
||||
_sessions = new Mongo().getDB("HttpSessions").getCollection("sessions");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
String action = request.getParameter("action");
|
||||
if ("create".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(true);
|
||||
assertTrue(session.isNew());
|
||||
}
|
||||
else if ("invalidate".equals(action))
|
||||
{
|
||||
HttpSession existingSession = request.getSession(false);
|
||||
assertNotNull(existingSession);
|
||||
existingSession.invalidate();
|
||||
String id = request.getRequestedSessionId();
|
||||
assertNotNull(id);
|
||||
id = id.substring(0, id.indexOf("."));
|
||||
|
||||
//still in db, just marked as invalid
|
||||
DBObject dbSession = _sessions.findOne(new BasicDBObject("id", id));
|
||||
assertTrue(dbSession != null);
|
||||
}
|
||||
else if ("test".equals(action))
|
||||
{
|
||||
String id = request.getRequestedSessionId();
|
||||
assertNotNull(id);
|
||||
id = id.substring(0, id.indexOf("."));
|
||||
|
||||
HttpSession existingSession = request.getSession(false);
|
||||
assertTrue(existingSession == null);
|
||||
|
||||
//not in db any more
|
||||
DBObject dbSession = _sessions.findOne(new BasicDBObject("id", id));
|
||||
assertTrue(dbSession == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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.nosql.mongodb;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.eclipse.jetty.client.ContentExchange;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* PurgeValidSessionTest
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class PurgeValidSessionTest
|
||||
{
|
||||
|
||||
|
||||
|
||||
public MongoTestServer createServer(int port, int max, int scavenge)
|
||||
{
|
||||
MongoTestServer server = new MongoTestServer(port,max,scavenge);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testPurgeValidSession() throws Exception
|
||||
{
|
||||
String contextPath = "";
|
||||
String servletMapping = "/server";
|
||||
long purgeDelay = 1000; //1 sec
|
||||
long purgeValidAge = 1000;
|
||||
|
||||
//ensure scavenging is turned off so the purger gets a chance to find the session
|
||||
MongoTestServer server = createServer(0, 1, 0);
|
||||
ServletContextHandler context = server.addContext(contextPath);
|
||||
context.addServlet(TestServlet.class, servletMapping);
|
||||
|
||||
MongoSessionManager sessionManager = (MongoSessionManager)context.getSessionHandler().getSessionManager();
|
||||
MongoSessionIdManager idManager = (MongoSessionIdManager)server.getServer().getSessionIdManager();
|
||||
idManager.setPurge(true);
|
||||
idManager.setPurgeDelay(purgeDelay);
|
||||
|
||||
idManager.setPurgeValidAge(purgeValidAge); //purge valid sessions older than
|
||||
|
||||
|
||||
|
||||
server.start();
|
||||
int port=server.getPort();
|
||||
try
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
|
||||
client.start();
|
||||
try
|
||||
{
|
||||
//Create a session
|
||||
ContentExchange exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
exchange.setURL("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
client.send(exchange);
|
||||
exchange.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
|
||||
String sessionCookie = exchange.getResponseFields().getStringField("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
||||
|
||||
Thread.currentThread().sleep(3*purgeDelay); //sleep long enough for purger to have run
|
||||
|
||||
//make a request using previous session to test if its still there
|
||||
exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
exchange.setURL("http://localhost:" + port + contextPath + servletMapping + "?action=test");
|
||||
exchange.getRequestFields().add("Cookie", sessionCookie);
|
||||
client.send(exchange);
|
||||
exchange.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class TestServlet extends HttpServlet
|
||||
{
|
||||
DBCollection _sessions;
|
||||
|
||||
|
||||
public TestServlet() throws UnknownHostException, MongoException
|
||||
{
|
||||
super();
|
||||
_sessions = new Mongo().getDB("HttpSessions").getCollection("sessions");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
String action = request.getParameter("action");
|
||||
if ("create".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(true);
|
||||
assertTrue(session.isNew());
|
||||
}
|
||||
else if ("test".equals(action))
|
||||
{
|
||||
String id = request.getRequestedSessionId();
|
||||
assertNotNull(id);
|
||||
id = id.substring(0, id.indexOf("."));
|
||||
|
||||
HttpSession existingSession = request.getSession(false);
|
||||
assertTrue(existingSession == null);
|
||||
|
||||
//not in db any more
|
||||
DBObject dbSession = _sessions.findOne(new BasicDBObject("id", id));
|
||||
assertTrue(dbSession == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -27,10 +27,14 @@ import javax.servlet.http.HttpServlet;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.eclipse.jetty.client.ContentExchange;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -51,7 +55,12 @@ public abstract class AbstractLastAccessTimeTest
|
|||
int maxInactivePeriod = 8;
|
||||
int scavengePeriod = 2;
|
||||
AbstractTestServer server1 = createServer(0, maxInactivePeriod, scavengePeriod);
|
||||
server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
|
||||
TestServlet servlet1 = new TestServlet();
|
||||
ServletHolder holder1 = new ServletHolder(servlet1);
|
||||
ServletContextHandler context = server1.addContext(contextPath);
|
||||
TestSessionListener listener1 = new TestSessionListener();
|
||||
context.addEventListener(listener1);
|
||||
context.addServlet(holder1, servletMapping);
|
||||
server1.start();
|
||||
int port1=server1.getPort();
|
||||
try
|
||||
|
@ -108,17 +117,9 @@ public abstract class AbstractLastAccessTimeTest
|
|||
// Let's wait for the scavenger to run, waiting 2.5 times the scavenger period
|
||||
Thread.sleep(scavengePeriod * 2500L);
|
||||
|
||||
// Access again server1, and ensure that we can still access the session
|
||||
exchange1 = new ContentExchange(true);
|
||||
exchange1.setMethod(HttpMethods.GET);
|
||||
exchange1.setURL("http://localhost:" + port1 + contextPath + servletMapping);
|
||||
exchange1.getRequestFields().add("Cookie", sessionCookie);
|
||||
client.send(exchange1);
|
||||
exchange1.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK, exchange1.getResponseStatus());
|
||||
//test that the session was kept alive by server 2 and still contains what server1 put in it
|
||||
assertEquals("test", exchange1.getResponseContent());
|
||||
|
||||
//check that the session was not scavenged over on server1 by ensuring that the SessionListener destroy method wasn't called
|
||||
assertTrue (listener1.destroyed == false);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -136,6 +137,25 @@ public abstract class AbstractLastAccessTimeTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class TestSessionListener implements HttpSessionListener
|
||||
{
|
||||
public boolean destroyed = false;
|
||||
public boolean created = false;
|
||||
|
||||
|
||||
public void sessionDestroyed(HttpSessionEvent se)
|
||||
{
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
|
||||
public void sessionCreated(HttpSessionEvent se)
|
||||
{
|
||||
created = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 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.server.session;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.eclipse.jetty.client.ContentExchange;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.eclipse.jetty.server.session.AbstractTestServer;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* AbstractSessionExpiryTest
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractSessionExpiryTest
|
||||
{
|
||||
public abstract AbstractTestServer createServer(int port, int max, int scavenge);
|
||||
|
||||
public void pause(int scavengePeriod)
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(scavengePeriod * 2500L);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionNotExpired() throws Exception
|
||||
{
|
||||
String contextPath = "";
|
||||
String servletMapping = "/server";
|
||||
int inactivePeriod = 10;
|
||||
int scavengePeriod = 10;
|
||||
AbstractTestServer server1 = createServer(0, inactivePeriod, scavengePeriod);
|
||||
TestServlet servlet = new TestServlet();
|
||||
ServletHolder holder = new ServletHolder(servlet);
|
||||
server1.addContext(contextPath).addServlet(holder, servletMapping);
|
||||
server1.start();
|
||||
int port1 = server1.getPort();
|
||||
|
||||
try
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
|
||||
client.start();
|
||||
String url = "http://localhost:" + port1 + contextPath + servletMapping;
|
||||
|
||||
//make a request to set up a session on the server
|
||||
ContentExchange exchange1 = new ContentExchange(true);
|
||||
exchange1.setMethod(HttpMethods.GET);
|
||||
exchange1.setURL(url + "?action=init");
|
||||
client.send(exchange1);
|
||||
exchange1.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange1.getResponseStatus());
|
||||
String sessionCookie = exchange1.getResponseFields().getStringField("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
||||
//now stop the server
|
||||
server1.stop();
|
||||
|
||||
//start the server again, before the session times out
|
||||
server1.start();
|
||||
port1 = server1.getPort();
|
||||
url = "http://localhost:" + port1 + contextPath + servletMapping;
|
||||
|
||||
//make another request, the session should not have expired
|
||||
ContentExchange exchange2 = new ContentExchange(true);
|
||||
exchange2.setMethod(HttpMethods.GET);
|
||||
exchange2.setURL(url + "?action=notexpired");
|
||||
exchange2.getRequestFields().add("Cookie", sessionCookie);
|
||||
client.send(exchange2);
|
||||
exchange2.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange2.getResponseStatus());
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
server1.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionExpiry() throws Exception
|
||||
{
|
||||
String contextPath = "";
|
||||
String servletMapping = "/server";
|
||||
int inactivePeriod = 2;
|
||||
int scavengePeriod = 10;
|
||||
AbstractTestServer server1 = createServer(0, inactivePeriod, scavengePeriod);
|
||||
TestServlet servlet = new TestServlet();
|
||||
ServletHolder holder = new ServletHolder(servlet);
|
||||
server1.addContext(contextPath).addServlet(holder, servletMapping);
|
||||
server1.start();
|
||||
int port1 = server1.getPort();
|
||||
|
||||
try
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
|
||||
client.start();
|
||||
String url = "http://localhost:" + port1 + contextPath + servletMapping;
|
||||
|
||||
//make a request to set up a session on the server
|
||||
ContentExchange exchange1 = new ContentExchange(true);
|
||||
exchange1.setMethod(HttpMethods.GET);
|
||||
exchange1.setURL(url + "?action=init");
|
||||
client.send(exchange1);
|
||||
exchange1.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange1.getResponseStatus());
|
||||
String sessionCookie = exchange1.getResponseFields().getStringField("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
||||
//now stop the server
|
||||
server1.stop();
|
||||
|
||||
//and wait until the expiry time has passed
|
||||
pause(inactivePeriod);
|
||||
|
||||
//restart the server
|
||||
server1.start();
|
||||
port1 = server1.getPort();
|
||||
url = "http://localhost:" + port1 + contextPath + servletMapping;
|
||||
|
||||
//make another request, the session should have expired
|
||||
ContentExchange exchange2 = new ContentExchange(true);
|
||||
exchange2.setMethod(HttpMethods.GET);
|
||||
exchange2.setURL(url + "?action=test");
|
||||
exchange2.getRequestFields().add("Cookie", sessionCookie);
|
||||
client.send(exchange2);
|
||||
exchange2.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange2.getResponseStatus());
|
||||
}
|
||||
finally
|
||||
{
|
||||
server1.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestServlet extends HttpServlet
|
||||
{
|
||||
public String originalId = null;
|
||||
public String testId = null;
|
||||
public String checkId = null;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
|
||||
{
|
||||
String action = request.getParameter("action");
|
||||
if ("init".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(true);
|
||||
session.setAttribute("test", "test");
|
||||
originalId = session.getId();
|
||||
}
|
||||
else if ("test".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(true);
|
||||
assertTrue(session != null);
|
||||
assertTrue(!originalId.equals(session.getId()));
|
||||
}
|
||||
else if ("notexpired".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(false);
|
||||
assertTrue(session != null);
|
||||
assertTrue(originalId.equals(session.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue