diff --git a/VERSION.txt b/VERSION.txt index 95f45237a37..e2844da62d8 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -43,6 +43,17 @@ jetty-8.1.0.RC0 - 30 November 2011 + 364283 can't parse the servlet multipart-config for the web.xml + 364430 Support web.xml enabled state for servlets +jetty-7.6.0.RC3 - 05 January 2012 + + 367433 added tests to investigate + + 367435 improved D00 test harness + + 367485 HttpExchange canceled before response do not release connection. + + 367502 WebSocket connections should be closed when application context is + stopped. + + 367591 corrected configuration.xml version to 7.6 + + 367635 Added support for start.d directory + + 637638 limit number of form parameters to avoid DOS + + JETTY-1467 close half closed when idle + jetty-7.6.0.RC2 - 22 December 2011 + 364638 HttpParser closes if data received while seeking EOF. Tests fixed to cope diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java index a032b38b17b..51a4b53560c 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java @@ -180,20 +180,23 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen String method=_exchange.getMethod(); String uri = _exchange.getRequestURI(); - if (_destination.isProxied() && !HttpMethods.CONNECT.equals(method) && uri.startsWith("/")) + if (_destination.isProxied()) { - boolean secure = _destination.isSecure(); - String host = _destination.getAddress().getHost(); - int port = _destination.getAddress().getPort(); - StringBuilder absoluteURI = new StringBuilder(); - absoluteURI.append(secure ? HttpSchemes.HTTPS : HttpSchemes.HTTP); - absoluteURI.append("://"); - absoluteURI.append(host); - // Avoid adding default ports - if (!(secure && port == 443 || !secure && port == 80)) - absoluteURI.append(":").append(port); - absoluteURI.append(uri); - uri = absoluteURI.toString(); + if (!HttpMethods.CONNECT.equals(method) && uri.startsWith("/")) + { + boolean secure = _destination.isSecure(); + String host = _destination.getAddress().getHost(); + int port = _destination.getAddress().getPort(); + StringBuilder absoluteURI = new StringBuilder(); + absoluteURI.append(secure ? HttpSchemes.HTTPS : HttpSchemes.HTTP); + absoluteURI.append("://"); + absoluteURI.append(host); + // Avoid adding default ports + if (!(secure && port == 443 || !secure && port == 80)) + absoluteURI.append(":").append(port); + absoluteURI.append(uri); + uri = absoluteURI.toString(); + } Authentication auth = _destination.getProxyAuthentication(); if (auth != null) auth.setCredentials(_exchange); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpsProxyAuthenticationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpsProxyAuthenticationTest.java new file mode 100644 index 00000000000..e04f93875e0 --- /dev/null +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpsProxyAuthenticationTest.java @@ -0,0 +1,118 @@ +// ======================================================================== +// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== + +package org.eclipse.jetty.client; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.client.security.Authentication; +import org.eclipse.jetty.client.security.BasicAuthentication; +import org.eclipse.jetty.client.security.Realm; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.ConnectHandler; +import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + +public class HttpsProxyAuthenticationTest +{ + private Server _proxy = new Server(); + private HttpClient _client = new HttpClient(); + private boolean authHandlerSend; + + @Before + public void init() throws Exception + { + SelectChannelConnector connector = new SelectChannelConnector(); + _proxy.addConnector(connector); + _proxy.setHandler(new ConnectHandler() + { + @Override + protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException + { + String authHeader = request.getHeader("Authorization"); + if (authHeader != null && authHeader.length() > 0) + authHandlerSend = true; + return super.handleAuthentication(request,response,address); + } + }); + _proxy.start(); + int proxyPort = connector.getLocalPort(); + + Authentication authentication = new BasicAuthentication(new Realm() + { + public String getId() + { + return "MyRealm"; + } + + public String getPrincipal() + { + return "jetty"; + } + + public String getCredentials() + { + return "jetty"; + } + }); + + _client.setProxy(new Address("localhost", proxyPort)); + _client.setProxyAuthentication(authentication); + _client.start(); + } + + @After + public void destroy() throws Exception + { + _client.stop(); + _proxy.stop(); + _proxy.join(); + } + + @Test + public void httpsViaProxyThatReturns504ErrorTest() throws Exception + { + // Assume that we can connect to google + String host = "google.com"; + int port = 443; + Socket socket = new Socket(); + try + { + socket.connect(new InetSocketAddress(host, port), 1000); + } + catch (IOException x) + { + Assume.assumeNoException(x); + } + finally + { + socket.close(); + } + + HttpExchange exchange = new ContentExchange(); + exchange.setURL("https://" + host + ":" + port); + exchange.addRequestHeader("behaviour", "google"); + _client.send(exchange); + Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); + Assert.assertTrue("Authorization header not set!", authHandlerSend); + } +} diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderRuntimeUpdatesTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderRuntimeUpdatesTest.java index d0611fa6923..f2535c20d33 100644 --- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderRuntimeUpdatesTest.java +++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderRuntimeUpdatesTest.java @@ -111,6 +111,7 @@ public class ScanningAppProviderRuntimeUpdatesTest jetty.copyWebapp("foo-webapp-1.war","foo.war"); jetty.copyContext("foo.xml","foo.xml"); + waitForDirectoryScan(); waitForDirectoryScan(); jetty.assertWebAppContextsExists("/foo"); @@ -125,12 +126,14 @@ public class ScanningAppProviderRuntimeUpdatesTest jetty.copyWebapp("foo-webapp-1.war","foo.war"); jetty.copyContext("foo.xml","foo.xml"); + waitForDirectoryScan(); waitForDirectoryScan(); jetty.assertWebAppContextsExists("/foo"); jetty.removeContext("foo.xml"); + waitForDirectoryScan(); waitForDirectoryScan(); // FIXME: hot undeploy with removal not working! - jetty.assertNoWebAppContexts(); @@ -151,6 +154,7 @@ public class ScanningAppProviderRuntimeUpdatesTest jetty.copyWebapp("foo-webapp-1.war","foo.war"); jetty.copyContext("foo.xml","foo.xml"); + waitForDirectoryScan(); waitForDirectoryScan(); jetty.assertWebAppContextsExists("/foo"); @@ -165,6 +169,7 @@ public class ScanningAppProviderRuntimeUpdatesTest // This should result in the existing foo.war being replaced with the new foo.war waitForDirectoryScan(); + waitForDirectoryScan(); jetty.assertWebAppContextsExists("/foo"); // Test that webapp response contains "-2" diff --git a/jetty-http-spi/pom.xml b/jetty-http-spi/pom.xml index 2842860f0c3..2366b919f61 100644 --- a/jetty-http-spi/pom.xml +++ b/jetty-http-spi/pom.xml @@ -31,6 +31,14 @@ + + maven-compiler-plugin + + 1.6 + 1.6 + false + + org.apache.felix maven-bundle-plugin diff --git a/jetty-http/pom.xml b/jetty-http/pom.xml index a14d46f59ed..8ba8890dd01 100644 --- a/jetty-http/pom.xml +++ b/jetty-http/pom.xml @@ -5,7 +5,6 @@ 8.1.0-SNAPSHOT 4.0.0 - org.eclipse.jetty jetty-http Jetty :: Http Utility diff --git a/jetty-io/pom.xml b/jetty-io/pom.xml index 43c64437ad4..386f0643ffc 100644 --- a/jetty-io/pom.xml +++ b/jetty-io/pom.xml @@ -5,7 +5,6 @@ 8.1.0-SNAPSHOT 4.0.0 - org.eclipse.jetty jetty-io Jetty :: IO Utility diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java index dbdb0b4a840..526f53a0101 100644 --- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java +++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java @@ -42,36 +42,38 @@ import org.eclipse.jetty.server.Authentication.User; public class JaspiAuthenticator implements Authenticator { private final ServerAuthConfig _authConfig; + private final Map _authProperties; + private final ServletCallbackHandler _callbackHandler; + private final Subject _serviceSubject; + private final boolean _allowLazyAuthentication; + private final IdentityService _identityService; + private final DeferredAuthentication _deferred; - public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler, - Subject serviceSubject, boolean allowLazyAuthentication, IdentityService identityService) + public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler, Subject serviceSubject, + boolean allowLazyAuthentication, IdentityService identityService) { // TODO maybe pass this in via setConfiguration ? - if (callbackHandler == null) - throw new NullPointerException("No CallbackHandler"); - if (authConfig == null) - throw new NullPointerException("No AuthConfig"); + if (callbackHandler == null) throw new NullPointerException("No CallbackHandler"); + if (authConfig == null) throw new NullPointerException("No AuthConfig"); this._authConfig = authConfig; this._authProperties = authProperties; this._callbackHandler = callbackHandler; this._serviceSubject = serviceSubject; this._allowLazyAuthentication = allowLazyAuthentication; this._identityService = identityService; - this._deferred=new DeferredAuthentication(this); + this._deferred = new DeferredAuthentication(this); } - public void setConfiguration(AuthConfiguration configuration) { } - - + public String getAuthMethod() { return "JASPI"; @@ -79,56 +81,71 @@ public class JaspiAuthenticator implements Authenticator public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException { - if (_allowLazyAuthentication && !mandatory) - return _deferred; - + System.err.println("\nJaspiAuthenticator.validateRequest, uri=" + ((javax.servlet.http.HttpServletRequest) request).getRequestURI() + + " lazy=" + + _allowLazyAuthentication + + " mandatory=" + + mandatory); + new Throwable().printStackTrace(); + JaspiMessageInfo info = new JaspiMessageInfo(request, response, mandatory); - request.setAttribute("org.eclipse.jetty.security.jaspi.info",info); - return validateRequest(info); + request.setAttribute("org.eclipse.jetty.security.jaspi.info", info); + + Authentication a = validateRequest(info); + + //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; + + System.err.println("JaspiAuthenticator.validateRequest returning "+a); + return a; } // most likely validatedUser is not needed here. public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException { - JaspiMessageInfo info = (JaspiMessageInfo)req.getAttribute("org.eclipse.jetty.security.jaspi.info"); - if (info==null) throw new NullPointerException("MeesageInfo from request missing: " + req); - return secureResponse(info,validatedUser); + System.err.println("JaspiAuthenticator.secureResponse uri=" + ((javax.servlet.http.HttpServletRequest) req).getRequestURI()); + + JaspiMessageInfo info = (JaspiMessageInfo) req.getAttribute("org.eclipse.jetty.security.jaspi.info"); + if (info == null) throw new NullPointerException("MessageInfo from request missing: " + req); + return secureResponse(info, validatedUser); } - + + public Authentication validateRequest(JaspiMessageInfo messageInfo) throws ServerAuthException { try { + System.err.println("jaspAuthenticator.validateRequest(info)"); String authContextId = _authConfig.getAuthContextID(messageInfo); - ServerAuthContext authContext = _authConfig.getAuthContext(authContextId,_serviceSubject,_authProperties); + ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties); Subject clientSubject = new Subject(); - AuthStatus authStatus = authContext.validateRequest(messageInfo,clientSubject,_serviceSubject); -// String authMethod = (String)messageInfo.getMap().get(JaspiMessageInfo.AUTH_METHOD_KEY); + AuthStatus authStatus = authContext.validateRequest(messageInfo, clientSubject, _serviceSubject); + // String authMethod = + // (String)messageInfo.getMap().get(JaspiMessageInfo.AUTH_METHOD_KEY); + + if (authStatus == AuthStatus.SEND_CONTINUE) return Authentication.SEND_CONTINUE; + if (authStatus == AuthStatus.SEND_FAILURE) return Authentication.SEND_FAILURE; - if (authStatus == AuthStatus.SEND_CONTINUE) - return Authentication.SEND_CONTINUE; - if (authStatus == AuthStatus.SEND_FAILURE) - return Authentication.SEND_FAILURE; - if (authStatus == AuthStatus.SUCCESS) { - Set ids = clientSubject.getPrivateCredentials(UserIdentity.class); + Set ids = clientSubject.getPrivateCredentials(UserIdentity.class); UserIdentity userIdentity; if (ids.size() > 0) { userIdentity = ids.iterator().next(); - } else { + } + else + { CallerPrincipalCallback principalCallback = _callbackHandler.getThreadCallerPrincipalCallback(); - if (principalCallback == null) - { - return Authentication.UNAUTHENTICATED; - } + if (principalCallback == null) { return Authentication.UNAUTHENTICATED; } Principal principal = principalCallback.getPrincipal(); - if (principal == null) { + if (principal == null) + { String principalName = principalCallback.getName(); Set principals = principalCallback.getSubject().getPrincipals(); - for (Principal p: principals) + for (Principal p : principals) { if (p.getName().equals(principalName)) { @@ -136,10 +153,7 @@ public class JaspiAuthenticator implements Authenticator break; } } - if (principal == null) - { - return Authentication.UNAUTHENTICATED; - } + if (principal == null) { return Authentication.UNAUTHENTICATED; } } GroupPrincipalCallback groupPrincipalCallback = _callbackHandler.getThreadGroupPrincipalCallback(); String[] groups = groupPrincipalCallback == null ? null : groupPrincipalCallback.getGroups(); @@ -149,10 +163,10 @@ public class JaspiAuthenticator implements Authenticator } if (authStatus == AuthStatus.SEND_SUCCESS) { - //we are processing a message in a secureResponse dialog. + // we are processing a message in a secureResponse dialog. return Authentication.SEND_SUCCESS; } - //should not happen + // should not happen throw new NullPointerException("No AuthStatus returned"); } catch (AuthException e) @@ -166,13 +180,16 @@ public class JaspiAuthenticator implements Authenticator try { String authContextId = _authConfig.getAuthContextID(messageInfo); - ServerAuthContext authContext = _authConfig.getAuthContext(authContextId,_serviceSubject,_authProperties); - // TODO authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject()); - AuthStatus status = authContext.secureResponse(messageInfo,_serviceSubject); + ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties); + // TODO + // authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject()); + AuthStatus status = authContext.secureResponse(messageInfo, _serviceSubject); return (AuthStatus.SEND_SUCCESS.equals(status)); } catch (AuthException e) { + System.err.println("Error in JaspiAuthenticator.secureResponse"); + e.printStackTrace(); throw new ServerAuthException(e); } } diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticatorFactory.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticatorFactory.java index 35015090fb8..c645ffa85a2 100644 --- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticatorFactory.java +++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticatorFactory.java @@ -98,9 +98,13 @@ public class JaspiAuthenticatorFactory extends DefaultAuthenticatorFactory Subject serviceSubject=findServiceSubject(server); String serverName=findServerName(server,serviceSubject); + System.err.println("authconfigfactory="+authConfigFactory+" serviceSubject="+serviceSubject+" serverName="+serverName); String appContext = serverName + " " + context.getContextPath(); + + System.err.println("appcontext="+appContext); AuthConfigProvider authConfigProvider = authConfigFactory.getConfigProvider(MESSAGE_LAYER,appContext,listener); + System.err.println("authconfigProvider="+authConfigProvider); if (authConfigProvider != null) { ServletCallbackHandler servletCallbackHandler = new ServletCallbackHandler(loginService); diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/ServletCallbackHandler.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/ServletCallbackHandler.java index d11a8d9bc84..44dbda13e3b 100644 --- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/ServletCallbackHandler.java +++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/ServletCallbackHandler.java @@ -90,8 +90,9 @@ public class ServletCallbackHandler implements CallbackHandler if (user!=null) { + loginCallback.setUserPrincipal(user.getUserPrincipal()); + credentialValidationCallback.getSubject().getPrivateCredentials().add(loginCallback); credentialValidationCallback.setResult(true); - credentialValidationCallback.getSubject().getPrincipals().addAll(user.getSubject().getPrincipals()); credentialValidationCallback.getSubject().getPrivateCredentials().add(user); } diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/BaseAuthModule.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/BaseAuthModule.java index ef05821b8a5..4eb1ad6e256 100644 --- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/BaseAuthModule.java +++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/BaseAuthModule.java @@ -90,12 +90,12 @@ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException { // servlets do not need secured responses - return AuthStatus.SUCCESS; + return AuthStatus.SEND_SUCCESS; } public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { - return AuthStatus.FAILURE; + return AuthStatus.SEND_FAILURE; } /** @@ -131,6 +131,7 @@ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext if (credValidationCallback.getResult()) { Set loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class); + System.err.println("LoginCallbackImpls.isEmpty="+loginCallbacks.isEmpty()); if (!loginCallbacks.isEmpty()) { LoginCallbackImpl loginCallback = loginCallbacks.iterator().next(); diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java index bd2cfaf1de2..be390555742 100644 --- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java +++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java @@ -36,7 +36,9 @@ import javax.servlet.http.HttpSessionBindingListener; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.security.Password; import org.eclipse.jetty.security.CrossContextPsuedoSession; +import org.eclipse.jetty.security.authentication.DeferredAuthentication; import org.eclipse.jetty.security.authentication.LoginCallbackImpl; +import org.eclipse.jetty.server.Authentication; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.log.Log; @@ -146,37 +148,50 @@ public class FormAuthModule extends BaseAuthModule @Override public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { + HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage(); HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage(); - HttpSession session = request.getSession(isMandatory(messageInfo)); - String uri = request.getPathInfo(); - // not mandatory and not authenticated - if (session == null || isLoginOrErrorPage(uri)) return AuthStatus.SUCCESS; + String uri = request.getRequestURI(); + if (uri==null) + uri=URIUtil.SLASH; + + boolean mandatory = isMandatory(messageInfo); + mandatory |= isJSecurityCheck(uri); + HttpSession session = request.getSession(mandatory); + + System.err.println("FormAuthModule.validateRequest(info,subject,serviceSubject) for uri="+uri+" mandatory="+mandatory+" isLoginOrError="+isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()))); + + // not mandatory or its the login or login error page don't authenticate + if (!mandatory || isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()))) return AuthStatus.SUCCESS; try { // Handle a request for authentication. - // TODO perhaps j_securitycheck can be uri suffix? - if (uri.endsWith(__J_SECURITY_CHECK)) + if (isJSecurityCheck(uri)) { - final String username = request.getParameter(__J_USERNAME); final String password = request.getParameter(__J_PASSWORD); + System.err.println("Try login username="+username+" password="+password); boolean success = tryLogin(messageInfo, clientSubject, response, session, username, new Password(password)); if (success) { - // Redirect to original request - String nuri = (String) session.getAttribute(__J_URI); + // Redirect to original request + String nuri=null; + synchronized(session) + { + nuri = (String) session.getAttribute(__J_URI); + } + if (nuri == null || nuri.length() == 0) { nuri = request.getContextPath(); - if (nuri.length() == 0) nuri = URIUtil.SLASH; + if (nuri.length() == 0) + nuri = URIUtil.SLASH; } - session.removeAttribute(__J_URI); // Remove popped return - // URI. - response.setContentLength(0); + + System.err.println("FormAuthModule succesful login, sending redirect to "+nuri); + response.setContentLength(0); response.sendRedirect(response.encodeRedirectURL(nuri)); - return AuthStatus.SEND_CONTINUE; } // not authenticated @@ -194,95 +209,18 @@ public class FormAuthModule extends BaseAuthModule // that occur? return AuthStatus.SEND_FAILURE; } + + // Check if the session is already authenticated. FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED); - if (form_cred != null) { + System.err.println("Form cred: form.username="+form_cred._jUserName+" form.pwd="+new String(form_cred._jPassword)); + + //TODO: we would like the form auth module to be able to invoke the loginservice.validate() method to check the previously authed user + boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword))); if (success) { return AuthStatus.SUCCESS; } - // CallbackHandler loginCallbackHandler = new - // UserPasswordCallbackHandler(form_cred._jUserName, - // form_cred._jPassword); - // LoginResult loginResult = loginService.login(clientSubject, - // loginCallbackHandler); - // //TODO what should happen if !isMandatory but credentials - // exist and are wrong? - // if (loginResult.isSuccess()) - // { - // callbackHandler.handle(new - // Callback[]{loginResult.getCallerPrincipalCallback(), - // loginResult.getGroupPrincipalCallback()}); - // messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY, - // Constraint.__FORM_AUTH); - // - // form_cred = new FormCredential(form_cred._jUserName, - // form_cred._jPassword, - // loginResult.getCallerPrincipalCallback().getPrincipal()); - // - // session.setAttribute(__J_AUTHENTICATED, form_cred); - // if (ssoSource != null && ssoSource.fetch(request) == null) - // { - // UserInfo userInfo = new UserInfo(form_cred._jUserName, - // form_cred._jPassword); - // ssoSource.store(userInfo, response); - // } - // messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY, - // Constraint.__FORM_AUTH); - // return AuthStatus.SUCCESS; - // } - - // // We have a form credential. Has it been distributed? - // if (form_cred._userPrincipal==null) - // { - // // This form_cred appears to have been distributed. Need to - // reauth - // form_cred.authenticate(realm, request); - // - // // Sign-on to SSO mechanism - // if (form_cred._userPrincipal!=null && realm instanceof - // SSORealm) - // ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new - // Password(form_cred._jPassword)); - // - // } - // else if (!realm.reauthenticate(form_cred._userPrincipal)) - // // Else check that it is still authenticated. - // form_cred._userPrincipal=null; - // - // // If this credential is still authenticated - // if (form_cred._userPrincipal!=null) - // { - // if(LOG.isDebugEnabled())LOG.debug("FORM Authenticated for - // "+form_cred._userPrincipal.getName()); - // request.setAuthType(Constraint.__FORM_AUTH); - // //jaspi - // // request.setUserPrincipal(form_cred._userPrincipal); - // return form_cred._userPrincipal; - // } - // else - // session.setAttribute(__J_AUTHENTICATED,null); - // } - // else if (realm instanceof SSORealm) - // { - // // Try a single sign on. - // Credential cred = - // ((SSORealm)realm).getSingleSignOn(request,response); - // - // if (request.getUserPrincipal()!=null) - // { - // form_cred=new FormCredential(); - // form_cred._userPrincipal=request.getUserPrincipal(); - // form_cred._jUserName=form_cred._userPrincipal.getName(); - // if (cred!=null) - // form_cred._jPassword=cred.toString(); - // if(LOG.isDebugEnabled())LOG.debug("SSO for - // "+form_cred._userPrincipal); - // - // request.setAuthType(Constraint.__FORM_AUTH); - // session.setAttribute(__J_AUTHENTICATED,form_cred); - // return form_cred._userPrincipal; - // } } else if (ssoSource != null) { @@ -293,19 +231,25 @@ public class FormAuthModule extends BaseAuthModule if (success) { return AuthStatus.SUCCESS; } } } + + - // Don't authenticate authform or errorpage - if (!isMandatory(messageInfo) || isLoginOrErrorPage(uri)) - // TODO verify this is correct action - return AuthStatus.SUCCESS; + // if we can't send challenge + if (DeferredAuthentication.isDeferred(response)) + return AuthStatus.SUCCESS; + - // redirect to login page - if (request.getQueryString() != null) uri += "?" + request.getQueryString(); - session.setAttribute(__J_URI, request.getScheme() + "://" - + request.getServerName() - + ":" - + request.getServerPort() - + URIUtil.addPaths(request.getContextPath(), uri)); + // redirect to login page + StringBuffer buf = request.getRequestURL(); + if (request.getQueryString() != null) + buf.append("?").append(request.getQueryString()); + + synchronized (session) + { + session.setAttribute(__J_URI, buf.toString()); + } + + System.err.println("Redirecting to login page "+_formLoginPage+" and remembering juri="+buf.toString()); response.setContentLength(0); response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), _formLoginPage))); return AuthStatus.SEND_CONTINUE; @@ -320,6 +264,20 @@ public class FormAuthModule extends BaseAuthModule } } + + /* ------------------------------------------------------------ */ + public boolean isJSecurityCheck(String uri) + { + int jsc = uri.indexOf(__J_SECURITY_CHECK); + + if (jsc<0) + return false; + int e=jsc+__J_SECURITY_CHECK.length(); + if (e==uri.length()) + return true; + char c = uri.charAt(e); + return c==';'||c=='#'||c=='/'||c=='?'; + } private boolean tryLogin(MessageInfo messageInfo, Subject clientSubject, HttpServletResponse response, HttpSession session, @@ -330,10 +288,11 @@ public class FormAuthModule extends BaseAuthModule { char[] pwdChars = password.toString().toCharArray(); Set loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class); + System.err.println("FormAuthModule, LoginCallbackImpl.isEmpty="+loginCallbacks.isEmpty()); if (!loginCallbacks.isEmpty()) { LoginCallbackImpl loginCallback = loginCallbacks.iterator().next(); - FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal()); + FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal(), loginCallback.getSubject()); session.setAttribute(__J_AUTHENTICATED, form_cred); } @@ -347,38 +306,11 @@ public class FormAuthModule extends BaseAuthModule return true; } return false; - // LoginCallback loginCallback = new LoginCallback(clientSubject, - // username, password); - // loginService.login(loginCallback); - // if (loginCallback.isSuccess()) - // { - // CallerPrincipalCallback callerPrincipalCallback = new - // CallerPrincipalCallback(clientSubject, - // loginCallback.getUserPrincipal()); - // GroupPrincipalCallback groupPrincipalCallback = new - // GroupPrincipalCallback(clientSubject, - // loginCallback.getGroups().toArray(new - // String[loginCallback.getGroups().size()])); - // callbackHandler.handle(new Callback[] {callerPrincipalCallback, - // groupPrincipalCallback}); - // messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY, - // Constraint.__FORM_AUTH); - // FormCredential form_cred = new FormCredential(username, password, - // loginCallback.getUserPrincipal()); - // - // session.setAttribute(__J_AUTHENTICATED, form_cred); - // // Sign-on to SSO mechanism - // if (ssoSource != null) - // { - // UserInfo userInfo = new UserInfo(username, password); - // ssoSource.store(userInfo, response); - // } - // } - // return loginCallback.isSuccess(); } public boolean isLoginOrErrorPage(String pathInContext) { + System.err.println("ISLOGINORERRORPAGE? "+pathInContext+" error: "+_formErrorPath+" login:"+_formLoginPath); return pathInContext != null && (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath)); } @@ -393,12 +325,15 @@ public class FormAuthModule extends BaseAuthModule char[] _jPassword; transient Principal _userPrincipal; + + transient Subject _subject; - private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal) + private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal, Subject subject) { this._jUserName = _jUserName; this._jPassword = _jPassword; this._userPrincipal = _userPrincipal; + this._subject = subject; } public void valueBound(HttpSessionBindingEvent event) diff --git a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml index 2c669d7db2b..c9fc409025a 100644 --- a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml +++ b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml @@ -6,7 +6,6 @@ ../pom.xml 4.0.0 - org.eclipse.jetty.osgi jetty-osgi-boot-jsp Jetty :: OSGi :: Boot JSP Jetty OSGi Boot JSP bundle diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml index 4b305bb0442..166e6e84301 100644 --- a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml +++ b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml @@ -6,7 +6,6 @@ ../pom.xml 4.0.0 - org.eclipse.jetty.osgi jetty-osgi-boot-warurl Jetty :: OSGi :: Boot :: Warurl Jetty OSGi Boot-Warurl bundle diff --git a/jetty-osgi/jetty-osgi-boot/pom.xml b/jetty-osgi/jetty-osgi-boot/pom.xml index 75a036f115b..d4da8bff3a7 100644 --- a/jetty-osgi/jetty-osgi-boot/pom.xml +++ b/jetty-osgi/jetty-osgi-boot/pom.xml @@ -6,7 +6,6 @@ ../pom.xml 4.0.0 - org.eclipse.jetty.osgi jetty-osgi-boot Jetty :: OSGi :: Boot Jetty OSGi Boot bundle diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml b/jetty-osgi/jetty-osgi-httpservice/pom.xml index 78eaf0210c8..09c81789bd9 100644 --- a/jetty-osgi/jetty-osgi-httpservice/pom.xml +++ b/jetty-osgi/jetty-osgi-httpservice/pom.xml @@ -6,7 +6,6 @@ ../pom.xml 4.0.0 - org.eclipse.jetty.osgi jetty-httpservice Jetty :: OSGi :: HttpService Jetty OSGi HttpService bundle diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml index 0957d141b57..defad09512e 100644 --- a/jetty-osgi/test-jetty-osgi/pom.xml +++ b/jetty-osgi/test-jetty-osgi/pom.xml @@ -6,7 +6,6 @@ ../pom.xml 4.0.0 - org.eclipse.jetty.osgi test-jetty-osgi Jetty :: OSGi :: Test Jetty OSGi Integration test diff --git a/jetty-policy/pom.xml b/jetty-policy/pom.xml index 568369662c9..8d4e9cc51ae 100644 --- a/jetty-policy/pom.xml +++ b/jetty-policy/pom.xml @@ -5,7 +5,6 @@ jetty-project 8.1.0-SNAPSHOT - org.eclipse.jetty jetty-policy Jetty :: Policy Tool jar diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java index 5878381ec2e..6a4b837783f 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java @@ -318,11 +318,13 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti if (!_loginServiceShared && _loginService instanceof LifeCycle) ((LifeCycle)_loginService).start(); + System.err.println("authenticator="+_authenticator+" authenticatorFactory="+_authenticatorFactory+" identityService="+_identityService); if (_authenticator==null && _authenticatorFactory!=null && _identityService!=null) { _authenticator=_authenticatorFactory.getAuthenticator(getServer(),ContextHandler.getCurrentContext(),this, _identityService, _loginService); if (_authenticator!=null) _authMethod=_authenticator.getAuthMethod(); + System.err.println("Called auth factory, authenticator="+_authenticator); } if (_authenticator==null) @@ -477,7 +479,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti deferred.setIdentityService(_identityService); deferred.setLoginService(_loginService); baseRequest.setAuthentication(authentication); - +System.err.println("uri="+baseRequest.getUri()+" Auth is deferred"); try { handler.handle(pathInContext, baseRequest, request, response); @@ -487,7 +489,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti previousIdentity = deferred.getPreviousAssociation(); deferred.setIdentityService(null); } - + System.err.println("Securityhandler calling secureResponse, for Authentication.User"); Authentication auth=baseRequest.getAuthentication(); if (auth instanceof Authentication.User) { diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java index 2ec515ca6a7..bab7e9b0ba5 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java @@ -169,7 +169,7 @@ public class DeferredAuthentication implements Authentication.Deferred * @param response * @return true if this response is from a deferred call to {@link #authenticate(ServletRequest)} */ - public boolean isDeferred(HttpServletResponse response) + public static boolean isDeferred(HttpServletResponse response) { return response==__deferredResponse; } @@ -177,7 +177,7 @@ public class DeferredAuthentication implements Authentication.Deferred /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ - static HttpServletResponse __deferredResponse = new HttpServletResponse() + final static HttpServletResponse __deferredResponse = new HttpServletResponse() { public void addCookie(Cookie cookie) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java index d3ee90c6415..a06ef9ef2df 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java @@ -216,9 +216,6 @@ public class AsyncContinuation implements AsyncContext, Continuation } /* ------------------------------------------------------------ */ - /* (non-Javadoc) - * @see javax.servlet.ServletRequest#isSuspended() - */ public boolean isSuspending() { synchronized(this) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java index 1ddedf015aa..59e66626e69 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java @@ -126,10 +126,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async } else if (_request.getAsyncContinuation().isAsyncStarted()) { - // The request is suspended, so even though progress has been made, break the while loop + // The request is suspended, so even though progress has been made, + // exit the while loop by setting progress to false LOG.debug("suspended {}",this); - // TODO: breaking inside finally blocks is bad: rethink how we should exit from here - break; + progress=false; } } } @@ -139,16 +139,19 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async setCurrentConnection(null); // If we are not suspended - if (!_request.isAsyncStarted()) + if (!_request.getAsyncContinuation().isAsyncStarted()) { // return buffers _parser.returnBuffers(); _generator.returnBuffers(); - - // resuming checking for idle + } + + // reenable idle checking unless request is suspended + if(!_request.getAsyncContinuation().isAsyncStarted()) + { _asyncEndp.setCheckForIdle(true); } - + // Safety net to catch spinning if (some_progress) _total_no_progress=0; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 34c17c2a6b9..40c03097f54 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -4,11 +4,11 @@ // 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 +// 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. +// You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.server; @@ -55,6 +55,7 @@ import javax.servlet.http.Part; import org.eclipse.jetty.continuation.Continuation; import org.eclipse.jetty.continuation.ContinuationListener; import org.eclipse.jetty.http.HttpCookie; +import org.eclipse.jetty.http.HttpException; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpMethods; @@ -83,63 +84,56 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ -/** Jetty Request. +/** + * Jetty Request. *

* Implements {@link javax.servlet.http.HttpServletRequest} from the javax.servlet.http package. *

*

- * The standard interface of mostly getters, - * is extended with setters so that the request is mutable by the handlers that it is - * passed to. This allows the request object to be as lightweight as possible and not - * actually implement any significant behavior. For example

    - * - *
  • The {@link Request#getContextPath()} method will return null, until the request has been - * passed to a {@link ContextHandler} which matches the {@link Request#getPathInfo()} with a context - * path and calls {@link Request#setContextPath(String)} as a result.
  • - * - *
  • the HTTP session methods - * will all return null sessions until such time as a request has been passed to - * a {@link org.eclipse.jetty.server.session.SessionHandler} which checks for session cookies - * and enables the ability to create new sessions.
  • - * - *
  • The {@link Request#getServletPath()} method will return null until the request has been - * passed to a org.eclipse.jetty.servlet.ServletHandler and the pathInfo matched - * against the servlet URL patterns and {@link Request#setServletPath(String)} called as a result.
  • + * The standard interface of mostly getters, is extended with setters so that the request is mutable by the handlers that it is passed to. This allows the + * request object to be as lightweight as possible and not actually implement any significant behavior. For example + *
      + * + *
    • The {@link Request#getContextPath()} method will return null, until the request has been passed to a {@link ContextHandler} which matches the + * {@link Request#getPathInfo()} with a context path and calls {@link Request#setContextPath(String)} as a result.
    • + * + *
    • the HTTP session methods will all return null sessions until such time as a request has been passed to a + * {@link org.eclipse.jetty.server.session.SessionHandler} which checks for session cookies and enables the ability to create new sessions.
    • + * + *
    • The {@link Request#getServletPath()} method will return null until the request has been passed to a org.eclipse.jetty.servlet.ServletHandler + * and the pathInfo matched against the servlet URL patterns and {@link Request#setServletPath(String)} called as a result.
    • *
    - * - * A request instance is created for each {@link AbstractHttpConnection} accepted by the server - * and recycled for each HTTP request received via that connection. An effort is made - * to avoid reparsing headers and cookies that are likely to be the same for - * requests from the same connection. - * + * + * A request instance is created for each {@link AbstractHttpConnection} accepted by the server and recycled for each HTTP request received via that connection. + * An effort is made to avoid reparsing headers and cookies that are likely to be the same for requests from the same connection. + * *

    - * The form content that a request can process is limited to protect from Denial of Service - * attacks. The size in bytes is limited by {@link ContextHandler#getMaxFormContentSize()} or if there is no - * context then the "org.eclipse.jetty.server.Request.maxFormContentSize" {@link Server} attribute. - * The number of parameters keys is limited by {@link ContextHandler#getMaxFormKeys()} or if there is no - * context then the "org.eclipse.jetty.server.Request.maxFormKeys" {@link Server} attribute. - * - * + * The form content that a request can process is limited to protect from Denial of Service attacks. The size in bytes is limited by + * {@link ContextHandler#getMaxFormContentSize()} or if there is no context then the "org.eclipse.jetty.server.Request.maxFormContentSize" {@link Server} + * attribute. The number of parameters keys is limited by {@link ContextHandler#getMaxFormKeys()} or if there is no context then the + * "org.eclipse.jetty.server.Request.maxFormKeys" {@link Server} attribute. + * + * */ public class Request implements HttpServletRequest { public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.multipartConfig"; private static final Logger LOG = Log.getLogger(Request.class); - private static final String __ASYNC_FWD="org.eclipse.asyncfwd"; + private static final String __ASYNC_FWD = "org.eclipse.asyncfwd"; private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault()); - private static final int __NONE=0, _STREAM=1, __READER=2; + private static final int __NONE = 0, _STREAM = 1, __READER = 2; /* ------------------------------------------------------------ */ public static Request getRequest(HttpServletRequest request) { if (request instanceof Request) - return (Request) request; + return (Request)request; return AbstractHttpConnection.getCurrentConnection().getRequest(); } protected final AsyncContinuation _async = new AsyncContinuation(); - private boolean _asyncSupported=true; + private boolean _asyncSupported = true; private volatile Attributes _attributes; private Authentication _authentication; private MultiMap _baseParameters; @@ -149,18 +143,18 @@ public class Request implements HttpServletRequest private boolean _newContext; private String _contextPath; private CookieCutter _cookies; - private boolean _cookiesExtracted=false; + private boolean _cookiesExtracted = false; private DispatcherType _dispatcherType; - private boolean _dns=false; + private boolean _dns = false; private EndPoint _endp; - private boolean _handled =false; - private int _inputState=__NONE; + private boolean _handled = false; + private int _inputState = __NONE; private String _method; private MultiMap _parameters; private boolean _paramsExtracted; private String _pathInfo; private int _port; - private String _protocol=HttpVersions.HTTP_1_1; + private String _protocol = HttpVersions.HTTP_1_1; private String _queryEncoding; private String _queryString; private BufferedReader _reader; @@ -169,10 +163,10 @@ public class Request implements HttpServletRequest private String _remoteHost; private Object _requestAttributeListeners; private String _requestedSessionId; - private boolean _requestedSessionIdFromCookie=false; + private boolean _requestedSessionIdFromCookie = false; private String _requestURI; - private Map _savedNewSessions; - private String _scheme=URIUtil.HTTP; + private Map _savedNewSessions; + private String _scheme = URIUtil.HTTP; private UserIdentity.Scope _scope; private String _serverName; private String _servletPath; @@ -180,7 +174,7 @@ public class Request implements HttpServletRequest private SessionManager _sessionManager; private long _timeStamp; private long _dispatchTime; - + private Buffer _timeStampBuffer; private HttpURI _uri; @@ -198,10 +192,10 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - public void addEventListener(final EventListener listener) + public void addEventListener(final EventListener listener) { if (listener instanceof ServletRequestAttributeListener) - _requestAttributeListeners= LazyList.add(_requestAttributeListeners, listener); + _requestAttributeListeners = LazyList.add(_requestAttributeListeners,listener); if (listener instanceof ContinuationListener) throw new IllegalArgumentException(listener.getClass().toString()); if (listener instanceof AsyncListener) @@ -214,13 +208,13 @@ public class Request implements HttpServletRequest */ public void extractParameters() { - if (_baseParameters == null) + if (_baseParameters == null) _baseParameters = new MultiMap(16); - if (_paramsExtracted) + if (_paramsExtracted) { - if (_parameters==null) - _parameters=_baseParameters; + if (_parameters == null) + _parameters = _baseParameters; return; } @@ -229,9 +223,9 @@ public class Request implements HttpServletRequest try { // Handle query string - if (_uri!=null && _uri.hasQuery()) + if (_uri != null && _uri.hasQuery()) { - if (_queryEncoding==null) + if (_queryEncoding == null) _uri.decodeQueryTo(_baseParameters); else { @@ -254,40 +248,41 @@ public class Request implements HttpServletRequest String content_type = getContentType(); if (content_type != null && content_type.length() > 0) { - content_type = HttpFields.valueParameters(content_type, null); - - if (MimeTypes.FORM_ENCODED.equalsIgnoreCase(content_type) && _inputState==__NONE && - (HttpMethods.POST.equals(getMethod()) || HttpMethods.PUT.equals(getMethod()))) + content_type = HttpFields.valueParameters(content_type,null); + + if (MimeTypes.FORM_ENCODED.equalsIgnoreCase(content_type) && _inputState == __NONE + && (HttpMethods.POST.equals(getMethod()) || HttpMethods.PUT.equals(getMethod()))) { int content_length = getContentLength(); if (content_length != 0) { try { - int maxFormContentSize=-1; - int maxFormKeys=-1; + int maxFormContentSize = -1; + int maxFormKeys = -1; - if (_context!=null) + if (_context != null) { - maxFormContentSize=_context.getContextHandler().getMaxFormContentSize(); - maxFormKeys=_context.getContextHandler().getMaxFormKeys(); + maxFormContentSize = _context.getContextHandler().getMaxFormContentSize(); + maxFormKeys = _context.getContextHandler().getMaxFormKeys(); } else { - Number size = (Number)_connection.getConnector().getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize"); - maxFormContentSize=size==null?200000:size.intValue(); + Number size = (Number)_connection.getConnector().getServer() + .getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize"); + maxFormContentSize = size == null?200000:size.intValue(); Number keys = (Number)_connection.getConnector().getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys"); - maxFormKeys =keys==null?1000:keys.intValue(); + maxFormKeys = keys == null?1000:keys.intValue(); } - - if (content_length>maxFormContentSize && maxFormContentSize > 0) + + if (content_length > maxFormContentSize && maxFormContentSize > 0) { - throw new IllegalStateException("Form too large"+content_length+">"+maxFormContentSize); + throw new IllegalStateException("Form too large" + content_length + ">" + maxFormContentSize); } InputStream in = getInputStream(); // Add form params to query params - UrlEncoded.decodeTo(in, _baseParameters, encoding,content_length<0?maxFormContentSize:-1,maxFormKeys); + UrlEncoded.decodeTo(in,_baseParameters,encoding,content_length < 0?maxFormContentSize:-1,maxFormKeys); } catch (IOException e) { @@ -300,34 +295,34 @@ public class Request implements HttpServletRequest } } - if (_parameters==null) - _parameters=_baseParameters; - else if (_parameters!=_baseParameters) + if (_parameters == null) + _parameters = _baseParameters; + else if (_parameters != _baseParameters) { // Merge parameters (needed if parameters extracted after a forward). Iterator iter = _baseParameters.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); - String name=(String)entry.getKey(); - Object values=entry.getValue(); - for (int i=0;inull if {@link #setContext} has not yet - * been called. + * @return The current {@link Context context} used for this request, or null if {@link #setContext} has not yet been called. */ public Context getContext() { @@ -453,7 +449,7 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getContextPath() */ public String getContextPath() @@ -462,23 +458,23 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getCookies() */ public Cookie[] getCookies() { - if (_cookiesExtracted) - return _cookies==null?null:_cookies.getCookies(); + if (_cookiesExtracted) + return _cookies == null?null:_cookies.getCookies(); _cookiesExtracted = true; - + Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.COOKIE_BUFFER); - + // Handle no cookies - if (enm!=null) + if (enm != null) { - if (_cookies==null) - _cookies=new CookieCutter(); + if (_cookies == null) + _cookies = new CookieCutter(); while (enm.hasMoreElements()) { @@ -487,11 +483,11 @@ public class Request implements HttpServletRequest } } - return _cookies==null?null:_cookies.getCookies(); + return _cookies == null?null:_cookies.getCookies(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String) */ public long getDateHeader(String name) @@ -502,11 +498,11 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ public DispatcherType getDispatcherType() { - return _dispatcherType; + return _dispatcherType; } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String) */ public String getHeader(String name) @@ -515,7 +511,7 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getHeaderNames() */ public Enumeration getHeaderNames() @@ -524,13 +520,13 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String) */ public Enumeration getHeaders(String name) { Enumeration e = _connection.getRequestFields().getValues(name); - if (e==null) + if (e == null) return Collections.enumeration(Collections.EMPTY_LIST); return e; } @@ -545,19 +541,19 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getInputStream() */ public ServletInputStream getInputStream() throws IOException { - if (_inputState!=__NONE && _inputState!=_STREAM) + if (_inputState != __NONE && _inputState != _STREAM) throw new IllegalStateException("READER"); - _inputState=_STREAM; + _inputState = _STREAM; return _connection.getInputStream(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String) */ public int getIntHeader(String name) @@ -566,37 +562,37 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getLocalAddr() */ public String getLocalAddr() { - return _endp==null?null:_endp.getLocalAddr(); + return _endp == null?null:_endp.getLocalAddr(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getLocale() */ public Locale getLocale() { - Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.ACCEPT_LANGUAGE, HttpFields.__separators); - + Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.ACCEPT_LANGUAGE,HttpFields.__separators); + // handle no locale if (enm == null || !enm.hasMoreElements()) return Locale.getDefault(); - + // sort the list in quality order List acceptLanguage = HttpFields.qualityList(enm); - if (acceptLanguage.size()==0) - return Locale.getDefault(); - - int size=acceptLanguage.size(); + if (acceptLanguage.size() == 0) + return Locale.getDefault(); - if (size>0) + int size = acceptLanguage.size(); + + if (size > 0) { String language = (String)acceptLanguage.get(0); - language=HttpFields.valueParameters(language,null); + language = HttpFields.valueParameters(language,null); String country = ""; int dash = language.indexOf('-'); if (dash > -1) @@ -606,37 +602,37 @@ public class Request implements HttpServletRequest } return new Locale(language,country); } - - return Locale.getDefault(); + + return Locale.getDefault(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getLocales() */ public Enumeration getLocales() { - Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.ACCEPT_LANGUAGE, HttpFields.__separators); - + + Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.ACCEPT_LANGUAGE,HttpFields.__separators); + // handle no locale if (enm == null || !enm.hasMoreElements()) return Collections.enumeration(__defaultLocale); - + // sort the list in quality order List acceptLanguage = HttpFields.qualityList(enm); - - if (acceptLanguage.size()==0) - return - Collections.enumeration(__defaultLocale); - + + if (acceptLanguage.size() == 0) + return Collections.enumeration(__defaultLocale); + Object langs = null; - int size=acceptLanguage.size(); - + int size = acceptLanguage.size(); + // convert to locals - for (int i=0; i -1) @@ -644,44 +640,44 @@ public class Request implements HttpServletRequest country = language.substring(dash + 1).trim(); language = language.substring(0,dash).trim(); } - langs=LazyList.ensureSize(langs,size); - langs=LazyList.add(langs,new Locale(language,country)); + langs = LazyList.ensureSize(langs,size); + langs = LazyList.add(langs,new Locale(language,country)); } - - if (LazyList.size(langs)==0) + + if (LazyList.size(langs) == 0) return Collections.enumeration(__defaultLocale); - + return Collections.enumeration(LazyList.getList(langs)); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getLocalName() */ public String getLocalName() { - if (_endp==null) + if (_endp == null) return null; if (_dns) return _endp.getLocalHost(); - + String local = _endp.getLocalAddr(); - if (local!=null && local.indexOf(':')>=0) - local="["+local+"]"; + if (local != null && local.indexOf(':') >= 0) + local = "[" + local + "]"; return local; } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getLocalPort() */ public int getLocalPort() { - return _endp==null?0:_endp.getLocalPort(); + return _endp == null?0:_endp.getLocalPort(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getMethod() */ public String getMethod() @@ -690,35 +686,35 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getParameter(java.lang.String) */ public String getParameter(String name) { - if (!_paramsExtracted) + if (!_paramsExtracted) extractParameters(); - return (String) _parameters.getValue(name, 0); + return (String)_parameters.getValue(name,0); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getParameterMap() */ public Map getParameterMap() { - if (!_paramsExtracted) + if (!_paramsExtracted) extractParameters(); - + return Collections.unmodifiableMap(_parameters.toStringArrayMap()); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getParameterNames() */ public Enumeration getParameterNames() { - if (!_paramsExtracted) + if (!_paramsExtracted) extractParameters(); return Collections.enumeration(_parameters.keySet()); } @@ -733,21 +729,21 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String) */ public String[] getParameterValues(String name) { - if (!_paramsExtracted) + if (!_paramsExtracted) extractParameters(); List vals = _parameters.getValues(name); - if (vals==null) + if (vals == null) return null; - return (String[])vals.toArray(new String[vals.size()]); + return vals.toArray(new String[vals.size()]); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getPathInfo() */ public String getPathInfo() @@ -756,18 +752,18 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getPathTranslated() */ public String getPathTranslated() { - if (_pathInfo==null || _context==null) + if (_pathInfo == null || _context == null) return null; return _context.getRealPath(_pathInfo); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getProtocol() */ public String getProtocol() @@ -782,78 +778,78 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getQueryString() */ public String getQueryString() { - if (_queryString==null && _uri!=null) + if (_queryString == null && _uri != null) { - if (_queryEncoding==null) - _queryString=_uri.getQuery(); + if (_queryEncoding == null) + _queryString = _uri.getQuery(); else - _queryString=_uri.getQuery(_queryEncoding); + _queryString = _uri.getQuery(_queryEncoding); } return _queryString; } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getReader() */ public BufferedReader getReader() throws IOException { - if (_inputState!=__NONE && _inputState!=__READER) + if (_inputState != __NONE && _inputState != __READER) throw new IllegalStateException("STREAMED"); - if (_inputState==__READER) + if (_inputState == __READER) return _reader; - - String encoding=getCharacterEncoding(); - if (encoding==null) - encoding=StringUtil.__ISO_8859_1; - - if (_reader==null || !encoding.equalsIgnoreCase(_readerEncoding)) + + String encoding = getCharacterEncoding(); + if (encoding == null) + encoding = StringUtil.__ISO_8859_1; + + if (_reader == null || !encoding.equalsIgnoreCase(_readerEncoding)) { final ServletInputStream in = getInputStream(); - _readerEncoding=encoding; - _reader=new BufferedReader(new InputStreamReader(in,encoding)) + _readerEncoding = encoding; + _reader = new BufferedReader(new InputStreamReader(in,encoding)) { @Override public void close() throws IOException { in.close(); - } + } }; } - _inputState=__READER; + _inputState = __READER; return _reader; } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getRealPath(java.lang.String) */ public String getRealPath(String path) { - if (_context==null) + if (_context == null) return null; return _context.getRealPath(path); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getRemoteAddr() */ public String getRemoteAddr() { if (_remoteAddr != null) - return _remoteAddr; - return _endp==null?null:_endp.getRemoteAddr(); + return _remoteAddr; + return _endp == null?null:_endp.getRemoteAddr(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getRemoteHost() */ public String getRemoteHost() @@ -864,58 +860,58 @@ public class Request implements HttpServletRequest { return _remoteHost; } - return _endp==null?null:_endp.getRemoteHost(); + return _endp == null?null:_endp.getRemoteHost(); } return getRemoteAddr(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getRemotePort() */ public int getRemotePort() { - return _endp==null?0:_endp.getRemotePort(); + return _endp == null?0:_endp.getRemotePort(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getRemoteUser() */ public String getRemoteUser() { Principal p = getUserPrincipal(); - if (p==null) + if (p == null) return null; return p.getName(); } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String) */ public RequestDispatcher getRequestDispatcher(String path) { - if (path == null || _context==null) + if (path == null || _context == null) return null; // handle relative path if (!path.startsWith("/")) { - String relTo=URIUtil.addPaths(_servletPath,_pathInfo); - int slash=relTo.lastIndexOf("/"); - if (slash>1) - relTo=relTo.substring(0,slash+1); + String relTo = URIUtil.addPaths(_servletPath,_pathInfo); + int slash = relTo.lastIndexOf("/"); + if (slash > 1) + relTo = relTo.substring(0,slash + 1); else - relTo="/"; - path=URIUtil.addPaths(relTo,path); + relTo = "/"; + path = URIUtil.addPaths(relTo,path); } - + return _context.getRequestDispatcher(path); } - + /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId() */ public String getRequestedSessionId() @@ -924,18 +920,18 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getRequestURI() */ public String getRequestURI() { - if (_requestURI==null && _uri!=null) - _requestURI=_uri.getPathAndParam(); + if (_requestURI == null && _uri != null) + _requestURI = _uri.getPathAndParam(); return _requestURI; } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getRequestURL() */ public StringBuffer getRequestURL() @@ -949,14 +945,12 @@ public class Request implements HttpServletRequest url.append(scheme); url.append("://"); url.append(getServerName()); - if (_port>0 && - ((scheme.equalsIgnoreCase(URIUtil.HTTP) && port != 80) || - (scheme.equalsIgnoreCase(URIUtil.HTTPS) && port != 443))) + if (_port > 0 && ((scheme.equalsIgnoreCase(URIUtil.HTTP) && port != 80) || (scheme.equalsIgnoreCase(URIUtil.HTTPS) && port != 443))) { url.append(':'); url.append(_port); } - + url.append(getRequestURI()); return url; } @@ -967,17 +961,16 @@ public class Request implements HttpServletRequest { return _connection._response; } - + /* ------------------------------------------------------------ */ /** - * Reconstructs the URL the client used to make the request. The returned URL contains a - * protocol, server name, port number, and, but it does not include a path. + * Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and, but it does not include a + * path. *

    - * Because this method returns a StringBuffer, not a string, you can modify the - * URL easily, for example, to append path and query parameters. - * + * Because this method returns a StringBuffer, not a string, you can modify the URL easily, for example, to append path and query parameters. + * * This method is useful for creating redirect messages and for reporting errors. - * + * * @return "scheme://host:port" */ public StringBuilder getRootURL() @@ -999,7 +992,7 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getScheme() */ public String getScheme() @@ -1008,49 +1001,63 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getServerName() */ public String getServerName() - { + { // Return already determined host - if (_serverName != null) + if (_serverName != null) return _serverName; - + if (_uri == null) throw new IllegalStateException("No uri"); // Return host from absolute URI _serverName = _uri.getHost(); _port = _uri.getPort(); - if (_serverName != null) + if (_serverName != null) return _serverName; // Return host from header field Buffer hostPort = _connection.getRequestFields().get(HttpHeaders.HOST_BUFFER); - if (hostPort!=null) + if (hostPort != null) { - loop: - for (int i=hostPort.putIndex();i-->hostPort.getIndex();) + loop: for (int i = hostPort.putIndex(); i-- > hostPort.getIndex();) { - char ch=(char)(0xff&hostPort.peek(i)); - switch(ch) + char ch = (char)(0xff & hostPort.peek(i)); + switch (ch) { case ']': break loop; case ':': - _serverName=BufferUtil.to8859_1_String(hostPort.peek(hostPort.getIndex(), i-hostPort.getIndex())); - _port=BufferUtil.toInt(hostPort.peek(i+1, hostPort.putIndex()-i-1)); + _serverName = BufferUtil.to8859_1_String(hostPort.peek(hostPort.getIndex(),i - hostPort.getIndex())); + try + { + _port = BufferUtil.toInt(hostPort.peek(i + 1,hostPort.putIndex() - i - 1)); + } + catch (NumberFormatException e) + { + try + { + if (_connection != null) + _connection._generator.sendError(HttpStatus.BAD_REQUEST_400,"Bad Host header",null,true); + } + catch (IOException e1) + { + throw new RuntimeException(e1); + } + } return _serverName; } } - if (_serverName==null || _port<0) + if (_serverName == null || _port < 0) { - _serverName=BufferUtil.to8859_1_String(hostPort); + _serverName = BufferUtil.to8859_1_String(hostPort); _port = 0; } - + return _serverName; } @@ -1059,7 +1066,7 @@ public class Request implements HttpServletRequest { _serverName = getLocalName(); _port = getLocalPort(); - if (_serverName != null && !StringUtil.ALL_INTERFACES.equals(_serverName)) + if (_serverName != null && !StringUtil.ALL_INTERFACES.equals(_serverName)) return _serverName; } @@ -1076,26 +1083,26 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#getServerPort() */ public int getServerPort() { - if (_port<=0) + if (_port <= 0) { - if (_serverName==null) + if (_serverName == null) getServerName(); - - if (_port<=0) + + if (_port <= 0) { - if (_serverName!=null && _uri!=null) + if (_serverName != null && _uri != null) _port = _uri.getPort(); else - _port = _endp==null?0:_endp.getLocalPort(); + _port = _endp == null?0:_endp.getLocalPort(); } } - - if (_port<=0) + + if (_port <= 0) { if (getScheme().equalsIgnoreCase(URIUtil.HTTPS)) return 443; @@ -1111,23 +1118,23 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* */ public String getServletName() { - if (_scope!=null) + if (_scope != null) return _scope.getName(); return null; } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getServletPath() */ public String getServletPath() { - if (_servletPath==null) - _servletPath=""; + if (_servletPath == null) + _servletPath = ""; return _servletPath; } @@ -1138,7 +1145,7 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getSession() */ public HttpSession getSession() @@ -1147,33 +1154,32 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getSession(boolean) */ public HttpSession getSession(boolean create) - { - if (_session != null ) + { + if (_session != null) { - if (_sessionManager!=null && !_sessionManager.isValid(_session)) - _session=null; + if (_sessionManager != null && !_sessionManager.isValid(_session)) + _session = null; else return _session; } - + if (!create) return null; - - if (_sessionManager==null) + + if (_sessionManager == null) throw new IllegalStateException("No SessionManager"); - _session=_sessionManager.newHttpSession(this); - HttpCookie cookie=_sessionManager.getSessionCookie(_session,getContextPath(),isSecure()); - if (cookie!=null) + _session = _sessionManager.newHttpSession(this); + HttpCookie cookie = _sessionManager.getSessionCookie(_session,getContextPath(),isSecure()); + if (cookie != null) _connection.getResponse().addCookie(cookie); - + return _session; } - /* ------------------------------------------------------------ */ /** @@ -1183,31 +1189,31 @@ public class Request implements HttpServletRequest { return _sessionManager; } - + /* ------------------------------------------------------------ */ /** * Get Request TimeStamp - * + * * @return The time that the request was received. */ public long getTimeStamp() { return _timeStamp; } - + /* ------------------------------------------------------------ */ /** * Get Request TimeStamp - * + * * @return The time that the request was received. */ public Buffer getTimeStampBuffer() { if (_timeStampBuffer == null && _timeStamp > 0) - _timeStampBuffer = HttpFields.__dateCache.formatBuffer(_timeStamp); + _timeStampBuffer = HttpFields.__dateCache.formatBuffer(_timeStamp); return _timeStampBuffer; } - + /* ------------------------------------------------------------ */ /** * @return Returns the uri. @@ -1222,7 +1228,7 @@ public class Request implements HttpServletRequest { if (_authentication instanceof Authentication.Deferred) setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); - + if (_authentication instanceof Authentication.User) return ((Authentication.User)_authentication).getUserIdentity(); return null; @@ -1230,9 +1236,8 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @return The resolved user Identity, which may be null if the - * {@link Authentication} is not {@link Authentication.User} - * (eg. {@link Authentication.Deferred}). + * @return The resolved user Identity, which may be null if the {@link Authentication} is not {@link Authentication.User} (eg. + * {@link Authentication.Deferred}). */ public UserIdentity getResolvedUserIdentity() { @@ -1240,22 +1245,22 @@ public class Request implements HttpServletRequest return ((Authentication.User)_authentication).getUserIdentity(); return null; } - + /* ------------------------------------------------------------ */ public UserIdentity.Scope getUserIdentityScope() { return _scope; } - + /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#getUserPrincipal() */ public Principal getUserPrincipal() { if (_authentication instanceof Authentication.Deferred) setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); - + if (_authentication instanceof Authentication.User) { UserIdentity user = ((Authentication.User)_authentication).getUserIdentity(); @@ -1263,10 +1268,11 @@ public class Request implements HttpServletRequest } return null; } - + /* ------------------------------------------------------------ */ - /** Get timestamp of the request dispatch - * + /** + * Get timestamp of the request dispatch + * * @return timestamp */ public long getDispatchTime() @@ -1275,11 +1281,17 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ + public boolean isHandled() + { + return _handled; + } + public boolean isAsyncStarted() { - return _async.isAsyncStarted(); + return _async.isAsyncStarted(); } - + + /* ------------------------------------------------------------ */ public boolean isAsyncSupported() { @@ -1287,162 +1299,155 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - public boolean isHandled() - { - return _handled; - } - - /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie() */ public boolean isRequestedSessionIdFromCookie() { - return _requestedSessionId!=null && _requestedSessionIdFromCookie; + return _requestedSessionId != null && _requestedSessionIdFromCookie; } - + /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl() */ public boolean isRequestedSessionIdFromUrl() { - return _requestedSessionId!=null && !_requestedSessionIdFromCookie; + return _requestedSessionId != null && !_requestedSessionIdFromCookie; } - + /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL() */ public boolean isRequestedSessionIdFromURL() { - return _requestedSessionId!=null && !_requestedSessionIdFromCookie; + return _requestedSessionId != null && !_requestedSessionIdFromCookie; } - + /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid() */ public boolean isRequestedSessionIdValid() - { - if (_requestedSessionId==null) + { + if (_requestedSessionId == null) return false; - - HttpSession session=getSession(false); + + HttpSession session = getSession(false); return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session))); } - + /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#isSecure() */ public boolean isSecure() { return _connection.isConfidential(this); } - + /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String) */ public boolean isUserInRole(String role) { if (_authentication instanceof Authentication.Deferred) setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); - + if (_authentication instanceof Authentication.User) return ((Authentication.User)_authentication).isUserInRole(_scope,role); return false; } - + /* ------------------------------------------------------------ */ public HttpSession recoverNewSession(Object key) { - if (_savedNewSessions==null) + if (_savedNewSessions == null) return null; return _savedNewSessions.get(key); } - + /* ------------------------------------------------------------ */ protected void recycle() { - if (_inputState==__READER) + if (_inputState == __READER) { try { - int r=_reader.read(); - while(r!=-1) - r=_reader.read(); + int r = _reader.read(); + while (r != -1) + r = _reader.read(); } - catch(Exception e) + catch (Exception e) { LOG.ignore(e); - _reader=null; + _reader = null; } } - + setAuthentication(Authentication.NOT_CHECKED); - _async.recycle(); - _asyncSupported=true; - _handled=false; - if (_context!=null) + _async.recycle(); + _asyncSupported = true; + _handled = false; + if (_context != null) throw new IllegalStateException("Request in context!"); - if(_attributes!=null) + if (_attributes != null) _attributes.clearAttributes(); - _characterEncoding=null; - if (_cookies!=null) + _characterEncoding = null; + if (_cookies != null) _cookies.reset(); - _cookiesExtracted=false; - _context=null; - _serverName=null; - _method=null; - _pathInfo=null; - _port=0; - _protocol=HttpVersions.HTTP_1_1; - _queryEncoding=null; - _queryString=null; - _requestedSessionId=null; - _requestedSessionIdFromCookie=false; - _session=null; - _sessionManager=null; - _requestURI=null; - _scope=null; - _scheme=URIUtil.HTTP; - _servletPath=null; - _timeStamp=0; - _timeStampBuffer=null; - _uri=null; - if (_baseParameters!=null) + _cookiesExtracted = false; + _context = null; + _serverName = null; + _method = null; + _pathInfo = null; + _port = 0; + _protocol = HttpVersions.HTTP_1_1; + _queryEncoding = null; + _queryString = null; + _requestedSessionId = null; + _requestedSessionIdFromCookie = false; + _session = null; + _sessionManager = null; + _requestURI = null; + _scope = null; + _scheme = URIUtil.HTTP; + _servletPath = null; + _timeStamp = 0; + _timeStampBuffer = null; + _uri = null; + if (_baseParameters != null) _baseParameters.clear(); - _parameters=null; - _paramsExtracted=false; - _inputState=__NONE; - - if (_savedNewSessions!=null) + _parameters = null; + _paramsExtracted = false; + _inputState = __NONE; + + if (_savedNewSessions != null) _savedNewSessions.clear(); _savedNewSessions=null; _multiPartInputStream = null; } - + /* ------------------------------------------------------------ */ - /* + /* * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String) */ public void removeAttribute(String name) { - Object old_value=_attributes==null?null:_attributes.getAttribute(name); - - if (_attributes!=null) + Object old_value = _attributes == null?null:_attributes.getAttribute(name); + + if (_attributes != null) _attributes.removeAttribute(name); - - if (old_value!=null) + + if (old_value != null) { - if (_requestAttributeListeners!=null) + if (_requestAttributeListeners != null) { - final ServletRequestAttributeEvent event = - new ServletRequestAttributeEvent(_context,this,name, old_value); - final int size=LazyList.size(_requestAttributeListeners); - for(int i=0;i(); + if (_savedNewSessions == null) + _savedNewSessions = new HashMap(); _savedNewSessions.put(key,session); } + /* ------------------------------------------------------------ */ public void setAsyncSupported(boolean supported) { - _asyncSupported=supported; + _asyncSupported = supported; } - + /* ------------------------------------------------------------ */ - /* - * Set a request attribute. - * if the attribute name is "org.eclipse.jetty.server.server.Request.queryEncoding" then - * the value is also passed in a call to {@link #setQueryEncoding}. - *

    - * if the attribute name is "org.eclipse.jetty.server.server.ResponseBuffer", then - * the response buffer is flushed with @{link #flushResponseBuffer} - *

    - * if the attribute name is "org.eclipse.jetty.io.EndPoint.maxIdleTime", then the - * value is passed to the associated {@link EndPoint#setMaxIdleTime}. + /* + * Set a request attribute. if the attribute name is "org.eclipse.jetty.server.server.Request.queryEncoding" then the value is also passed in a call to + * {@link #setQueryEncoding}.

    if the attribute name is "org.eclipse.jetty.server.server.ResponseBuffer", then the response buffer is flushed with @{link + * #flushResponseBuffer}

    if the attribute name is "org.eclipse.jetty.io.EndPoint.maxIdleTime", then the value is passed to the associated {@link + * EndPoint#setMaxIdleTime}. + * * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object) */ public void setAttribute(String name, Object value) { - Object old_value=_attributes==null?null:_attributes.getAttribute(name); - + Object old_value = _attributes == null?null:_attributes.getAttribute(name); + if (name.startsWith("org.eclipse.jetty.")) { if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name)) - setQueryEncoding(value==null?null:value.toString()); - else if("org.eclipse.jetty.server.sendContent".equals(name)) + setQueryEncoding(value == null?null:value.toString()); + else if ("org.eclipse.jetty.server.sendContent".equals(name)) { - try + try { - ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendContent(value); - } + ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendContent(value); + } catch (IOException e) { throw new RuntimeException(e); } } - else if("org.eclipse.jetty.server.ResponseBuffer".equals(name)) + else if ("org.eclipse.jetty.server.ResponseBuffer".equals(name)) { try { - final ByteBuffer byteBuffer=(ByteBuffer)value; + final ByteBuffer byteBuffer = (ByteBuffer)value; synchronized (byteBuffer) { - NIOBuffer buffer = byteBuffer.isDirect() - ?new DirectNIOBuffer(byteBuffer,true) - :new IndirectNIOBuffer(byteBuffer,true); + NIOBuffer buffer = byteBuffer.isDirect()?new DirectNIOBuffer(byteBuffer,true):new IndirectNIOBuffer(byteBuffer,true); ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendResponse(buffer); } } @@ -1529,32 +1530,31 @@ public class Request implements HttpServletRequest { getConnection().getEndPoint().setMaxIdleTime(Integer.valueOf(value.toString())); } - catch(IOException e) + catch (IOException e) { throw new RuntimeException(e); } } } - - if (_attributes==null) - _attributes=new AttributesMap(); - _attributes.setAttribute(name, value); - - if (_requestAttributeListeners!=null) + + if (_attributes == null) + _attributes = new AttributesMap(); + _attributes.setAttribute(name,value); + + if (_requestAttributeListeners != null) { - final ServletRequestAttributeEvent event = - new ServletRequestAttributeEvent(_context,this,name, old_value==null?value:old_value); - final int size=LazyList.size(_requestAttributeListeners); - for(int i=0;i parameters) { - _parameters= (parameters==null)?_baseParameters:parameters; - if (_paramsExtracted && _parameters==null) + _parameters = (parameters == null)?_baseParameters:parameters; + if (_paramsExtracted && _parameters == null) throw new IllegalStateException(); } /* ------------------------------------------------------------ */ /** - * @param pathInfo The pathInfo to set. + * @param pathInfo + * The pathInfo to set. */ public void setPathInfo(String pathInfo) { _pathInfo = pathInfo; } - + /* ------------------------------------------------------------ */ /** - * @param protocol The protocol to set. + * @param protocol + * The protocol to set. */ public void setProtocol(String protocol) { @@ -1725,33 +1734,34 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /** Set the character encoding used for the query string. - * This call will effect the return of getQueryString and getParamaters. - * It must be called before any geParameter methods. - * - * The request attribute "org.eclipse.jetty.server.server.Request.queryEncoding" - * may be set as an alternate method of calling setQueryEncoding. - * + /** + * Set the character encoding used for the query string. This call will effect the return of getQueryString and getParamaters. It must be called before any + * geParameter methods. + * + * The request attribute "org.eclipse.jetty.server.server.Request.queryEncoding" may be set as an alternate method of calling setQueryEncoding. + * * @param queryEncoding */ public void setQueryEncoding(String queryEncoding) { - _queryEncoding=queryEncoding; - _queryString=null; + _queryEncoding = queryEncoding; + _queryString = null; } - + /* ------------------------------------------------------------ */ /** - * @param queryString The queryString to set. + * @param queryString + * The queryString to set. */ public void setQueryString(String queryString) { _queryString = queryString; } - + /* ------------------------------------------------------------ */ /** - * @param addr The address to set. + * @param addr + * The address to set. */ public void setRemoteAddr(String addr) { @@ -1760,7 +1770,8 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param host The host to set. + * @param host + * The host to set. */ public void setRemoteHost(String host) { @@ -1769,16 +1780,18 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param requestedSessionId The requestedSessionId to set. + * @param requestedSessionId + * The requestedSessionId to set. */ public void setRequestedSessionId(String requestedSessionId) { _requestedSessionId = requestedSessionId; } - + /* ------------------------------------------------------------ */ /** - * @param requestedSessionIdCookie The requestedSessionIdCookie to set. + * @param requestedSessionIdCookie + * The requestedSessionIdCookie to set. */ public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie) { @@ -1787,7 +1800,8 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param requestURI The requestURI to set. + * @param requestURI + * The requestURI to set. */ public void setRequestURI(String requestURI) { @@ -1796,7 +1810,8 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param scheme The scheme to set. + * @param scheme + * The scheme to set. */ public void setScheme(String scheme) { @@ -1805,16 +1820,18 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param host The host to set. + * @param host + * The host to set. */ public void setServerName(String host) { _serverName = host; } - + /* ------------------------------------------------------------ */ /** - * @param port The port to set. + * @param port + * The port to set. */ public void setServerPort(int port) { @@ -1823,7 +1840,8 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param servletPath The servletPath to set. + * @param servletPath + * The servletPath to set. */ public void setServletPath(String servletPath) { @@ -1832,7 +1850,8 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param session The session to set. + * @param session + * The session to set. */ public void setSession(HttpSession session) { @@ -1841,7 +1860,8 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param sessionManager The sessionManager to set. + * @param sessionManager + * The sessionManager to set. */ public void setSessionManager(SessionManager sessionManager) { @@ -1856,7 +1876,8 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ /** - * @param uri The uri to set. + * @param uri + * The uri to set. */ public void setUri(HttpURI uri) { @@ -1866,13 +1887,15 @@ public class Request implements HttpServletRequest /* ------------------------------------------------------------ */ public void setUserIdentityScope(UserIdentity.Scope scope) { - _scope=scope; + _scope = scope; } /* ------------------------------------------------------------ */ - /** Set timetstamp of request dispatch - * - * @param value timestamp + /** + * Set timetstamp of request dispatch + * + * @param value + * timestamp */ public void setDispatchTime(long value) { @@ -1884,7 +1907,7 @@ public class Request implements HttpServletRequest { if (!_asyncSupported) throw new IllegalStateException("!asyncSupported"); - _async.suspend(_context,this,_connection._response); + _async.suspend(_context,this,_connection._response); return _async; } @@ -1901,7 +1924,7 @@ public class Request implements HttpServletRequest @Override public String toString() { - return (_handled?"[":"(")+getMethod()+" "+_uri+(_handled?"]@":")@")+hashCode()+" "+super.toString(); + return (_handled?"[":"(") + getMethod() + " " + _uri + (_handled?"]@":")@") + hashCode() + " " + super.toString(); } /* ------------------------------------------------------------ */ @@ -1970,80 +1993,81 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - /** Merge in a new query string. - * The query string is merged with the existing parameters and {@link #setParameters(MultiMap)} and {@link #setQueryString(String)} are called with the result. - * The merge is according to the rules of the servlet dispatch forward method. - * @param query The query string to merge into the request. + /** + * Merge in a new query string. The query string is merged with the existing parameters and {@link #setParameters(MultiMap)} and + * {@link #setQueryString(String)} are called with the result. The merge is according to the rules of the servlet dispatch forward method. + * + * @param query + * The query string to merge into the request. */ public void mergeQueryString(String query) { // extract parameters from dispatch query - MultiMap parameters=new MultiMap(); + MultiMap parameters = new MultiMap(); UrlEncoded.decodeTo(query,parameters,getCharacterEncoding()); - + boolean merge_old_query = false; // Have we evaluated parameters - if (!_paramsExtracted) + if (!_paramsExtracted) extractParameters(); - + // Are there any existing parameters? - if (_parameters!=null && _parameters.size()>0) + if (_parameters != null && _parameters.size() > 0) { // Merge parameters; new parameters of the same name take precedence. - Iterator> iter = _parameters.entrySet().iterator(); + Iterator> iter = _parameters.entrySet().iterator(); while (iter.hasNext()) { - Map.Entry entry = iter.next(); - String name=entry.getKey(); - + Map.Entry entry = iter.next(); + String name = entry.getKey(); + // If the names match, we will need to remake the query string if (parameters.containsKey(name)) merge_old_query = true; // Add the old values to the new parameter map - Object values=entry.getValue(); - for (int i=0;i0) + + if (_queryString != null && _queryString.length() > 0) { - if ( merge_old_query ) + if (merge_old_query) { StringBuilder overridden_query_string = new StringBuilder(); MultiMap overridden_old_query = new MultiMap(); UrlEncoded.decodeTo(_queryString,overridden_old_query,getCharacterEncoding()); - MultiMap overridden_new_query = new MultiMap(); + MultiMap overridden_new_query = new MultiMap(); UrlEncoded.decodeTo(query,overridden_new_query,getCharacterEncoding()); - Iterator> iter = overridden_old_query.entrySet().iterator(); + Iterator> iter = overridden_old_query.entrySet().iterator(); while (iter.hasNext()) { - Map.Entry entry = iter.next(); - String name=entry.getKey(); - if(!overridden_new_query.containsKey(name)) + Map.Entry entry = iter.next(); + String name = entry.getKey(); + if (!overridden_new_query.containsKey(name)) { - Object values=entry.getValue(); - for (int i=0;i200); - Assert.assertTrue(System.currentTimeMillis()-start<5000); + Assert.assertTrue(System.currentTimeMillis()-start>minimumTestRuntime); + Assert.assertTrue(System.currentTimeMillis()-start200); - Assert.assertTrue(System.currentTimeMillis()-start<5000); + Assert.assertTrue(System.currentTimeMillis()-start>minimumTestRuntime); + Assert.assertTrue(System.currentTimeMillis()-start0) - { - byte[] buf=new byte[_read]; - request.getInputStream().read(buf); - } - else if (_read<0) - { - InputStream in = request.getInputStream(); - int b=in.read(); - while(b!=-1) - b=in.read(); - } - - - final AsyncContext asyncContext = baseRequest.startAsync(); - response.getOutputStream().println("STARTASYNC"); - asyncContext.addListener(__asyncListener); - asyncContext.addListener(__asyncListener1); - if (_suspendFor>0) - asyncContext.setTimeout(_suspendFor); - - - if (_completeAfter>0) - { - new Thread() { - @Override - public void run() - { - try - { - Thread.sleep(_completeAfter); - response.getOutputStream().println("COMPLETED"); - response.setStatus(200); - baseRequest.setHandled(true); - asyncContext.complete(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - }.start(); - } - else if (_completeAfter==0) - { - response.getOutputStream().println("COMPLETED"); - response.setStatus(200); - baseRequest.setHandled(true); - asyncContext.complete(); - } - - if (_resumeAfter>0) - { - new Thread() { - @Override - public void run() - { - try - { - Thread.sleep(_resumeAfter); - if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null) - asyncContext.dispatch(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - }.start(); - } - else if (_resumeAfter==0) - { - asyncContext.dispatch(); - } - } - else - { - if (request.getAttribute("TIMEOUT")!=null) - response.getOutputStream().println("TIMEOUT"); - else - response.getOutputStream().println("DISPATCHED"); - - if (_suspendFor2>=0) - { - final AsyncContext asyncContext = baseRequest.startAsync(); - response.getOutputStream().println("STARTASYNC2"); - if (_suspendFor2>0) - asyncContext.setTimeout(_suspendFor2); - _suspendFor2=-1; - - if (_completeAfter2>0) - { - new Thread() { - @Override - public void run() - { - try - { - Thread.sleep(_completeAfter2); - response.getOutputStream().println("COMPLETED2"); - response.setStatus(200); - baseRequest.setHandled(true); - asyncContext.complete(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - }.start(); - } - else if (_completeAfter2==0) - { - response.getOutputStream().println("COMPLETED2"); - response.setStatus(200); - baseRequest.setHandled(true); - asyncContext.complete(); - } - - if (_resumeAfter2>0) - { - new Thread() { - @Override - public void run() - { - try - { - Thread.sleep(_resumeAfter2); - asyncContext.dispatch(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - }.start(); - } - else if (_resumeAfter2==0) - { - asyncContext.dispatch(); - } - } - else - { - response.setStatus(200); - baseRequest.setHandled(true); - } - } - } - finally - { - } - } - } static AtomicInteger __completed = new AtomicInteger(); static AtomicInteger __completed1 = new AtomicInteger(); - private static AsyncListener __asyncListener = new AsyncListener() + static AsyncListener __asyncListener = new AsyncListener() { @Override @@ -512,7 +236,7 @@ public class LocalAsyncContextTest }; - private static AsyncListener __asyncListener1 = new AsyncListener() + static AsyncListener __asyncListener1 = new AsyncListener() { @Override diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 039fe0d25ef..5496c028dce 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -40,6 +40,7 @@ import junit.framework.Assert; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.server.handler.AbstractHandler; +import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; @@ -78,7 +79,7 @@ public class RequestTest _server.stop(); _server.join(); } - + @Test public void testParamExtraction() throws Exception { @@ -101,27 +102,27 @@ public class RequestTest System.err.println(map); assertFalse(map == null); assertTrue(map.isEmpty()); - + Enumeration names = request.getParameterNames(); assertFalse(names.hasMoreElements()); } - + return true; } }; - + //Send a request with query string with illegal hex code to cause //an exception parsing the params String request="GET /?param=%ZZaaa HTTP/1.1\r\n"+ "Host: whatever\r\n"+ "Content-Type: text/html;charset=utf8\n"+ "\n"; - + String responses=_connector.getResponses(request); assertTrue(responses.startsWith("HTTP/1.1 200")); - + } - + @Test public void testBadUtf8ParamExtraction() throws Exception { @@ -133,20 +134,40 @@ public class RequestTest return value.startsWith("aaa") && value.endsWith("bb"); } }; - + //Send a request with query string with illegal hex code to cause //an exception parsing the params String request="GET /?param=aaa%E7bbb HTTP/1.1\r\n"+ "Host: whatever\r\n"+ "Content-Type: text/html;charset=utf8\n"+ "\n"; - + String responses=_connector.getResponses(request); - assertTrue(responses.startsWith("HTTP/1.1 200")); + assertTrue(responses.startsWith("HTTP/1.1 200")); } - - + @Test + public void testInvalidHostHeader() throws Exception + { + // Use a contextHandler with vhosts to force call to Request.getServerName() + ContextHandler handler = new ContextHandler(); + handler.addVirtualHosts(new String[1]); + _server.stop(); + _server.setHandler(handler); + _server.start(); + + // Request with illegal Host header + String request="GET / HTTP/1.1\r\n"+ + "Host: whatever.com:\r\n"+ + "Content-Type: text/html;charset=utf8\n"+ + "\n"; + + String responses=_connector.getResponses(request); + assertTrue("400 Bad Request response expected",responses.startsWith("HTTP/1.1 400")); + } + + + @Test public void testContentTypeEncoding() throws Exception { @@ -196,7 +217,7 @@ public class RequestTest assertTrue(results.get(i++).startsWith("text/html")); assertEquals(" x=z; ",results.get(i++)); } - + @Test public void testHostPort() throws Exception { @@ -369,7 +390,7 @@ public class RequestTest Reader reader=request.getReader(); String in = IO.toString(reader); String param = request.getParameter("param"); - + byte[] b=("read='"+in+"' param="+param+"\n").getBytes(StringUtil.__UTF8); response.setContentLength(b.length); response.getOutputStream().write(b); @@ -389,11 +410,11 @@ public class RequestTest "param=wrong\r\n"; String responses = _connector.getResponses(request); - + assertTrue(responses.indexOf("read='param=wrong' param=right")>0); - + } - + @Test public void testPartialInput() throws Exception { @@ -754,7 +775,7 @@ public class RequestTest { _server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize",-1); _server.setAttribute("org.eclipse.jetty.server.Request.maxFormKeys",1000); - + // This file is not distributed - as it is dangerous File evil_keys = new File("/tmp/keys_mapping_to_zero_2m"); if (!evil_keys.exists()) @@ -762,10 +783,10 @@ public class RequestTest Log.info("testHashDOS skipped"); return; } - + BufferedReader in = new BufferedReader(new FileReader(evil_keys)); StringBuilder buf = new StringBuilder(4000000); - + String key=null; buf.append("a=b"); while((key=in.readLine())!=null) @@ -773,7 +794,7 @@ public class RequestTest buf.append("&").append(key).append("=").append("x"); } buf.append("&c=d"); - + _handler._checker = new RequestTester() { public boolean check(HttpServletRequest request,HttpServletResponse response) @@ -789,15 +810,15 @@ public class RequestTest "Connection: close\r\n"+ "\r\n"+ buf; - + long start=System.currentTimeMillis(); String response = _connector.getResponses(request); assertTrue(response.contains("200 OK")); long now=System.currentTimeMillis(); assertTrue((now-start)<5000); } - - + + interface RequestTester { boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException; @@ -814,12 +835,12 @@ public class RequestTest if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType())) _content=IO.toString(request.getInputStream()); - + if (_checker!=null && _checker.check(request,response)) response.setStatus(200); else response.sendError(500); - + } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java index ece6ae77b9f..9fcdfb6d532 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java @@ -13,17 +13,96 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.Socket; + import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.eclipse.jetty.server.session.SessionHandler; +import org.eclipse.jetty.util.IO; import org.junit.BeforeClass; +import org.junit.Test; public class SelectChannelTimeoutTest extends ConnectorTimeoutTest { + @BeforeClass public static void init() throws Exception { SelectChannelConnector connector = new SelectChannelConnector(); - connector.setMaxIdleTime(MAX_IDLE_TIME); //250 msec max idle + connector.setMaxIdleTime(MAX_IDLE_TIME); // 250 msec max idle startServer(connector); } + @Test + public void testIdleTimeoutAfterSuspend() throws Exception + { + SuspendHandler _handler = new SuspendHandler(); + _server.stop(); + SessionHandler session = new SessionHandler(); + session.setHandler(_handler); + _server.setHandler(session); + _server.start(); + + _handler.setSuspendFor(100); + _handler.setResumeAfter(25); + assertTrue(process(null).toUpperCase().contains("DISPATCHED")); + } + + @Test + public void testIdleTimeoutAfterTimeout() throws Exception + { + SuspendHandler _handler = new SuspendHandler(); + _server.stop(); + SessionHandler session = new SessionHandler(); + session.setHandler(_handler); + _server.setHandler(session); + _server.start(); + + _handler.setSuspendFor(50); + assertTrue(process(null).toUpperCase().contains("TIMEOUT")); + } + + @Test + public void testIdleTimeoutAfterComplete() throws Exception + { + SuspendHandler _handler = new SuspendHandler(); + _server.stop(); + SessionHandler session = new SessionHandler(); + session.setHandler(_handler); + _server.setHandler(session); + _server.start(); + + _handler.setSuspendFor(100); + _handler.setCompleteAfter(25); + assertTrue(process(null).toUpperCase().contains("COMPLETED")); + } + + private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException + { + String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n"; + + if (content == null) + request += "\r\n"; + else + request += "Content-Length: " + content.length() + "\r\n" + "\r\n" + content; + return getResponse(request); + } + + private String getResponse(String request) throws UnsupportedEncodingException, IOException, InterruptedException + { + SelectChannelConnector connector = (SelectChannelConnector)_connector; + Socket socket = new Socket((String)null,connector.getLocalPort()); + socket.getOutputStream().write(request.getBytes("UTF-8")); + InputStream inputStream = socket.getInputStream(); + String response = IO.toString(inputStream); + Thread.sleep(500); + assertEquals("Socket should be closed and return -1 on reading",-1,socket.getInputStream().read()); + return response; + } + } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java new file mode 100644 index 00000000000..db4c297f932 --- /dev/null +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java @@ -0,0 +1,290 @@ +package org.eclipse.jetty.server; + +import java.io.IOException; +import java.io.InputStream; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.server.handler.HandlerWrapper; + +class SuspendHandler extends HandlerWrapper +{ + private int _read; + private long _suspendFor=-1; + private long _resumeAfter=-1; + private long _completeAfter=-1; + private long _suspendFor2=-1; + private long _resumeAfter2=-1; + private long _completeAfter2=-1; + + public SuspendHandler() + { + } + + public int getRead() + { + return _read; + } + + public void setRead(int read) + { + _read = read; + } + + public long getSuspendFor() + { + return _suspendFor; + } + + public void setSuspendFor(long suspendFor) + { + _suspendFor = suspendFor; + } + + public long getResumeAfter() + { + return _resumeAfter; + } + + public void setResumeAfter(long resumeAfter) + { + _resumeAfter = resumeAfter; + } + + public long getCompleteAfter() + { + return _completeAfter; + } + + public void setCompleteAfter(long completeAfter) + { + _completeAfter = completeAfter; + } + + + + /* ------------------------------------------------------------ */ + /** Get the suspendFor2. + * @return the suspendFor2 + */ + public long getSuspendFor2() + { + return _suspendFor2; + } + + + /* ------------------------------------------------------------ */ + /** Set the suspendFor2. + * @param suspendFor2 the suspendFor2 to set + */ + public void setSuspendFor2(long suspendFor2) + { + _suspendFor2 = suspendFor2; + } + + + /* ------------------------------------------------------------ */ + /** Get the resumeAfter2. + * @return the resumeAfter2 + */ + public long getResumeAfter2() + { + return _resumeAfter2; + } + + + /* ------------------------------------------------------------ */ + /** Set the resumeAfter2. + * @param resumeAfter2 the resumeAfter2 to set + */ + public void setResumeAfter2(long resumeAfter2) + { + _resumeAfter2 = resumeAfter2; + } + + + /* ------------------------------------------------------------ */ + /** Get the completeAfter2. + * @return the completeAfter2 + */ + public long getCompleteAfter2() + { + return _completeAfter2; + } + + + /* ------------------------------------------------------------ */ + /** Set the completeAfter2. + * @param completeAfter2 the completeAfter2 to set + */ + public void setCompleteAfter2(long completeAfter2) + { + _completeAfter2 = completeAfter2; + } + + + @Override + public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException + { + try + { + if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType())) + { + if (_read>0) + { + byte[] buf=new byte[_read]; + request.getInputStream().read(buf); + } + else if (_read<0) + { + InputStream in = request.getInputStream(); + int b=in.read(); + while(b!=-1) + b=in.read(); + } + + + final AsyncContext asyncContext = baseRequest.startAsync(); + response.getOutputStream().println("STARTASYNC"); + asyncContext.addListener(LocalAsyncContextTest.__asyncListener); + asyncContext.addListener(LocalAsyncContextTest.__asyncListener1); + if (_suspendFor>0) + asyncContext.setTimeout(_suspendFor); + + + if (_completeAfter>0) + { + new Thread() { + @Override + public void run() + { + try + { + Thread.sleep(_completeAfter); + response.getOutputStream().println("COMPLETED"); + response.setStatus(200); + baseRequest.setHandled(true); + asyncContext.complete(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + }.start(); + } + else if (_completeAfter==0) + { + response.getOutputStream().println("COMPLETED"); + response.setStatus(200); + baseRequest.setHandled(true); + asyncContext.complete(); + } + + if (_resumeAfter>0) + { + new Thread() { + @Override + public void run() + { + try + { + Thread.sleep(_resumeAfter); + if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null) + asyncContext.dispatch(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + }.start(); + } + else if (_resumeAfter==0) + { + asyncContext.dispatch(); + } + } + else + { + if (request.getAttribute("TIMEOUT")!=null) + response.getOutputStream().println("TIMEOUT"); + else + response.getOutputStream().println("DISPATCHED"); + + if (_suspendFor2>=0) + { + final AsyncContext asyncContext = baseRequest.startAsync(); + response.getOutputStream().println("STARTASYNC2"); + if (_suspendFor2>0) + asyncContext.setTimeout(_suspendFor2); + _suspendFor2=-1; + + if (_completeAfter2>0) + { + new Thread() { + @Override + public void run() + { + try + { + Thread.sleep(_completeAfter2); + response.getOutputStream().println("COMPLETED2"); + response.setStatus(200); + baseRequest.setHandled(true); + asyncContext.complete(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + }.start(); + } + else if (_completeAfter2==0) + { + response.getOutputStream().println("COMPLETED2"); + response.setStatus(200); + baseRequest.setHandled(true); + asyncContext.complete(); + } + + if (_resumeAfter2>0) + { + new Thread() { + @Override + public void run() + { + try + { + Thread.sleep(_resumeAfter2); + asyncContext.dispatch(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + }.start(); + } + else if (_resumeAfter2==0) + { + asyncContext.dispatch(); + } + } + else + { + response.setStatus(200); + baseRequest.setHandled(true); + } + } + } + finally + { + } + } +} \ No newline at end of file diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java index 2b186b49677..48bfcf391c0 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java @@ -57,7 +57,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool; /** * Asynchronous Proxy Servlet. - * + * * Forward requests to another server either as a standard web proxy (as defined by RFC2616) or as a transparent proxy. *

    * This servlet needs the jetty-util and jetty-client classes to be available to the web application. @@ -75,17 +75,15 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool; *

  • requestBufferSize - the size of the request buffer (d. 12,288) *
  • responseHeaderSize - the size of the response header buffer (d. 6,144) *
  • responseBufferSize - the size of the response buffer (d. 32,768) - *
  • HostHeader - Force the host header to a particular value + *
  • HostHeader - Force the host header to a particular value *
  • whiteList - comma-separated list of allowed proxy destinations *
  • blackList - comma-separated list of forbidden proxy destinations * - * + * * @see org.eclipse.jetty.server.handler.ConnectHandler */ public class ProxyServlet implements Servlet { - private static final Logger LOG = Log.getLogger(ProxyServlet.class); - protected Logger _log; protected HttpClient _client; protected String _hostHeader; @@ -111,22 +109,22 @@ public class ProxyServlet implements Servlet /* ------------------------------------------------------------ */ /* * (non-Javadoc) - * + * * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) */ public void init(ServletConfig config) throws ServletException { _config = config; _context = config.getServletContext(); - + _hostHeader = config.getInitParameter("HostHeader"); try { - _log = createLogger(config); + _log = createLogger(config); _client = createHttpClient(config); - + if (_context != null) { _context.setAttribute(config.getServletName() + ".Logger",_log); @@ -162,12 +160,12 @@ public class ProxyServlet implements Servlet _log.debug(x); } } - - + + /** - * Create and return a logger based on the ServletConfig for use in the + * Create and return a logger based on the ServletConfig for use in the * proxy servlet - * + * * @param config * @return Logger */ @@ -175,24 +173,24 @@ public class ProxyServlet implements Servlet { return Log.getLogger("org.eclipse.jetty.servlets." + config.getServletName()); } - + /** * Create and return an HttpClient based on ServletConfig - * - * By default this implementation will create an instance of the + * + * By default this implementation will create an instance of the * HttpClient for use by this proxy servlet. - * - * @param config - * @return HttpClient + * + * @param config + * @return HttpClient * @throws Exception */ protected HttpClient createHttpClient(ServletConfig config) throws Exception { HttpClient client = new HttpClient(); client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - + String t = config.getInitParameter("maxThreads"); - + if (t != null) { client.setThreadPool(new QueuedThreadPool(Integer.parseInt(t))); @@ -201,67 +199,67 @@ public class ProxyServlet implements Servlet { client.setThreadPool(new QueuedThreadPool()); } - - ((QueuedThreadPool)client.getThreadPool()).setName(config.getServletName()); + + ((QueuedThreadPool)client.getThreadPool()).setName(config.getServletName()); t = config.getInitParameter("maxConnections"); - + if (t != null) { client.setMaxConnectionsPerAddress(Integer.parseInt(t)); } - + t = config.getInitParameter("timeout"); - + if ( t != null ) { client.setTimeout(Long.parseLong(t)); } - + t = config.getInitParameter("idleTimeout"); - + if ( t != null ) { client.setIdleTimeout(Long.parseLong(t)); } - + t = config.getInitParameter("requestHeaderSize"); - + if ( t != null ) { client.setRequestHeaderSize(Integer.parseInt(t)); } - + t = config.getInitParameter("requestBufferSize"); - + if ( t != null ) { client.setRequestBufferSize(Integer.parseInt(t)); } - + t = config.getInitParameter("responseHeaderSize"); - + if ( t != null ) { client.setResponseHeaderSize(Integer.parseInt(t)); } - + t = config.getInitParameter("responseBufferSize"); - + if ( t != null ) { client.setResponseBufferSize(Integer.parseInt(t)); } - + client.start(); - + return client; } - + /* ------------------------------------------------------------ */ /** * Helper function to process a parameter value containing a list of new entries and initialize the specified host map. - * + * * @param list * comma-separated list of new entries * @param hostMap @@ -301,7 +299,7 @@ public class ProxyServlet implements Servlet /* ------------------------------------------------------------ */ /** * Check the request hostname and path against white- and blacklist. - * + * * @param host * hostname to check * @param path @@ -353,7 +351,7 @@ public class ProxyServlet implements Servlet /* ------------------------------------------------------------ */ /* * (non-Javadoc) - * + * * @see javax.servlet.Servlet#getServletConfig() */ public ServletConfig getServletConfig() @@ -364,7 +362,7 @@ public class ProxyServlet implements Servlet /* ------------------------------------------------------------ */ /** * Get the hostHeader. - * + * * @return the hostHeader */ public String getHostHeader() @@ -375,7 +373,7 @@ public class ProxyServlet implements Servlet /* ------------------------------------------------------------ */ /** * Set the hostHeader. - * + * * @param hostHeader * the hostHeader to set */ @@ -387,7 +385,7 @@ public class ProxyServlet implements Servlet /* ------------------------------------------------------------ */ /* * (non-Javadoc) - * + * * @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse) */ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException @@ -412,7 +410,7 @@ public class ProxyServlet implements Servlet response.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT); // Need better test that isInitial else { - + String uri = request.getRequestURI(); if (request.getQueryString() != null) uri += "?" + request.getQueryString(); @@ -430,14 +428,17 @@ public class ProxyServlet implements Servlet HttpExchange exchange = new HttpExchange() { + @Override protected void onRequestCommitted() throws IOException { } + @Override protected void onRequestComplete() throws IOException { } + @Override protected void onResponseComplete() throws IOException { if (debug != 0) @@ -445,6 +446,7 @@ public class ProxyServlet implements Servlet continuation.complete(); } + @Override protected void onResponseContent(Buffer content) throws IOException { if (debug != 0) @@ -452,10 +454,12 @@ public class ProxyServlet implements Servlet content.writeTo(out); } + @Override protected void onResponseHeaderComplete() throws IOException { } + @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { if (debug != 0) @@ -467,6 +471,7 @@ public class ProxyServlet implements Servlet response.setStatus(status); } + @Override protected void onResponseHeader(Buffer name, Buffer value) throws IOException { String s = name.toString().toLowerCase(); @@ -481,11 +486,12 @@ public class ProxyServlet implements Servlet _log.debug(debug + " " + name + "! " + value); } + @Override protected void onConnectionFailed(Throwable ex) { handleOnConnectionFailed(ex,request,response); - - // it is possible this might trigger before the + + // it is possible this might trigger before the // continuation.suspend() if (!continuation.isInitial()) { @@ -493,16 +499,17 @@ public class ProxyServlet implements Servlet } } + @Override protected void onException(Throwable ex) { if (ex instanceof EofException) { - LOG.ignore(ex); + _log.ignore(ex); return; } handleOnException(ex,request,response); - - // it is possible this might trigger before the + + // it is possible this might trigger before the // continuation.suspend() if (!continuation.isInitial()) { @@ -510,6 +517,7 @@ public class ProxyServlet implements Servlet } } + @Override protected void onExpire() { handleOnExpire(request,response); @@ -597,14 +605,14 @@ public class ProxyServlet implements Servlet if (hasContent) exchange.setRequestContentSource(in); - customizeExchange(exchange, request); - + customizeExchange(exchange, request); + /* * we need to set the timeout on the continuation to take into * account the timeout of the HttpClient and the HttpExchange */ long ctimeout = (_client.getTimeout() > exchange.getTimeout()) ? _client.getTimeout() : exchange.getTimeout(); - + // continuation fudge factor of 1000, underlying components // should fail/expire first from exchange if ( ctimeout == 0 ) @@ -612,12 +620,12 @@ public class ProxyServlet implements Servlet continuation.setTimeout(0); // ideally never times out } else - { + { continuation.setTimeout(ctimeout + 1000); } - + customizeContinuation(continuation); - + continuation.suspend(response); _client.send(exchange); @@ -678,7 +686,7 @@ public class ProxyServlet implements Servlet /* * (non-Javadoc) - * + * * @see javax.servlet.Servlet#getServletInfo() */ public String getServletInfo() @@ -689,7 +697,7 @@ public class ProxyServlet implements Servlet /** * Extension point for subclasses to customize an exchange. Useful for setting timeouts etc. The default implementation does nothing. - * + * * @param exchange * @param request */ @@ -701,7 +709,7 @@ public class ProxyServlet implements Servlet /** * Extension point for subclasses to customize the Continuation after it's initial creation in the service method. Useful for setting timeouts etc. The * default implementation does nothing. - * + * * @param continuation */ protected void customizeContinuation(Continuation continuation) @@ -712,7 +720,7 @@ public class ProxyServlet implements Servlet /** * Extension point for custom handling of an HttpExchange's onConnectionFailed method. The default implementation delegates to * {@link #handleOnException(Throwable, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)} - * + * * @param ex * @param request * @param response @@ -725,15 +733,15 @@ public class ProxyServlet implements Servlet /** * Extension point for custom handling of an HttpExchange's onException method. The default implementation sets the response status to * HttpServletResponse.SC_INTERNAL_SERVER_ERROR (503) - * + * * @param ex * @param request * @param response */ protected void handleOnException(Throwable ex, HttpServletRequest request, HttpServletResponse response) { - LOG.warn(ex.toString()); - LOG.debug(ex); + _log.warn(ex.toString()); + _log.debug(ex); if (!response.isCommitted()) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); @@ -743,7 +751,7 @@ public class ProxyServlet implements Servlet /** * Extension point for custom handling of an HttpExchange's onExpire method. The default implementation sets the response status to * HttpServletResponse.SC_GATEWAY_TIMEOUT (504) - * + * * @param request * @param response */ @@ -757,7 +765,7 @@ public class ProxyServlet implements Servlet /** * Transparent Proxy. - * + * * This convenience extension to ProxyServlet configures the servlet as a transparent proxy. The servlet is configured with init parameters: *
      *
    • ProxyTo - a URI like http://host:80/context to which the request is proxied. @@ -765,7 +773,7 @@ public class ProxyServlet implements Servlet *
    * For example, if a request was received at /foo/bar and the ProxyTo was http://host:80/context and the Prefix was /foo, then the request would be proxied * to http://host:80/context/bar - * + * */ public static class Transparent extends ProxyServlet { diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java index c42b93d7106..69112f8f319 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java @@ -123,30 +123,35 @@ public class Main // if no non-option inis, add the start.ini and start.d if (!ini) { - List ini_args=new ArrayList(); - File start_ini = new File(_jettyHome,"start.ini"); - if (start_ini.exists()) - ini_args.addAll(loadStartIni(start_ini)); - - File start_d = new File(_jettyHome,"start.d"); - if (start_d.isDirectory()) - { - File[] inis = start_d.listFiles(new FilenameFilter() - { - public boolean accept(File dir, String name) - { - return name.toLowerCase().endsWith(".ini"); - } - }); - Arrays.sort(inis); - for (File i : inis) - ini_args.addAll(loadStartIni(i)); - } - arguments.addAll(0,ini_args); + arguments.addAll(0,parseStartIniFiles()); } return arguments; } + + List parseStartIniFiles() + { + List ini_args=new ArrayList(); + File start_ini = new File(_jettyHome,"start.ini"); + if (start_ini.exists()) + ini_args.addAll(loadStartIni(start_ini)); + + File start_d = new File(_jettyHome,"start.d"); + if (start_d.isDirectory()) + { + File[] inis = start_d.listFiles(new FilenameFilter() + { + public boolean accept(File dir, String name) + { + return name.toLowerCase().endsWith(".ini"); + } + }); + Arrays.sort(inis); + for (File i : inis) + ini_args.addAll(loadStartIni(i)); + } + return ini_args; + } public List processCommandLine(List arguments) throws Exception { @@ -1075,7 +1080,7 @@ public class Main } catch (IOException e) { - // usageExit(e,ERR_UNKNOWN); + usageExit(e,ERR_UNKNOWN); } finally { diff --git a/jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt b/jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt index c4c85c4523d..41b0107580e 100644 --- a/jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt +++ b/jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt @@ -20,7 +20,7 @@ Command Line Options: when the start.ini includes -X or -D arguments. --exec Run the generated command line (see --dry-run) in - a sub processes. This can be used when start.ini + a sub process. This can be used when start.ini contains -X or -D arguments, but creates an extra JVM instance. @@ -36,8 +36,10 @@ Command Line Options: --ini= Load command line arguments from a file. If no --ini options are specified, then the - start.ini file will be read if it exists. - A --ini option with no file indicates that + start.ini file will be read if it exists in + jetty.home. If specified jetty.home/start.ini + and additional .ini files in jetty.home/start.d/ + will NOT be read. A --ini option with no file indicates that start.ini should not be read. --pre= Specify a configuration file that is to be processed @@ -116,10 +118,10 @@ Available Configurations: Defaults: A start.ini file may be used to specify default arguments to start.jar, which are used if no command line arguments are provided and override - the defaults in the start.config file. If the directory start.d exists, - then multiple *.ini files will be read from that directory in alphabetical - order. If --ini options are provided on the command line, then start.ini - and start.d will not be read. + the defaults in the start.config file. If the directory jetty.home/start.d + exists, then multiple *.ini files will be read from that directory in + alphabetical order. If --ini options are provided on the command line, + then start.ini and start.d will NOT be read. The current start.ini arguments are: diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java index 246771b4da6..8e2f1f071bb 100644 --- a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java @@ -15,7 +15,7 @@ package org.eclipse.jetty.start; import static org.junit.Assert.assertEquals; -import java.io.File; +import java.io.IOException; import java.net.URL; import java.util.List; @@ -39,15 +39,18 @@ public class MainTest /** * Test method for {@link org.eclipse.jetty.start.StartIniParser#loadStartIni(java.lang.String)}. + * @throws IOException */ @Test - public void testLoadStartIni() + public void testLoadStartIni() throws IOException { - URL startIni = this.getClass().getResource("/jetty.home/start.ini"); - String startIniFileName = startIni.getFile(); - List args = Main.loadStartIni(new File(startIniFileName)); - assertEquals("Expected 5 uncommented lines in start.ini",5,args.size()); + URL startIni = this.getClass().getResource("/jetty.home/"); + System.setProperty("jetty.home",startIni.getFile()); + Main main = new Main(); + List args = main.parseStartIniFiles(); + assertEquals("Expected 5 uncommented lines in start.ini",9,args.size()); assertEquals("First uncommented line in start.ini doesn't match expected result","OPTIONS=Server,jsp,resources,websocket,ext",args.get(0)); + assertEquals("Last uncommented line in start.ini doesn't match expected result","etc/jetty-testrealm.xml",args.get(8)); } @Test diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/log/Log.java b/jetty-util/src/main/java/org/eclipse/jetty/util/log/Log.java index 74f8e5fa66d..c1f42baa85e 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/log/Log.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/log/Log.java @@ -102,7 +102,10 @@ public class Log while (systemKeyEnum.hasMoreElements()) { String key = systemKeyEnum.nextElement(); - __props.setProperty(key,System.getProperty(key)); + String val = System.getProperty(key); + //protect against application code insertion of non-String values (returned as null) + if (val != null) + __props.setProperty(key,val); } /* Now use the configuration properties to configure the Log statics diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketClientFactory.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketClientFactory.java index 4b250ab1b2d..c7c73bc6524 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketClientFactory.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketClientFactory.java @@ -45,6 +45,7 @@ import org.eclipse.jetty.io.nio.SslConnection; import org.eclipse.jetty.util.B64Code; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.component.AggregateLifeCycle; +import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -67,6 +68,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle private final Queue connections = new ConcurrentLinkedQueue(); private final SslContextFactory _sslContextFactory = new SslContextFactory(); private final ThreadPool _threadPool; + private final boolean _shutdownThreadPool; private final WebSocketClientSelector _selector; private MaskGen _maskGen; private WebSocketBuffers _buffers; @@ -77,7 +79,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle */ public WebSocketClientFactory() { - this(new QueuedThreadPool()); + this(null); } /* ------------------------------------------------------------ */ @@ -114,14 +116,27 @@ public class WebSocketClientFactory extends AggregateLifeCycle */ public WebSocketClientFactory(ThreadPool threadPool, MaskGen maskGen, int bufferSize) { - _threadPool = threadPool; - addBean(threadPool); + if (threadPool == null) + { + _threadPool = new QueuedThreadPool(); + addBean(_threadPool); + _shutdownThreadPool = true; + } + else + { + _threadPool = threadPool; + _shutdownThreadPool = false; + } + _buffers = new WebSocketBuffers(bufferSize); addBean(_buffers); + _maskGen = maskGen; addBean(_maskGen); + _selector = new WebSocketClientSelector(); addBean(_selector); + addBean(_sslContextFactory); } @@ -208,6 +223,9 @@ public class WebSocketClientFactory extends AggregateLifeCycle protected void doStop() throws Exception { closeConnections(); + super.doStop(); + if (_shutdownThreadPool && _threadPool instanceof LifeCycle) + ((LifeCycle)_threadPool).stop(); } /* ------------------------------------------------------------ */ diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnectionRFC6455.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnectionRFC6455.java index 7f693751be0..9a6377bd125 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnectionRFC6455.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnectionRFC6455.java @@ -121,7 +121,7 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We private final static byte[] MAGIC; private final List _extensions; - private final WebSocketParserD13 _parser; + private final WebSocketParserRFC6455 _parser; private final WebSocketGeneratorRFC6455 _generator; private final WebSocketGenerator _outbound; private final WebSocket _webSocket; @@ -197,7 +197,7 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We _outbound=(_extensions==null||_extensions.size()==0)?_generator:extensions.get(extensions.size()-1); WebSocketParser.FrameHandler inbound = (_extensions == null || _extensions.size() == 0) ? frameHandler : extensions.get(0); - _parser = new WebSocketParserD13(buffers, endpoint, inbound,maskgen==null); + _parser = new WebSocketParserRFC6455(buffers, endpoint, inbound,maskgen==null); _protocol=protocol; @@ -642,7 +642,13 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We @Override public String toString() { - return this.getClass().getSimpleName()+"D13@"+_endp.getLocalAddr()+":"+_endp.getLocalPort()+"<->"+_endp.getRemoteAddr()+":"+_endp.getRemotePort(); + return String.format("%s@%x l(%s:%d)<->r(%s:%d)", + getClass().getSimpleName(), + hashCode(), + _endp.getLocalAddr(), + _endp.getLocalPort(), + _endp.getRemoteAddr(), + _endp.getRemotePort()); } } @@ -973,6 +979,6 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We @Override public String toString() { - return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator); + return String.format("%s p=%s g=%s", getClass().getSimpleName(), _parser, _generator); } } diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParserD13.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455.java similarity index 98% rename from jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParserD13.java rename to jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455.java index 9979a683735..dbb16cb4390 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParserD13.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455.java @@ -43,9 +43,9 @@ import org.eclipse.jetty.util.log.Logger; * Parser the WebSocket protocol. * */ -public class WebSocketParserD13 implements WebSocketParser +public class WebSocketParserRFC6455 implements WebSocketParser { - private static final Logger LOG = Log.getLogger(WebSocketParserD13.class); + private static final Logger LOG = Log.getLogger(WebSocketParserRFC6455.class); public enum State { @@ -89,7 +89,7 @@ public class WebSocketParserD13 implements WebSocketParser * @param handler the handler to notify when a parse event occurs * @param shouldBeMasked whether masking should be handled */ - public WebSocketParserD13(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked) + public WebSocketParserRFC6455(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked) { _buffers=buffers; _endp=endp; diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SafariWebsocketDraft0Test.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SafariWebsocketDraft0Test.java index 0afb1dfae64..9b4af2d27c9 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SafariWebsocketDraft0Test.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SafariWebsocketDraft0Test.java @@ -15,8 +15,6 @@ *******************************************************************************/ package org.eclipse.jetty.websocket; -import static org.hamcrest.Matchers.*; - import java.net.URI; import java.util.concurrent.TimeUnit; @@ -24,7 +22,6 @@ import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.log.StdErrLog; import org.eclipse.jetty.websocket.helper.CaptureSocket; import org.eclipse.jetty.websocket.helper.SafariD00; import org.eclipse.jetty.websocket.helper.WebSocketCaptureServlet; @@ -32,9 +29,11 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + public class SafariWebsocketDraft0Test { private Server server; @@ -76,7 +75,7 @@ public class SafariWebsocketDraft0Test serverUri = new URI(String.format("ws://%s:%d/",host,port)); // System.out.printf("Server URI: %s%n",serverUri); } - + @Test public void testSendTextMessages() throws Exception { @@ -96,10 +95,11 @@ public class SafariWebsocketDraft0Test CaptureSocket socket = servlet.captures.get(0); Assert.assertThat("CaptureSocket",socket,notNullValue()); - Assert.assertThat("CaptureSocket.isConnected", socket.isConnected(), is(true)); + Assert.assertThat("CaptureSocket.isConnected", socket.awaitConnected(1000), is(true)); - // Give servlet 500 millisecond to process messages + // Give servlet time to process messages threadSleep(1,TimeUnit.SECONDS); + // Should have captured 5 messages. Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5)); } @@ -109,13 +109,13 @@ public class SafariWebsocketDraft0Test safari.disconnect(); } } - + public static void threadSleep(int dur, TimeUnit unit) throws InterruptedException { long ms = TimeUnit.MILLISECONDS.convert(dur,unit); Thread.sleep(ms); } - + @After public void stopServer() throws Exception { diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketClientTest.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketClientTest.java index 571a454e0da..07a9060baa0 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketClientTest.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketClientTest.java @@ -74,8 +74,10 @@ public class WebSocketClientTest @Test public void testMessageBiggerThanBufferSize() throws Exception { + QueuedThreadPool threadPool = new QueuedThreadPool(); int bufferSize = 512; - WebSocketClientFactory factory = new WebSocketClientFactory(new QueuedThreadPool(), new ZeroMaskGen(), bufferSize); + WebSocketClientFactory factory = new WebSocketClientFactory(threadPool, new ZeroMaskGen(), bufferSize); + threadPool.start(); factory.start(); WebSocketClient client = new WebSocketClient(factory); @@ -118,6 +120,7 @@ public class WebSocketClientTest Assert.assertTrue(dataLatch.await(1000, TimeUnit.SECONDS)); factory.stop(); + threadPool.stop(); } @Test diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketCommTest.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketCommTest.java index 0e91ffaa0e9..1668d13b5ad 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketCommTest.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketCommTest.java @@ -15,8 +15,6 @@ *******************************************************************************/ package org.eclipse.jetty.websocket; -import static org.hamcrest.Matchers.*; - import java.net.URI; import java.util.concurrent.TimeUnit; @@ -32,6 +30,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + /** * WebSocketCommTest - to test reported undelivered messages in bug JETTY-1463 @@ -109,11 +110,11 @@ public class WebSocketCommTest CaptureSocket socket = servlet.captures.get(0); Assert.assertThat("CaptureSocket",socket,notNullValue()); - Assert.assertThat("CaptureSocket.isConnected",socket.isConnected(),is(true)); + Assert.assertThat("CaptureSocket.isConnected",socket.awaitConnected(1000),is(true)); - // Give servlet 500 millisecond to process messages + // Give servlet time to process messages TimeUnit.MILLISECONDS.sleep(500); - + // Should have captured 5 messages. Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5)); } diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketLoadD13Test.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketLoadRFC6455Test.java similarity index 96% rename from jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketLoadD13Test.java rename to jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketLoadRFC6455Test.java index 9a12059a006..13a3869bdc1 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketLoadD13Test.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketLoadRFC6455Test.java @@ -15,8 +15,6 @@ *******************************************************************************/ package org.eclipse.jetty.websocket; -import static org.junit.Assert.*; - import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; @@ -28,11 +26,9 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; - import javax.servlet.http.HttpServletRequest; import junit.framework.Assert; - import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.bio.SocketEndPoint; import org.eclipse.jetty.server.Connector; @@ -45,7 +41,9 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -public class WebSocketLoadD13Test +import static org.junit.Assert.assertTrue; + +public class WebSocketLoadRFC6455Test { private static Server _server; private static Connector _connector; @@ -127,7 +125,7 @@ public class WebSocketLoadD13Test { this.outbound = outbound; } - + public void onMessage(String data) { try @@ -155,7 +153,7 @@ public class WebSocketLoadD13Test private final CountDownLatch latch; private final SocketEndPoint _endp; private final WebSocketGeneratorRFC6455 _generator; - private final WebSocketParserD13 _parser; + private final WebSocketParserRFC6455 _parser; private final WebSocketParser.FrameHandler _handler = new WebSocketParser.FrameHandler() { public void onFrame(byte flags, byte opcode, Buffer buffer) @@ -168,7 +166,7 @@ public class WebSocketLoadD13Test } }; private volatile Buffer _response; - + public WebSocketClient(String host, int port, int readTimeout, CountDownLatch latch, int iterations) throws IOException { this.latch = latch; @@ -177,11 +175,11 @@ public class WebSocketLoadD13Test output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "ISO-8859-1")); input = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ISO-8859-1")); this.iterations = iterations; - + _endp=new SocketEndPoint(socket); _generator = new WebSocketGeneratorRFC6455(new WebSocketBuffers(32*1024),_endp,new FixedMaskGen()); - _parser = new WebSocketParserD13(new WebSocketBuffers(32*1024),_endp,_handler,false); - + _parser = new WebSocketParserRFC6455(new WebSocketBuffers(32*1024),_endp,_handler,false); + } private void open() throws IOException @@ -216,9 +214,9 @@ public class WebSocketLoadD13Test byte[] data = message.getBytes(StringUtil.__UTF8); _generator.addFrame((byte)0x8,WebSocketConnectionRFC6455.OP_TEXT,data,0,data.length); _generator.flush(); - + //System.err.println("-> "+message); - + _response=null; while(_response==null) _parser.parseNext(); diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketMessageRFC6455Test.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketMessageRFC6455Test.java index 6c017e93175..3fe9942cb63 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketMessageRFC6455Test.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketMessageRFC6455Test.java @@ -15,8 +15,6 @@ *******************************************************************************/ package org.eclipse.jetty.websocket; -import static org.junit.Assert.*; - import java.io.EOFException; import java.io.IOException; import java.io.InputStream; @@ -30,11 +28,9 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.zip.Deflater; import java.util.zip.Inflater; - import javax.servlet.http.HttpServletRequest; import junit.framework.Assert; - import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.server.Connector; @@ -48,6 +44,10 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + public class WebSocketMessageRFC6455Test { private static Server __server; @@ -78,7 +78,7 @@ public class WebSocketMessageRFC6455Test } }; wsHandler.getWebSocketFactory().setBufferSize(8192); - wsHandler.getWebSocketFactory().setMaxIdleTime(1000); + wsHandler.getWebSocketFactory().setMaxIdleTime(1000); wsHandler.setHandler(new DefaultHandler()); __server.setHandler(wsHandler); __server.start(); @@ -91,13 +91,13 @@ public class WebSocketMessageRFC6455Test __server.join(); } - + @Test public void testHash() { assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",WebSocketConnectionRFC6455.hashKey("dGhlIHNhbXBsZSBub25jZQ==")); } - + @Test public void testServerSendBigStringMessage() throws Exception { @@ -119,7 +119,7 @@ public class WebSocketMessageRFC6455Test socket.setSoTimeout(1000); InputStream input = socket.getInputStream(); - + lookFor("HTTP/1.1 101 Switching Protocols\r\n",input); skipTo("Sec-WebSocket-Accept: ",input); lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); @@ -127,7 +127,7 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - + // Server sends a big message StringBuilder message = new StringBuilder(); String text = "0123456789ABCDEF"; @@ -167,7 +167,7 @@ public class WebSocketMessageRFC6455Test socket.setSoTimeout(1000); InputStream input = socket.getInputStream(); - + lookFor("HTTP/1.1 101 Switching Protocols\r\n",input); skipTo("Sec-WebSocket-Accept: ",input); lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); @@ -175,7 +175,7 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - + assertEquals(0x81,input.read()); assertEquals(0x0f,input.read()); lookFor("sent on connect",input); @@ -312,8 +312,8 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - - + + // Server sends a big message String text = "0123456789ABCDEF "; text=text+text+text+text; @@ -324,15 +324,15 @@ public class WebSocketMessageRFC6455Test deflater.setInput(data); deflater.finish(); byte[] buf=new byte[data.length]; - + buf[0]=(byte)((byte)0x7e); buf[1]=(byte)(data.length>>8); buf[2]=(byte)(data.length&0xff); - + int l=deflater.deflate(buf,3,buf.length-3); assertTrue(deflater.finished()); - + output.write(0xC1); output.write((byte)(0x80|(0xff&(l+3)))); output.write(0x00); @@ -341,41 +341,41 @@ public class WebSocketMessageRFC6455Test output.write(0x00); output.write(buf,0,l+3); output.flush(); - + assertEquals(0x40+WebSocketConnectionRFC6455.OP_TEXT,input.read()); assertEquals(0x20+3,input.read()); assertEquals(0x7e,input.read()); assertEquals(0x02,input.read()); assertEquals(0x20,input.read()); - + byte[] raw = new byte[32]; assertEquals(32,input.read(raw)); - + Inflater inflater = new Inflater(); inflater.setInput(raw); - + byte[] result = new byte[544]; assertEquals(544,inflater.inflate(result)); assertEquals(TypeUtil.toHexString(data,0,544),TypeUtil.toHexString(result)); - + assertEquals((byte)0xC0,(byte)input.read()); assertEquals(0x21+3,input.read()); assertEquals(0x7e,input.read()); assertEquals(0x02,input.read()); assertEquals(0x21,input.read()); - + assertEquals(32,input.read(raw)); - + inflater.reset(); inflater.setInput(raw); result = new byte[545]; assertEquals(545,inflater.inflate(result)); assertEquals(TypeUtil.toHexString(data,544,545),TypeUtil.toHexString(result)); - + } - + @Test public void testServerEcho() throws Exception { @@ -403,10 +403,10 @@ public class WebSocketMessageRFC6455Test output.write(bytes[i]^0xff); output.flush(); // Make sure the read times out if there are problems with the implementation - socket.setSoTimeout(1000); + socket.setSoTimeout(1000); InputStream input = socket.getInputStream(); - + lookFor("HTTP/1.1 101 Switching Protocols\r\n",input); skipTo("Sec-WebSocket-Accept: ",input); lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); @@ -414,12 +414,12 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - + assertEquals(0x84,input.read()); assertEquals(0x0f,input.read()); lookFor("this is an echo",input); } - + @Test public void testBlockedConsumer() throws Exception { @@ -436,7 +436,7 @@ public class WebSocketMessageRFC6455Test mesg[5]=(byte)0xff; for (int i=0;i>> "+i); output.flush(); - + long now=System.currentTimeMillis(); long duration=now-start; start=now; @@ -518,13 +518,13 @@ public class WebSocketMessageRFC6455Test assertEquals(count+1,__textCount.get()); // all messages assertTrue(max>2000); // was blocked } - + @Test public void testBlockedProducer() throws Exception { final Socket socket = new Socket("localhost", __connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - + final int count = 100000; output.write( @@ -581,8 +581,8 @@ public class WebSocketMessageRFC6455Test } } }.start(); - - + + // Send enough messages to fill receive buffer long max=0; long start=System.currentTimeMillis(); @@ -593,7 +593,7 @@ public class WebSocketMessageRFC6455Test if (i%100==0) { output.flush(); - + long now=System.currentTimeMillis(); long duration=now-start; start=now; @@ -601,10 +601,10 @@ public class WebSocketMessageRFC6455Test max=duration; } } - + while(totalB.get()<(count*(mesg.length()+2))) Thread.sleep(100); - + assertEquals(count*(mesg.length()+2),totalB.get()); // all messages assertTrue(max>1000); // was blocked } @@ -635,7 +635,7 @@ public class WebSocketMessageRFC6455Test output.flush(); InputStream input = socket.getInputStream(); - + lookFor("HTTP/1.1 101 Switching Protocols\r\n",input); skipTo("Sec-WebSocket-Accept: ",input); lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); @@ -668,7 +668,7 @@ public class WebSocketMessageRFC6455Test socket.setSoTimeout(1000); InputStream input = socket.getInputStream(); - + lookFor("HTTP/1.1 101 Switching Protocols\r\n",input); skipTo("Sec-WebSocket-Accept: ",input); lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); @@ -676,10 +676,10 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - + __serverWebSocket.getConnection().setMaxTextMessageSize(10*1024); __serverWebSocket.getConnection().setAllowFrameFragmentation(true); - + output.write(0x81); output.write(0x80|0x7E); output.write((byte)((16*1024)>>8)); @@ -692,7 +692,7 @@ public class WebSocketMessageRFC6455Test for (int i=0;i<(16*1024);i++) output.write('X'); output.flush(); - + assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read()); assertEquals(33,input.read()); @@ -720,7 +720,7 @@ public class WebSocketMessageRFC6455Test socket.setSoTimeout(1000); InputStream input = socket.getInputStream(); - + lookFor("HTTP/1.1 101 Switching Protocols\r\n",input); skipTo("Sec-WebSocket-Accept: ",input); lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); @@ -728,9 +728,9 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - + __serverWebSocket.getConnection().setMaxTextMessageSize(15); - + output.write(0x01); output.write(0x8a); output.write(0xff); @@ -779,7 +779,7 @@ public class WebSocketMessageRFC6455Test socket.setSoTimeout(100000); InputStream input = socket.getInputStream(); - + lookFor("HTTP/1.1 101 Switching Protocols\r\n",input); skipTo("Sec-WebSocket-Accept: ",input); lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); @@ -787,9 +787,9 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - + __serverWebSocket.getConnection().setMaxTextMessageSize(15); - + output.write(0x01); output.write(0x94); output.write(0xff); @@ -800,9 +800,9 @@ public class WebSocketMessageRFC6455Test for (int i=0;i 15",input); } - - + + @Test public void testCloseIn() throws Exception { - int[][] tests = + int[][] tests = { {-1,0,-1}, {-1,0,-1}, @@ -960,7 +960,7 @@ public class WebSocketMessageRFC6455Test "", "mesg" }; - + String[] resp = { "", @@ -1007,14 +1007,14 @@ public class WebSocketMessageRFC6455Test int code=tests[t][0]; String m=mesg[t]; - + output.write(0x88); output.write(0x80 + (code<=0?0:(2+m.length()))); output.write(0x00); output.write(0x00); output.write(0x00); output.write(0x00); - + if (code>0) { output.write(code/0x100); @@ -1022,12 +1022,12 @@ public class WebSocketMessageRFC6455Test output.write(m.getBytes()); } output.flush(); - + __serverWebSocket.awaitDisconnected(1000); byte[] buf = new byte[128]; int len = input.read(buf); - + assertEquals(tst,2+tests[t][1],len); assertEquals(tst,(byte)0x88,buf[0]); @@ -1035,7 +1035,7 @@ public class WebSocketMessageRFC6455Test { code=(0xff&buf[2])*0x100+(0xff&buf[3]); assertEquals(tst,tests[t][2],code); - + if (len>4) { m = new String(buf,4,len-4,"UTF-8"); @@ -1044,19 +1044,19 @@ public class WebSocketMessageRFC6455Test } else assertEquals(tst,tests[t][2],-1); - + len = input.read(buf); assertEquals(tst,-1,len); } } - + @Test public void testCloseOut() throws Exception { - int[][] tests = + int[][] tests = { {-1,0,-1}, {-1,0,-1}, @@ -1127,7 +1127,7 @@ public class WebSocketMessageRFC6455Test { int code=(0xff&buf[2])*0x100+(0xff&buf[3]); assertEquals(tst,tests[t][2],code); - + if (len>4) { String m = new String(buf,4,len-4,"UTF-8"); @@ -1136,7 +1136,7 @@ public class WebSocketMessageRFC6455Test } else assertEquals(tst,tests[t][2],-1); - + try { output.write(0x88); @@ -1152,12 +1152,12 @@ public class WebSocketMessageRFC6455Test System.err.println("socket "+socket); throw e; } - + len = input.read(buf); assertEquals(tst,-1,len); - } + } } - + @Test public void testNotUTF8() throws Exception @@ -1225,7 +1225,7 @@ public class WebSocketMessageRFC6455Test socket.setSoTimeout(100000); InputStream input = socket.getInputStream(); - + lookFor("HTTP/1.1 101 Switching Protocols\r\n",input); skipTo("Sec-WebSocket-Accept: ",input); lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); @@ -1233,9 +1233,9 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - + __serverWebSocket.getConnection().setMaxBinaryMessageSize(15); - + output.write(0x02); output.write(0x94); output.write(0xff); @@ -1246,7 +1246,7 @@ public class WebSocketMessageRFC6455Test for (int i=0;i received = new AtomicReference(); ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096); - + WebSocketGeneratorRFC6455 gen = new WebSocketGeneratorRFC6455(new WebSocketBuffers(8096),endp,null); - + byte[] data = message.getBytes(StringUtil.__UTF8); gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length); - + endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096); - - WebSocketParserD13 parser = new WebSocketParserD13(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler() + + WebSocketParserRFC6455 parser = new WebSocketParserRFC6455(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler() { public void onFrame(byte flags, byte opcode, Buffer buffer) { @@ -1449,12 +1449,12 @@ public class WebSocketMessageRFC6455Test } },false); - + parser.parseNext(); - + assertEquals(message,received.get()); } - + @Test public void testParserAndGeneratorMasked() throws Exception { @@ -1463,14 +1463,14 @@ public class WebSocketMessageRFC6455Test ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096); MaskGen maskGen = new RandomMaskGen(); - + WebSocketGeneratorRFC6455 gen = new WebSocketGeneratorRFC6455(new WebSocketBuffers(8096),endp,maskGen); byte[] data = message.getBytes(StringUtil.__UTF8); gen.addFrame((byte)0x8,(byte)0x1,data,0,data.length); - + endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096); - - WebSocketParserD13 parser = new WebSocketParserD13(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler() + + WebSocketParserRFC6455 parser = new WebSocketParserRFC6455(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler() { public void onFrame(byte flags, byte opcode, Buffer buffer) { @@ -1481,13 +1481,13 @@ public class WebSocketMessageRFC6455Test { } },true); - + parser.parseNext(); - + assertEquals(message,received.get()); } - - + + private void lookFor(String string,InputStream in) throws IOException { @@ -1535,7 +1535,7 @@ public class WebSocketMessageRFC6455Test state=0; } } - + private static class TestWebSocket implements WebSocket.OnFrame, WebSocket.OnBinaryMessage, WebSocket.OnTextMessage { @@ -1556,7 +1556,7 @@ public class WebSocketMessageRFC6455Test { this.connection = connection; } - + public void onOpen(Connection connection) { if (_onConnect) @@ -1582,14 +1582,14 @@ public class WebSocketMessageRFC6455Test { return disconnected.await(time, TimeUnit.MILLISECONDS); } - + public void onClose(int code,String message) { disconnected.countDown(); } public boolean onFrame(byte flags, byte opcode, byte[] data, int offset, int length) - { + { if (_echo) { switch(opcode) @@ -1598,7 +1598,7 @@ public class WebSocketMessageRFC6455Test case WebSocketConnectionRFC6455.OP_PING: case WebSocketConnectionRFC6455.OP_PONG: break; - + default: try { @@ -1642,7 +1642,7 @@ public class WebSocketMessageRFC6455Test e.printStackTrace(); } } - + if (_aggregate) { try diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketOverSSLTest.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketOverSSLTest.java index 80b262d6392..524d8d0ece3 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketOverSSLTest.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketOverSSLTest.java @@ -35,6 +35,8 @@ public class WebSocketOverSSLTest { private Server _server; private int _port; + private QueuedThreadPool _threadPool; + private WebSocketClientFactory _wsFactory; private WebSocket.Connection _connection; private void startServer(final WebSocket webSocket) throws Exception @@ -61,13 +63,18 @@ public class WebSocketOverSSLTest { Assert.assertTrue(_server.isStarted()); - WebSocketClientFactory factory = new WebSocketClientFactory(new QueuedThreadPool(), new ZeroMaskGen()); - SslContextFactory cf = factory.getSslContextFactory(); + _threadPool = new QueuedThreadPool(); + _threadPool.setName("wsc-" + _threadPool.getName()); + _threadPool.start(); + + _wsFactory = new WebSocketClientFactory(_threadPool, new ZeroMaskGen()); + SslContextFactory cf = _wsFactory.getSslContextFactory(); cf.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath()); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); - factory.start(); - WebSocketClient client = new WebSocketClient(factory); + _wsFactory.start(); + + WebSocketClient client = new WebSocketClient(_wsFactory); _connection = client.open(new URI("wss://localhost:" + _port), webSocket).get(5, TimeUnit.SECONDS); } @@ -76,6 +83,13 @@ public class WebSocketOverSSLTest { if (_connection != null) _connection.close(); + + if (_wsFactory != null) + _wsFactory.stop(); + + if (_threadPool != null) + _threadPool.stop(); + if (_server != null) { _server.stop(); diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455Test.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455Test.java index 34d0f1efdd1..5d9e920dd76 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455Test.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455Test.java @@ -15,8 +15,6 @@ *******************************************************************************/ package org.eclipse.jetty.websocket; -import static org.junit.Assert.*; - import java.util.ArrayList; import java.util.List; @@ -30,12 +28,16 @@ import org.eclipse.jetty.util.Utf8StringBuilder; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + public class WebSocketParserRFC6455Test { private ByteArrayEndPoint _endPoint; private MaskedByteArrayBuffer _in; private Handler _handler; - private WebSocketParserD13 _parser; + private WebSocketParserRFC6455 _parser; private byte[] _mask = new byte[] {(byte)0x00,(byte)0xF0,(byte)0x0F,(byte)0xFF}; private int _m; @@ -45,7 +47,7 @@ public class WebSocketParserRFC6455Test { super(4096); } - + public void sendMask() { super.poke(putIndex(),_mask,0,4); @@ -63,7 +65,7 @@ public class WebSocketParserRFC6455Test { super.put(b); } - + @Override public void put(byte b) { @@ -87,10 +89,10 @@ public class WebSocketParserRFC6455Test { return put(b,0,b.length); } - + }; - - + + @Before public void setUp() throws Exception { @@ -98,10 +100,10 @@ public class WebSocketParserRFC6455Test _endPoint = new ByteArrayEndPoint(); _endPoint.setNonBlocking(true); _handler = new Handler(); - _parser=new WebSocketParserD13(buffers, _endPoint,_handler,true); + _parser=new WebSocketParserRFC6455(buffers, _endPoint,_handler,true); _parser.setFakeFragments(false); _in = new MaskedByteArrayBuffer(); - + _endPoint.setIn(_in); } @@ -127,7 +129,7 @@ public class WebSocketParserRFC6455Test _parser.returnBuffer(); assertTrue(_parser.getBuffer()==null); } - + @Test public void testShortText() throws Exception { @@ -147,7 +149,7 @@ public class WebSocketParserRFC6455Test _parser.returnBuffer(); assertTrue(_parser.getBuffer()==null); } - + @Test public void testShortUtf8() throws Exception { @@ -169,7 +171,7 @@ public class WebSocketParserRFC6455Test assertTrue(_parser.isBufferEmpty()); assertTrue(_parser.getBuffer()==null); } - + @Test public void testMediumText() throws Exception { @@ -177,9 +179,9 @@ public class WebSocketParserRFC6455Test for (int i=0;i<4;i++) string = string+string; string += ". The end."; - + byte[] bytes = string.getBytes(StringUtil.__UTF8); - + _in.putUnmasked((byte)0x81); _in.putUnmasked((byte)(0x80|0x7E)); _in.putUnmasked((byte)(bytes.length>>8)); @@ -197,21 +199,21 @@ public class WebSocketParserRFC6455Test assertTrue(_parser.isBufferEmpty()); assertTrue(_parser.getBuffer()==null); } - + @Test public void testLongText() throws Exception { WebSocketBuffers buffers = new WebSocketBuffers(0x20000); ByteArrayEndPoint endPoint = new ByteArrayEndPoint(); - WebSocketParserD13 parser=new WebSocketParserD13(buffers, endPoint,_handler,false); + WebSocketParserRFC6455 parser=new WebSocketParserRFC6455(buffers, endPoint,_handler,false); ByteArrayBuffer in = new ByteArrayBuffer(0x20000); endPoint.setIn(in); - + String string = "Hell\uFF4f Big W\uFF4Frld "; for (int i=0;i<12;i++) string = string+string; string += ". The end."; - + byte[] bytes = string.getBytes("UTF-8"); _in.sendMask(); @@ -269,7 +271,7 @@ public class WebSocketParserRFC6455Test { // Buffers are only 1024, so this frame is too large _parser.setFakeFragments(false); - + _in.putUnmasked((byte)0x81); _in.putUnmasked((byte)(0x80|0x7E)); _in.putUnmasked((byte)(2048>>8)); @@ -280,8 +282,8 @@ public class WebSocketParserRFC6455Test assertTrue(progress>0); assertEquals(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,_handler._code); - - + + for (int i=0;i<2048;i++) _in.put((byte)'a'); progress =_parser.parseNext(); @@ -289,7 +291,7 @@ public class WebSocketParserRFC6455Test assertTrue(progress>0); assertEquals(0,_handler._data.size()); assertEquals(0,_handler._utf8.length()); - + _handler._code=0; _in.putUnmasked((byte)0x81); @@ -310,7 +312,7 @@ public class WebSocketParserRFC6455Test { // Buffers are only 1024, so this frame will be fake fragmented _parser.setFakeFragments(true); - + _in.putUnmasked((byte)0x81); _in.putUnmasked((byte)(0x80|0x7E)); _in.putUnmasked((byte)(2048>>8)); @@ -318,7 +320,7 @@ public class WebSocketParserRFC6455Test _in.sendMask(); for (int i=0;i<2048;i++) _in.put((byte)('a'+i%26)); - + int progress =_parser.parseNext(); assertTrue(progress>0); @@ -355,21 +357,21 @@ public class WebSocketParserRFC6455Test _parser.returnBuffer(); assertTrue(_parser.isBufferEmpty()); assertTrue(_parser.getBuffer()==null); - + _in.clear(); _in.put(bytes); _endPoint.setIn(_in); progress =_parser.parseNext(); assertTrue(progress>0); - + _endPoint.shutdownInput(); - + progress =_parser.parseNext(); assertEquals(-1,progress); - + } - - + + private class Handler implements WebSocketParser.FrameHandler { Utf8StringBuilder _utf8 = new Utf8StringBuilder(); diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/CaptureSocket.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/CaptureSocket.java index 19233d4d297..de969280a34 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/CaptureSocket.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/CaptureSocket.java @@ -17,12 +17,14 @@ package org.eclipse.jetty.websocket.helper; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import org.eclipse.jetty.websocket.WebSocket; -public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage +public class CaptureSocket implements WebSocket.OnTextMessage { - private Connection conn; + private final CountDownLatch latch = new CountDownLatch(1); public List messages; public CaptureSocket() @@ -30,13 +32,9 @@ public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage messages = new ArrayList(); } - public boolean isConnected() + public boolean awaitConnected(long timeout) throws InterruptedException { - if (conn == null) - { - return false; - } - return conn.isOpen(); + return latch.await(timeout, TimeUnit.MILLISECONDS); } public void onMessage(String data) @@ -47,11 +45,10 @@ public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage public void onOpen(Connection connection) { - this.conn = connection; + latch.countDown(); } public void onClose(int closeCode, String message) { - this.conn = null; } -} \ No newline at end of file +} diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/SafariD00.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/SafariD00.java index 244e71cdc2d..85ab83c2ae4 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/SafariD00.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/SafariD00.java @@ -15,8 +15,6 @@ *******************************************************************************/ package org.eclipse.jetty.websocket.helper; -import static org.hamcrest.Matchers.*; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -32,6 +30,8 @@ import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.util.TypeUtil; import org.junit.Assert; +import static org.hamcrest.Matchers.is; + public class SafariD00 { private URI uri; @@ -48,7 +48,7 @@ public class SafariD00 /** * Open the Socket to the destination endpoint and - * + * * @return the open java Socket. * @throws IOException */ @@ -65,7 +65,7 @@ public class SafariD00 /** * Issue an Http websocket (Draft-0) upgrade request using the Safari particulars. - * + * * @throws UnsupportedEncodingException */ public void issueHandshake() throws IOException @@ -96,6 +96,8 @@ public class SafariD00 InputStreamReader reader = new InputStreamReader(in); BufferedReader br = new BufferedReader(reader); + socket.setSoTimeout(5000); + boolean foundEnd = false; String line; while (!foundEnd) diff --git a/test-jetty-webapp/pom.xml b/test-jetty-webapp/pom.xml index 22a57433367..4f5096f1684 100644 --- a/test-jetty-webapp/pom.xml +++ b/test-jetty-webapp/pom.xml @@ -5,7 +5,6 @@ 8.1.0-SNAPSHOT 4.0.0 - org.eclipse.jetty test-jetty-webapp Test :: Jetty Test Webapp war