diff --git a/example-jetty-embedded/pom.xml b/example-jetty-embedded/pom.xml index f2408d3a287..03da5633e3e 100644 --- a/example-jetty-embedded/pom.xml +++ b/example-jetty-embedded/pom.xml @@ -38,6 +38,11 @@ org.eclipse.jetty jetty-jmx ${project.version} + + + org.eclipse.jetty.spdy + spdy-jetty-http + ${project.version} org.eclipse.jetty.toolchain diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index 7c4083551cb..3c626d93f89 100644 --- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -27,8 +27,7 @@ import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpServerConnectionFactory; +import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.NCSARequestLog; import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; @@ -65,13 +64,11 @@ public class LikeJettyXml mbContainer.addBean(new Log()); // Setup Connectors - SelectChannelConnector connector = new SelectChannelConnector(server); + HttpConnectionFactory http = new HttpConnectionFactory(); + http.getHttpChannelConfig().setSecurePort(8443); + SelectChannelConnector connector = new SelectChannelConnector(server,http); connector.setPort(8080); connector.setIdleTimeout(30000); - HttpConfiguration httpConfiguration = new HttpConfiguration(null, false); - httpConfiguration.setConfidentialPort(8443); - connector.setDefaultConnectionFactory(new HttpServerConnectionFactory(connector, httpConfiguration)); - // TODO connector.setStatsOn(false); server.setConnectors(new Connector[] { connector }); @@ -94,7 +91,6 @@ public class LikeJettyXml }); SelectChannelConnector sslConnector = new SelectChannelConnector(server,sslContextFactory); sslConnector.setPort(8443); - // TODO sslConnector.setStatsOn(false); server.addConnector(sslConnector); sslConnector.open(); diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java index 4dc4411c806..1f308145000 100644 --- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java +++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java @@ -18,10 +18,23 @@ package org.eclipse.jetty.embedded; +import org.eclipse.jetty.io.ArrayByteBufferPool; +import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.ForwardedRequestCustomizer; +import org.eclipse.jetty.server.HttpChannelConfig; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.spdy.NPNServerConnectionFactory; +import org.eclipse.jetty.spdy.http.PushStrategy; +import org.eclipse.jetty.spdy.http.ReferrerPushStrategy; +import org.eclipse.jetty.spdy.http.HTTPSPDYServerConnectionFactory; import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.util.thread.TimerScheduler; /* ------------------------------------------------------------ */ /** @@ -32,31 +45,73 @@ public class ManyConnectors { public static void main(String[] args) throws Exception { + String jetty_home = System.getProperty("jetty.home","../jetty-server/src/main/config"); + System.setProperty("jetty.home", jetty_home); + Server server = new Server(); + // HTTP connector SelectChannelConnector connector0 = new SelectChannelConnector(server); connector0.setPort(8080); connector0.setIdleTimeout(30000); - SelectChannelConnector connector1 = new SelectChannelConnector(server); - connector1.setHost("127.0.0.1"); - connector1.setPort(8888); - - String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution"); - System.setProperty("jetty.home", jetty_home); + // HTTPS connector SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(jetty_home + "/etc/keystore"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); - SelectChannelConnector sslConnector = new SelectChannelConnector(server,sslContextFactory); - sslConnector.setPort(8443); - - server.setConnectors(new Connector[] - { connector0, connector1, sslConnector }); + + SelectChannelConnector connector1 = new SelectChannelConnector(server,sslContextFactory); + connector1.setPort(8443); + + + // A verbosely fully configured connector with SSL, SPDY and HTTP + + HttpChannelConfig config = new HttpChannelConfig(); + config.setSecureScheme("https"); + config.setSecurePort(8443); + config.setOutputBufferSize(32768); + config.setRequestHeaderSize(8192); + config.setResponseHeaderSize(8192); + config.addCustomizer(new ForwardedRequestCustomizer()); + config.addCustomizer(new SecureRequestCustomizer()); + + HttpConnectionFactory http = new HttpConnectionFactory(config); + http.setInputBufferSize(16384); + + PushStrategy push = new ReferrerPushStrategy(); + HTTPSPDYServerConnectionFactory spdy2 = new HTTPSPDYServerConnectionFactory(2,config,push); + spdy2.setInputBufferSize(8192); + spdy2.setInitialWindowSize(32768); + + HTTPSPDYServerConnectionFactory spdy3 = new HTTPSPDYServerConnectionFactory(3,config,push); + spdy2.setInputBufferSize(8192); + + NPNServerConnectionFactory npn = new NPNServerConnectionFactory(http.getProtocol(),spdy2.getProtocol(),spdy3.getProtocol()); + npn.setDefaultProtocol(http.getProtocol()); + npn.setInputBufferSize(1024); + + SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory,npn.getProtocol()); + + QueuedThreadPool threadPool = new QueuedThreadPool(); + threadPool.setMaxThreads(256); + TimerScheduler scheduler = new TimerScheduler(); + ByteBufferPool bufferPool= new ArrayByteBufferPool(32,4096,32768); + + SelectChannelConnector connector2 = new SelectChannelConnector(server,threadPool,scheduler,bufferPool,2,2,ssl,npn,spdy3,spdy2,http); + connector2.setDefaultProtocol("ssl-npn"); + connector2.setPort(8444); + connector2.setIdleTimeout(30000); + connector2.setSoLingerTime(10000); + + // Set the connectors + server.setConnectors(new Connector[] { connector0, connector1, connector2 }); + server.setHandler(new HelloHandler()); server.start(); + server.dumpStdErr(); server.join(); } } diff --git a/jetty-distribution/src/main/resources/start.ini b/jetty-distribution/src/main/resources/start.ini index b86d24d2c77..e9dfa9abd28 100644 --- a/jetty-distribution/src/main/resources/start.ini +++ b/jetty-distribution/src/main/resources/start.ini @@ -51,7 +51,7 @@ # for a full listing do # java -jar start.jar --list-options #----------------------------------------------------------- -OPTIONS=Server,jsp,resources,websocket,ext,plus +OPTIONS=Server,jsp,resources,websocket,ext #----------------------------------------------------------- @@ -64,7 +64,6 @@ etc/jetty.xml # etc/jetty-ssl.xml # etc/jetty-requestlog.xml etc/jetty-deploy.xml -#etc/jetty-overlay.xml etc/jetty-webapps.xml etc/jetty-contexts.xml etc/jetty-testrealm.xml diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java index 9c9862f8d52..3200d0edb36 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java @@ -47,6 +47,8 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; // TODO: Make this class inherit from oej.util.Fields +// TODO move this class to jetty-http? + /** * HTTP Fields. A collection of HTTP header and or Trailer fields. @@ -787,11 +789,11 @@ public class HttpFields implements Iterable // Format value and params StringBuilder buf = new StringBuilder(128); String name_value_params; - boolean quoted = QuotedStringTokenizer.quoteIfNeeded(buf, name, delim); + QuotedStringTokenizer.quoteIfNeeded(buf, name, delim); buf.append('='); String start=buf.toString(); if (value != null && value.length() > 0) - quoted|=QuotedStringTokenizer.quoteIfNeeded(buf, value, delim); + QuotedStringTokenizer.quoteIfNeeded(buf, value, delim); if (path != null && path.length() > 0) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 2db27b62bc5..9f7c3e04bef 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -59,9 +59,9 @@ public class HttpParser CLOSED }; - private final HttpHandler _handler; - private final RequestHandler _requestHandler; - private final ResponseHandler _responseHandler; + private final HttpHandler _handler; + private final RequestHandler _requestHandler; + private final ResponseHandler _responseHandler; private final int _maxHeaderBytes; private HttpHeader _header; private String _headerString; @@ -91,19 +91,19 @@ public class HttpParser private final Utf8StringBuilder _utf8=new Utf8StringBuilder(); /* ------------------------------------------------------------------------------- */ - public HttpParser(RequestHandler handler) + public HttpParser(RequestHandler handler) { this(handler,-1); } /* ------------------------------------------------------------------------------- */ - public HttpParser(ResponseHandler handler) + public HttpParser(ResponseHandler handler) { this(handler,-1); } /* ------------------------------------------------------------------------------- */ - public HttpParser(RequestHandler handler,int maxHeaderBytes) + public HttpParser(RequestHandler handler,int maxHeaderBytes) { _handler=handler; _requestHandler=handler; @@ -112,7 +112,7 @@ public class HttpParser } /* ------------------------------------------------------------------------------- */ - public HttpParser(ResponseHandler handler,int maxHeaderBytes) + public HttpParser(ResponseHandler handler,int maxHeaderBytes) { _handler=handler; _requestHandler=null; @@ -931,12 +931,14 @@ public class HttpParser case CLOSED: if (BufferUtil.hasContent(buffer)) { - _headerBytes+=buffer.remaining(); + int len=buffer.remaining(); + _headerBytes+=len; if (_headerBytes>_maxHeaderBytes) { + Thread.sleep(100); String chars = BufferUtil.toDetailString(buffer); BufferUtil.clear(buffer); - throw new IllegalStateException(this+" data when CLOSED: "+chars); + throw new IllegalStateException(String.format("%s %d/%d data when CLOSED:%s",this,len,_headerBytes,chars)); } BufferUtil.clear(buffer); } @@ -1182,6 +1184,7 @@ public class HttpParser } setState(State.CLOSED); _endOfContent=EndOfContent.UNKNOWN_CONTENT; + _contentLength=-1; _contentPosition=0; _responseStatus=0; _headerBytes=0; @@ -1194,6 +1197,7 @@ public class HttpParser // reset state setState(State.START); _endOfContent=EndOfContent.UNKNOWN_CONTENT; + _contentLength=-1; _contentPosition=0; _responseStatus=0; _contentChunk=null; diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java index aeebc0c6140..89f5bd4c292 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java @@ -115,9 +115,9 @@ public class HttpFieldsTest header.put("name:2", "value:\r\n2"); ByteBuffer buffer = BufferUtil.allocate(1024); - buffer.clear(); + BufferUtil.flipToFill(buffer); header.putTo(buffer); - buffer.flip(); + BufferUtil.flipToFlush(buffer,0); String out = BufferUtil.toString(buffer); assertThat(out,containsString("name0: value??0")); assertThat(out,containsString("name??1: value1")); @@ -134,9 +134,9 @@ public class HttpFieldsTest header.put("CONTENT-ENCODING", "gZIP"); ByteBuffer buffer = BufferUtil.allocate(1024); - buffer.clear(); + BufferUtil.flipToFill(buffer); header.putTo(buffer); - buffer.flip(); + BufferUtil.flipToFlush(buffer,0); String out = BufferUtil.toString(buffer); Assert.assertThat(out,Matchers.containsString(HttpHeader.CONNECTION+": "+HttpHeaderValue.KEEP_ALIVE)); diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java index abe1e1f7c3f..cb62efdbcb3 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java @@ -45,6 +45,8 @@ public abstract class AbstractConnection implements Connection private enum State {IDLE,INTERESTED,FILLING,FILLING_INTERESTED}; private final AtomicReference _state = new AtomicReference<>(State.IDLE); + private int _inputBufferSize=8192; + public AbstractConnection(EndPoint endp, Executor executor) { this(endp, executor, true); @@ -117,6 +119,16 @@ public abstract class AbstractConnection implements Connection } }; } + + public int getInputBufferSize() + { + return _inputBufferSize; + } + + public void setInputBufferSize(int inputBufferSize) + { + _inputBufferSize = inputBufferSize; + } public Executor getExecutor() { @@ -146,7 +158,6 @@ public abstract class AbstractConnection implements Connection break; case FILLING: - if (_state.compareAndSet(State.FILLING,State.FILLING_INTERESTED)) break loop; break; diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectChannelEndPoint.java index fa0c8507641..75822c86dcd 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectChannelEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectChannelEndPoint.java @@ -109,7 +109,10 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements SelectorMa Connection old = getConnection(); super.setConnection(connection); if (old != null && old != connection) + { + LOG.debug("Upgrading connection {} -> {} on endPoint {}", old, connection, this); _selector.getSelectorManager().connectionUpgraded(this, old); + } } @Override diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java index 3a669747c01..4422f9241f1 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java @@ -19,7 +19,9 @@ package org.eclipse.jetty.io.ssl; import java.io.IOException; +import java.net.SocketException; import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; import java.util.Arrays; import java.util.concurrent.Executor; import javax.net.ssl.SSLEngine; @@ -31,6 +33,7 @@ import javax.net.ssl.SSLException; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.AbstractEndPoint; import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.ChannelEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; @@ -111,6 +114,19 @@ public class SslConnection extends AbstractConnection this._bufferPool = byteBufferPool; this._sslEngine = sslEngine; this._decryptedEndPoint = new DecryptedEndPoint(); + + // TODO ugly + if (endPoint instanceof ChannelEndPoint) + { + try + { + ((SocketChannel)((ChannelEndPoint)endPoint).getChannel()).socket().setSoLinger(true,30000); + } + catch (SocketException e) + { + throw new RuntimeIOException(e); + } + } } public SSLEngine getSSLEngine() @@ -396,6 +412,18 @@ public class SslConnection extends AbstractConnection } } + @Override + public void setConnection(Connection connection) + { + if (connection instanceof AbstractConnection) + { + AbstractConnection a = (AbstractConnection)connection; + if (a.getInputBufferSize()<_sslEngine.getSession().getApplicationBufferSize()); + a.setInputBufferSize(_sslEngine.getSession().getApplicationBufferSize()); + } + super.setConnection(connection); + } + public SslConnection getSslConnection() { return SslConnection.this; diff --git a/jetty-plus/src/main/config/100-jetty-plus.ini b/jetty-plus/src/main/config/100-jetty-plus.ini new file mode 100644 index 00000000000..7e23d701fd0 --- /dev/null +++ b/jetty-plus/src/main/config/100-jetty-plus.ini @@ -0,0 +1,2 @@ +OPTIONS=plus +etc/jetty-plus.xml \ No newline at end of file diff --git a/jetty-plus/src/main/config/start.d b/jetty-plus/src/main/config/start.d new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java index d323fce2a72..a9e688bbfbb 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java @@ -28,9 +28,10 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; +import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.PathMap; import org.eclipse.jetty.server.HttpChannel; -import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpChannelConfig; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; import org.eclipse.jetty.server.UserIdentity; @@ -87,12 +88,14 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr /** * @return Returns the constraintMappings. */ + @Override public List getConstraintMappings() { return _constraintMappings; } /* ------------------------------------------------------------ */ + @Override public Set getRoles() { return _roles; @@ -134,6 +137,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr * The constraintMappings to set. * @param roles The known roles (or null to determine them from the mappings) */ + @Override public void setConstraintMappings(List constraintMappings, Set roles) { if (isStarted()) @@ -181,6 +185,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr /** * @see org.eclipse.jetty.security.ConstraintAware#addConstraintMapping(org.eclipse.jetty.security.ConstraintMapping) */ + @Override public void addConstraintMapping(ConstraintMapping mapping) { _constraintMappings.add(mapping); @@ -198,6 +203,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr /** * @see org.eclipse.jetty.security.ConstraintAware#addRole(java.lang.String) */ + @Override public void addRole(String role) { boolean modified = _roles.add(role); @@ -325,6 +331,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr } } + @Override protected RoleInfo prepareConstraintInfo(String pathInContext, Request request) { Map mappings = _constraintMap.match(pathInContext); @@ -354,34 +361,16 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr if (dataConstraint == null || dataConstraint == UserDataConstraint.None) return true; - HttpConfiguration httpConfiguration = HttpChannel.getCurrentHttpChannel().getHttpConfiguration(); + HttpChannelConfig httpConfig = HttpChannel.getCurrentHttpChannel().getHttpChannelConfig(); - if (dataConstraint == UserDataConstraint.Integral) + if (dataConstraint == UserDataConstraint.Confidential || dataConstraint == UserDataConstraint.Integral) { - if (httpConfiguration.isIntegral(request)) - return true; - if (httpConfiguration.getIntegralPort() > 0) - { - String url = httpConfiguration.getIntegralScheme() + "://" + request.getServerName() + ":" + httpConfiguration.getIntegralPort() + request.getRequestURI(); - if (request.getQueryString() != null) - url += "?" + request.getQueryString(); - response.setContentLength(0); - response.sendRedirect(url); - } - else - response.sendError(Response.SC_FORBIDDEN,"!Integral"); - - request.setHandled(true); - return false; - } - else if (dataConstraint == UserDataConstraint.Confidential) - { - if (httpConfiguration.isConfidential(request)) + if (request.isSecure()) return true; - if (httpConfiguration.getConfidentialPort() > 0) + if (httpConfig.getSecurePort() > 0) { - String url = httpConfiguration.getConfidentialScheme() + "://" + request.getServerName() + ":" + httpConfiguration.getConfidentialPort() + String url = httpConfig.getSecureScheme() + "://" + request.getServerName() + ":" + httpConfig.getSecurePort() + request.getRequestURI(); if (request.getQueryString() != null) url += "?" + request.getQueryString(); @@ -390,7 +379,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr response.sendRedirect(url); } else - response.sendError(Response.SC_FORBIDDEN,"!Confidential"); + response.sendError(HttpStatus.FORBIDDEN_403,"!Secure"); request.setHandled(true); return false; @@ -402,6 +391,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr } + @Override protected boolean isAuthMandatory(Request baseRequest, Response base_response, Object constraintInfo) { return constraintInfo != null && ((RoleInfo)constraintInfo).isChecked(); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java index 321031f0611..65c8eacc95a 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java @@ -28,8 +28,8 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpServerConnectionFactory; +import org.eclipse.jetty.server.HttpChannelConfig; +import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; @@ -60,38 +60,25 @@ public class DataConstraintsTest public void startServer() { _server = new Server(); - _connector = new LocalConnector(_server); + + HttpConnectionFactory http = new HttpConnectionFactory(); + http.getHttpChannelConfig().setSecurePort(9999); + http.getHttpChannelConfig().setSecureScheme("BWTP"); + _connector = new LocalConnector(_server,http); _connector.setIdleTimeout(300000); - HttpConfiguration httpConfiguration = new HttpConfiguration(null, false); - httpConfiguration.setIntegralPort(9998); - httpConfiguration.setIntegralScheme("FTP"); - httpConfiguration.setConfidentialPort(9999); - httpConfiguration.setConfidentialScheme("SPDY"); - _connector.setDefaultConnectionFactory(new HttpServerConnectionFactory(_connector, httpConfiguration)); - _connectorS = new LocalConnector(_server); - _connectorS.setDefaultConnectionFactory(new HttpServerConnectionFactory(_connectorS, new HttpConfiguration(null,false) + HttpConnectionFactory https = new HttpConnectionFactory(); + https.getHttpChannelConfig().addCustomizer(new HttpChannelConfig.Customizer() { @Override - public void customize(Request request) throws IOException + public void customize(Connector connector, HttpChannelConfig channelConfig, Request request) { request.setScheme(HttpScheme.HTTPS.asString()); - super.customize(request); + request.setSecure(true); } - - - @Override - public boolean isIntegral(Request request) - { - return true; - } - - @Override - public boolean isConfidential(Request request) - { - return true; - } - })); + }); + + _connectorS = new LocalConnector(_server,https); _server.setConnectors(new Connector[]{_connector,_connectorS}); ContextHandler _context = new ContextHandler(); @@ -106,6 +93,7 @@ public class DataConstraintsTest _security.setHandler(new AbstractHandler() { + @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); @@ -149,8 +137,8 @@ public class DataConstraintsTest response = _connector.getResponses("GET /ctx/integral/info HTTP/1.0\r\n\r\n"); assertThat(response, containsString("HTTP/1.1 302 Found")); - assertThat(response, containsString("Location: FTP://")); - assertThat(response, containsString(":9998")); + assertThat(response, containsString("Location: BWTP://")); + assertThat(response, containsString(":9999")); response = _connectorS.getResponses("GET /ctx/integral/info HTTP/1.0\r\n\r\n"); assertThat(response, containsString("HTTP/1.1 404 Not Found")); @@ -181,7 +169,7 @@ public class DataConstraintsTest response = _connector.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n"); assertThat(response, containsString("HTTP/1.1 302 Found")); - assertThat(response, containsString("Location: SPDY://")); + assertThat(response, containsString("Location: BWTP://")); assertThat(response, containsString(":9999")); response = _connectorS.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n"); @@ -444,11 +432,14 @@ public class DataConstraintsTest { this.identityService = identityService; } + + @Override public String getName() { return "name"; } + @Override public UserIdentity login(String username, Object credentials) { if("admin".equals(username) && "password".equals(credentials)) @@ -456,20 +447,24 @@ public class DataConstraintsTest return null; } + @Override public boolean validate(UserIdentity user) { return false; } + @Override public IdentityService getIdentityService() { return identityService; } + @Override public void setIdentityService(IdentityService service) { } + @Override public void logout(UserIdentity user) { } diff --git a/jetty-server/src/main/config/etc/jetty.xml b/jetty-server/src/main/config/etc/jetty.xml index 6d5a7e79409..9d0f8b6a961 100644 --- a/jetty-server/src/main/config/etc/jetty.xml +++ b/jetty-server/src/main/config/etc/jetty.xml @@ -38,7 +38,7 @@ - 300000 + 30000 diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnectionFactory.java new file mode 100644 index 00000000000..d11f33fe818 --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnectionFactory.java @@ -0,0 +1,78 @@ +// +// ======================================================================== +// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server; + +import org.eclipse.jetty.util.ArrayUtil; +import org.eclipse.jetty.util.component.AggregateLifeCycle; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public abstract class AbstractConnectionFactory extends AggregateLifeCycle implements ConnectionFactory +{ + final String _protocol; + int _inputbufferSize=8192; + + protected AbstractConnectionFactory(String protocol) + { + _protocol=protocol; + } + + @Override + public String getProtocol() + { + return _protocol; + } + + public int getInputBufferSize() + { + return _inputbufferSize; + } + + public void setInputBufferSize(int size) + { + _inputbufferSize=size; + } + + @Override + public String toString() + { + return String.format("%s@%x{%s}",this.getClass().getSimpleName(),hashCode(),getProtocol()); + } + + public static ConnectionFactory[] getFactories(SslContextFactory sslContextFactory, ConnectionFactory... factories) + { + factories=ArrayUtil.removeNulls(factories); + + if (sslContextFactory==null) + return factories; + + for (ConnectionFactory factory : factories) + { + if (factory instanceof HttpChannelConfig.ConnectionFactory) + { + HttpChannelConfig config = ((HttpChannelConfig.ConnectionFactory)factory).getHttpChannelConfig(); + if (config.getCustomizer(SecureRequestCustomizer.class)==null) + config.addCustomizer(new SecureRequestCustomizer()); + } + } + return ArrayUtil.prependToArray(new SslConnectionFactory(sslContextFactory,factories[0].getProtocol()),factories,ConnectionFactory.class); + + } + + +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java index 4afd4bdc0ee..6016dd2688b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java @@ -20,7 +20,10 @@ package org.eclipse.jetty.server; import java.io.IOException; import java.net.Socket; +import java.util.ArrayList; +import java.util.Collection; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; @@ -37,51 +40,63 @@ import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.TimerScheduler; /** *

Partial implementation of {@link Connector}

+ * + *

+ * The connector keeps a collection of {@link ConnectionFactory} instances, each of which are known by their + * protocol name. The protocol name may be a real protocol (eg http/1.1 or spdy/3) or it may be a private name + * that represents a special connection factory. For example, the name "SSL-http/1.1" is used for + * an {@link SslConnectionFactory} that has been instantiated with the {@link HttpConnectionFactory} as it's + * next protocol. + *

+ * If NPN is used to select the real protocol used by an SSL connection, then the name "SSL-NPN" is used, + * which represents a {@link SslConnectionFactory} with a NPNConnectionFactory as the next protocol. Once + * the NPN connection is established, it will get the next protocol from the NPN extension and then call + * {@link #getConnectionFactory(String)} to get the next connection factory. + * */ @ManagedObject("Abstract implementation of the Connector Interface") public abstract class AbstractConnector extends AggregateLifeCycle implements Connector, Dumpable { protected final Logger LOG = Log.getLogger(getClass()); // Order is important on server side, so we use a LinkedHashMap - private final Map factories = new LinkedHashMap<>(); + private final Map _factories = new LinkedHashMap<>(); private final Statistics _stats = new ConnectorStatistics(); private final Server _server; - private final SslContextFactory _sslContextFactory; private final Executor _executor; private final Scheduler _scheduler; private final ByteBufferPool _byteBufferPool; private final Thread[] _acceptors; private volatile CountDownLatch _stopping; - private volatile long _idleTimeout = 200000; - private volatile ConnectionFactory defaultConnectionFactory; + private long _idleTimeout = 200000; + private String _defaultProtocol; + private ConnectionFactory _defaultConnectionFactory; /** * @param server The server this connector will be added to. Must not be null. + * @param factory TODO + * @param sslContextFactory the SSL context factory to make this connector SSL enabled, or null * @param executor An executor for this connector or null to use the servers executor * @param scheduler A scheduler for this connector or null to use the servers scheduler * @param pool A buffer pool for this connector or null to use a default {@link ByteBufferPool} - * @param sslContextFactory the SSL context factory to make this connector SSL enabled, or null * @param acceptors the number of acceptor threads to use, or 0 for a default value. */ public AbstractConnector( Server server, Executor executor, Scheduler scheduler, - ByteBufferPool pool, - SslContextFactory sslContextFactory, - int acceptors) + ByteBufferPool pool, + int acceptors, + ConnectionFactory... factories) { _server=server; _executor=executor!=null?executor:_server.getThreadPool(); _scheduler=scheduler!=null?scheduler:new TimerScheduler(); _byteBufferPool = pool!=null?pool:new ArrayByteBufferPool(); - _sslContextFactory = sslContextFactory; addBean(_server,false); addBean(_executor); @@ -89,9 +104,11 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co unmanage(_executor); // inherited from server addBean(_scheduler); addBean(_byteBufferPool); - addBean(_sslContextFactory); addBean(_stats,true); + for (ConnectionFactory factory:factories) + addConnectionFactory(factory); + if (acceptors<=0) acceptors=Math.max(1,(Runtime.getRuntime().availableProcessors()) / 4); if (acceptors > 2 * Runtime.getRuntime().availableProcessors()) @@ -123,12 +140,6 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co return _byteBufferPool; } - @Override - public SslContextFactory getSslContextFactory() - { - return _sslContextFactory; - } - @Override public long getIdleTimeout() { @@ -162,10 +173,13 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co return _acceptors.length; } - @Override protected void doStart() throws Exception { + _defaultConnectionFactory = getConnectionFactory(_defaultProtocol); + if(_defaultConnectionFactory==null) + throw new IllegalStateException("No protocol factory for default protocol: "+_defaultProtocol); + super.doStart(); _stopping=new CountDownLatch(_acceptors.length); @@ -232,56 +246,97 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co return isRunning(); } + @Override public ConnectionFactory getConnectionFactory(String protocol) { - synchronized (factories) + synchronized (_factories) { - return factories.get(protocol); + return _factories.get(protocol.toLowerCase()); } } - public ConnectionFactory putConnectionFactory(String protocol, ConnectionFactory factory) + @Override + public T getConnectionFactory(Class factoryType) { - synchronized (factories) + synchronized (_factories) { - return factories.put(protocol, factory); + for (ConnectionFactory f : _factories.values()) + if (factoryType.isAssignableFrom(f.getClass())) + return (T)f; + return null; + } + } + + public void addConnectionFactory(ConnectionFactory factory) + { + synchronized (_factories) + { + ConnectionFactory old=_factories.remove(factory.getProtocol()); + if (old!=null) + removeBean(old); + _factories.put(factory.getProtocol().toLowerCase(), factory); + addBean(factory); + if (_defaultProtocol==null) + _defaultProtocol=factory.getProtocol(); } } public ConnectionFactory removeConnectionFactory(String protocol) { - synchronized (factories) + synchronized (_factories) { - return factories.remove(protocol); + ConnectionFactory factory= _factories.remove(protocol.toLowerCase()); + removeBean(factory); + return factory; } } - public Map getConnectionFactories() + @Override + public Collection getConnectionFactories() { - synchronized (factories) + synchronized (_factories) { - return new LinkedHashMap<>(factories); + return _factories.values(); + } + } + + @Override + public List getProtocols() + { + synchronized (_factories) + { + return new ArrayList<>(_factories.keySet()); } } public void clearConnectionFactories() { - synchronized (factories) + synchronized (_factories) { - factories.clear(); + _factories.clear(); } } + public String getDefaultProtocol() + { + return _defaultProtocol; + } + + public void setDefaultProtocol(String defaultProtocol) + { + if(isRunning()) + throw new IllegalStateException(getState()); + _defaultProtocol = defaultProtocol.toLowerCase(); + } + + @Override public ConnectionFactory getDefaultConnectionFactory() { - return defaultConnectionFactory; + if (isStarted()) + return _defaultConnectionFactory; + return getConnectionFactory(_defaultProtocol); } - - public void setDefaultConnectionFactory(ConnectionFactory defaultConnectionFactory) - { - this.defaultConnectionFactory = defaultConnectionFactory; - } - + private class Acceptor implements Runnable { private final int _acceptor; @@ -358,4 +413,13 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co { return _scheduler; } + + @Override + public String toString() + { + return String.format("%s@%x{%s}", + getClass().getSimpleName(), + hashCode(), + getDefaultProtocol()); + } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNetworkConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNetworkConnector.java index 21fafc7a50c..59070233d33 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNetworkConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNetworkConnector.java @@ -23,7 +23,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.Future; import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.Scheduler; /** @@ -34,9 +33,9 @@ public abstract class AbstractNetworkConnector extends AbstractConnector impleme private volatile String _host; private volatile int _port = 0; - public AbstractNetworkConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool pool, SslContextFactory sslContextFactory, int acceptors) + public AbstractNetworkConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool pool, int acceptors, ConnectionFactory... factories) { - super(server, executor, scheduler, pool, sslContextFactory, acceptors); + super(server,executor,scheduler,pool,acceptors,factories); } public void setHost(String host) @@ -110,8 +109,8 @@ public abstract class AbstractNetworkConnector extends AbstractConnector impleme @Override public String toString() { - return String.format("%s@%s:%d", - getClass().getSimpleName(), + return String.format("%s{%s:%d}", + super.toString(), getHost() == null ? "0.0.0.0" : getHost(), getLocalPort() <= 0 ? getPort() : getLocalPort()); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ByteBufferHttpInput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ByteBufferHttpInput.java index 680deb511f6..8d81c83c7b5 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ByteBufferHttpInput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ByteBufferHttpInput.java @@ -42,6 +42,5 @@ public class ByteBufferHttpInput extends HttpInput @Override protected void onContentConsumed(ByteBuffer item) { - item.clear(); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java index daad1fa5c9c..b129baf62f9 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java @@ -18,7 +18,6 @@ package org.eclipse.jetty.server; -import java.nio.channels.SocketChannel; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; @@ -28,12 +27,14 @@ import org.eclipse.jetty.io.EndPoint; */ public interface ConnectionFactory { + public String getProtocol(); + /** *

Creates a new {@link Connection} with the given parameters

- * @param channel the {@link SocketChannel} associated with the connection + * @param connector The {@link Connector} creating this connection * @param endPoint the {@link EndPoint} associated with the connection - * @param attachment the attachment associated with the connection * @return a new {@link Connection} */ - public Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment); + public Connection newConnection(Connector connector, EndPoint endPoint); + } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java index 908abd0db07..c37f3fd5463 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.server; +import java.util.Collection; +import java.util.List; import java.util.concurrent.Executor; import org.eclipse.jetty.io.ByteBufferPool; @@ -25,7 +27,6 @@ import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.component.Graceful; import org.eclipse.jetty.util.component.LifeCycle; -import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.Scheduler; /** @@ -57,10 +58,22 @@ public interface Connector extends LifeCycle, Graceful public ByteBufferPool getByteBufferPool(); /** - * @return the {@link SslContextFactory} associated with this {@link Connector} + * @return the {@link ConnectionFactory} associated with the protocol name */ - public SslContextFactory getSslContextFactory(); + public ConnectionFactory getConnectionFactory(String nextProtocol); + + public T getConnectionFactory(Class factoryType); + + /** + * @return the default {@link ConnectionFactory} associated with the default protocol name + */ + public ConnectionFactory getDefaultConnectionFactory(); + + public Collection getConnectionFactories(); + + public List getProtocols(); + /** * @return the dle timeout for connections in milliseconds */ @@ -199,4 +212,6 @@ public interface Connector extends LifeCycle, Graceful */ public void connectionClosed(long duration, int messagesIn, int messagesOut); } + + } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java index 90954666c6f..9919323211b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; + import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java new file mode 100644 index 00000000000..8f9f5825d76 --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -0,0 +1,280 @@ +// +// ======================================================================== +// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server; + +import java.net.InetSocketAddress; + +import javax.servlet.ServletRequest; + +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.server.HttpChannelConfig.Customizer; + +public class ForwardedRequestCustomizer implements Customizer +{ + private String _hostHeader; + private String _forwardedHostHeader = HttpHeader.X_FORWARDED_HOST.toString(); + private String _forwardedServerHeader = HttpHeader.X_FORWARDED_SERVER.toString(); + private String _forwardedForHeader = HttpHeader.X_FORWARDED_FOR.toString(); + private String _forwardedProtoHeader = HttpHeader.X_FORWARDED_PROTO.toString(); + private String _forwardedCipherSuiteHeader; + private String _forwardedSslSessionIdHeader; + + + /* ------------------------------------------------------------ */ + public String getHostHeader() + { + return _hostHeader; + } + + /* ------------------------------------------------------------ */ + /** + * Set a forced valued for the host header to control what is returned by {@link ServletRequest#getServerName()} and {@link ServletRequest#getServerPort()}. + * This value is only used if {@link #isForwarded()} is true. + * + * @param hostHeader + * The value of the host header to force. + */ + public void setHostHeader(String hostHeader) + { + _hostHeader = hostHeader; + } + + /* ------------------------------------------------------------ */ + /* + * + * @see #setForwarded(boolean) + */ + public String getForwardedHostHeader() + { + return _forwardedHostHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @param forwardedHostHeader + * The header name for forwarded hosts (default x-forwarded-host) + * @see #setForwarded(boolean) + */ + public void setForwardedHostHeader(String forwardedHostHeader) + { + _forwardedHostHeader = forwardedHostHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @return the header name for forwarded server. + * @see #setForwarded(boolean) + */ + public String getForwardedServerHeader() + { + return _forwardedServerHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @param forwardedServerHeader + * The header name for forwarded server (default x-forwarded-server) + * @see #setForwarded(boolean) + */ + public void setForwardedServerHeader(String forwardedServerHeader) + { + _forwardedServerHeader = forwardedServerHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @return the forwarded for header + * @see #setForwarded(boolean) + */ + public String getForwardedForHeader() + { + return _forwardedForHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @param forwardedRemoteAddressHeader + * The header name for forwarded for (default x-forwarded-for) + * @see #setForwarded(boolean) + */ + public void setForwardedForHeader(String forwardedRemoteAddressHeader) + { + _forwardedForHeader = forwardedRemoteAddressHeader; + } + + /* ------------------------------------------------------------ */ + /** + * Get the forwardedProtoHeader. + * + * @return the forwardedProtoHeader (default X-Forwarded-For) + * @see #setForwarded(boolean) + */ + public String getForwardedProtoHeader() + { + return _forwardedProtoHeader; + } + + /* ------------------------------------------------------------ */ + /** + * Set the forwardedProtoHeader. + * + * @param forwardedProtoHeader + * the forwardedProtoHeader to set (default X-Forwarded-For) + * @see #setForwarded(boolean) + */ + public void setForwardedProtoHeader(String forwardedProtoHeader) + { + _forwardedProtoHeader = forwardedProtoHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @return The header name holding a forwarded cipher suite (default null) + */ + public String getForwardedCipherSuiteHeader() + { + return _forwardedCipherSuiteHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @param forwardedCipherSuite + * The header name holding a forwarded cipher suite (default null) + */ + public void setForwardedCipherSuiteHeader(String forwardedCipherSuite) + { + _forwardedCipherSuiteHeader = forwardedCipherSuite; + } + + /* ------------------------------------------------------------ */ + /** + * @return The header name holding a forwarded SSL Session ID (default null) + */ + public String getForwardedSslSessionIdHeader() + { + return _forwardedSslSessionIdHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @param forwardedSslSessionId + * The header name holding a forwarded SSL Session ID (default null) + */ + public void setForwardedSslSessionIdHeader(String forwardedSslSessionId) + { + _forwardedSslSessionIdHeader = forwardedSslSessionId; + } + + /* ------------------------------------------------------------ */ + @Override + public void customize(Connector connector, HttpChannelConfig config, Request request) + { + HttpFields httpFields = request.getHttpFields(); + + // Do SSL first + if (getForwardedCipherSuiteHeader()!=null) + { + String cipher_suite=httpFields.getStringField(getForwardedCipherSuiteHeader()); + if (cipher_suite!=null) + request.setAttribute("javax.servlet.request.cipher_suite",cipher_suite); + } + if (getForwardedSslSessionIdHeader()!=null) + { + String ssl_session_id=httpFields.getStringField(getForwardedSslSessionIdHeader()); + if(ssl_session_id!=null) + { + request.setAttribute("javax.servlet.request.ssl_session_id", ssl_session_id); + request.setScheme(HttpScheme.HTTPS.asString()); + } + } + + // Retrieving headers from the request + String forwardedHost = getLeftMostFieldValue(httpFields,getForwardedHostHeader()); + String forwardedServer = getLeftMostFieldValue(httpFields,getForwardedServerHeader()); + String forwardedFor = getLeftMostFieldValue(httpFields,getForwardedForHeader()); + String forwardedProto = getLeftMostFieldValue(httpFields,getForwardedProtoHeader()); + + if (_hostHeader != null) + { + // Update host header + httpFields.put(HttpHeader.HOST.toString(),_hostHeader); + request.setServerName(null); + request.setServerPort(-1); + request.getServerName(); + } + else if (forwardedHost != null) + { + // Update host header + httpFields.put(HttpHeader.HOST.toString(),forwardedHost); + request.setServerName(null); + request.setServerPort(-1); + request.getServerName(); + } + else if (forwardedServer != null) + { + // Use provided server name + request.setServerName(forwardedServer); + } + + if (forwardedFor != null) + { + request.setRemoteAddr(new InetSocketAddress(forwardedFor,request.getRemotePort())); + } + + if (forwardedProto != null) + { + request.setScheme(forwardedProto); + if (forwardedProto.equals(config.getSecureScheme())) + request.setSecure(true); + } + } + + /* ------------------------------------------------------------ */ + protected String getLeftMostFieldValue(HttpFields fields, String header) + { + if (header == null) + return null; + + String headerValue = fields.getStringField(header); + + if (headerValue == null) + return null; + + int commaIndex = headerValue.indexOf(','); + + if (commaIndex == -1) + { + // Single value + return headerValue; + } + + // The left-most value is the farthest downstream client + return headerValue.substring(0,commaIndex); + } + + + /* ------------------------------------------------------------ */ + @Override + public String toString() + { + return String.format("%s@%x",this.getClass().getSimpleName(),hashCode()); + } +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java index b2715a9c634..1a6205f59ef 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.server; import java.io.IOException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 29fac7f48a2..24536935237 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -23,6 +23,7 @@ import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; + import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; @@ -63,14 +64,14 @@ import org.eclipse.jetty.util.thread.Scheduler; public class HttpChannel implements HttpParser.RequestHandler, Runnable { private static final Logger LOG = Log.getLogger(HttpChannel.class); - private static final ThreadLocal __currentChannel = new ThreadLocal<>(); + private static final ThreadLocal> __currentChannel = new ThreadLocal<>(); - public static HttpChannel getCurrentHttpChannel() + public static HttpChannel getCurrentHttpChannel() { return __currentChannel.get(); } - protected static void setCurrentHttpChannel(HttpChannel channel) + protected static void setCurrentHttpChannel(HttpChannel channel) { __currentChannel.set(channel); } @@ -78,7 +79,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable private final AtomicBoolean _committed = new AtomicBoolean(); private final AtomicInteger _requests = new AtomicInteger(); private final Connector _connector; - private final HttpConfiguration _configuration; + private final HttpChannelConfig _configuration; private final EndPoint _endPoint; private final HttpTransport _transport; private final HttpURI _uri; @@ -90,7 +91,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable private boolean _expect100Continue = false; private boolean _expect102Processing = false; - public HttpChannel(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransport transport, HttpInput input) + public HttpChannel(Connector connector, HttpChannelConfig configuration, EndPoint endPoint, HttpTransport transport, HttpInput input) { _connector = connector; _configuration = configuration; @@ -131,7 +132,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable return _connector.getByteBufferPool(); } - public HttpConfiguration getHttpConfiguration() + public HttpChannelConfig getHttpChannelConfig() { return _configuration; } @@ -237,8 +238,11 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable if (_state.isInitial()) { + _request.setTimeStamp(System.currentTimeMillis()); _request.setDispatcherType(DispatcherType.REQUEST); - getHttpConfiguration().customize(_request); + + for (HttpChannelConfig.Customizer customizer : _configuration.getCustomizers()) + customizer.customize(getConnector(),_configuration,_request); getServer().handle(this); } else @@ -321,7 +325,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable if (_state.isSuspended()) { HttpFields fields = new HttpFields(); - ResponseInfo info = new ResponseInfo(_request.getHttpVersion(), fields, 0, Response.SC_INTERNAL_SERVER_ERROR, null, _request.isHead()); + ResponseInfo info = new ResponseInfo(_request.getHttpVersion(), fields, 0, HttpStatus.INTERNAL_SERVER_ERROR_500, null, _request.isHead()); boolean committed = commitResponse(info, null, true); if (!committed) LOG.warn("Could not send response error 500: "+x); @@ -515,7 +519,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable if (LOG.isDebugEnabled()) LOG.debug("{} content {}", this, item); @SuppressWarnings("unchecked") - HttpInput input = _request.getHttpInput(); + HttpInput input = (HttpInput)_request.getHttpInput(); input.content(item); return true; } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelConfig.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelConfig.java new file mode 100644 index 00000000000..2ef9016b82c --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelConfig.java @@ -0,0 +1,124 @@ +// +// ======================================================================== +// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.eclipse.jetty.http.HttpScheme; + +public class HttpChannelConfig +{ + private List _customizers=new CopyOnWriteArrayList<>(); + private int _outputBufferSize=32*1024; + private int _requestHeaderSize=8*1024; + private int _responseHeaderSize=8*1024; + private int _securePort; + private String _secureScheme = HttpScheme.HTTPS.asString(); + + public interface Customizer + { + public void customize(Connector connector, HttpChannelConfig channelConfig, Request request); + } + + public interface ConnectionFactory + { + HttpChannelConfig getHttpChannelConfig(); + } + + public void addCustomizer(Customizer customizer) + { + _customizers.add(customizer); + } + + public List getCustomizers() + { + return _customizers; + } + + public T getCustomizer(Class type) + { + for (Customizer c : _customizers) + if (type.isAssignableFrom(c.getClass())) + return (T)c; + return null; + } + + public int getOutputBufferSize() + { + return _outputBufferSize; + } + + public int getRequestHeaderSize() + { + return _requestHeaderSize; + } + + public int getResponseHeaderSize() + { + return _responseHeaderSize; + } + + public int getSecurePort() + { + return _securePort; + } + + public String getSecureScheme() + { + return _secureScheme; + } + + public void setCustomizers(List customizers) + { + _customizers.clear(); + _customizers.addAll(customizers); + } + + public void setOutputBufferSize(int responseBufferSize) + { + _outputBufferSize = responseBufferSize; + } + + public void setRequestHeaderSize(int requestHeaderSize) + { + _requestHeaderSize = requestHeaderSize; + } + + public void setResponseHeaderSize(int responseHeaderSize) + { + _responseHeaderSize = responseHeaderSize; + } + + public void setSecurePort(int confidentialPort) + { + _securePort = confidentialPort; + } + + public void setSecureScheme(String confidentialScheme) + { + _secureScheme = confidentialScheme; + } + + @Override + public String toString() + { + return String.format("%s@%x{%d,%d/%d,%s://:%d,%s}",this.getClass().getSimpleName(),hashCode(),_outputBufferSize,_requestHeaderSize,_responseHeaderSize,_secureScheme,_securePort,_customizers); + } +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java index 83e7f0ee079..04c3b7008b1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; + import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java deleted file mode 100644 index 266b22f3e8b..00000000000 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java +++ /dev/null @@ -1,556 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.server; - -import java.io.IOException; -import java.net.InetSocketAddress; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLSession; -import javax.servlet.ServletRequest; - -import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.http.HttpScheme; -import org.eclipse.jetty.io.ssl.SslConnection; -import org.eclipse.jetty.server.ssl.SslCertificates; -import org.eclipse.jetty.util.component.AggregateLifeCycle; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.ssl.SslContextFactory; - - -public class HttpConfiguration extends AggregateLifeCycle -{ - static final Logger LOG = Log.getLogger(HttpConfiguration.class); - - private final SslContextFactory _sslContextFactory; - private final boolean _ssl; - - private String _integralScheme = HttpScheme.HTTPS.asString(); - private int _integralPort = 0; - private String _confidentialScheme = HttpScheme.HTTPS.asString(); - private int _confidentialPort = 0; - private boolean _forwarded; - private String _hostHeader; - private String _forwardedHostHeader = HttpHeader.X_FORWARDED_HOST.toString(); - private String _forwardedServerHeader = HttpHeader.X_FORWARDED_SERVER.toString(); - private String _forwardedForHeader = HttpHeader.X_FORWARDED_FOR.toString(); - private String _forwardedProtoHeader = HttpHeader.X_FORWARDED_PROTO.toString(); - private String _forwardedCipherSuiteHeader; - private String _forwardedSslSessionIdHeader; - private int _requestHeaderSize=8*1024; - private int _requestBufferSize=16*1024; - private int _responseHeaderSize=8*1024; - private int _responseBufferSize=32*1024; - - public HttpConfiguration(SslContextFactory sslContextFactory,boolean ssl) - { - _sslContextFactory=sslContextFactory!=null?sslContextFactory:ssl?new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH):null; - _ssl=ssl; - if (_sslContextFactory!=null) - addBean(_sslContextFactory,sslContextFactory==null); - } - - public SslContextFactory getSslContextFactory() - { - return _sslContextFactory; - } - - public boolean isSecure() - { - return _ssl; - } - - public int getRequestHeaderSize() - { - return _requestHeaderSize; - } - - public void setRequestHeaderSize(int requestHeaderSize) - { - _requestHeaderSize = requestHeaderSize; - } - - public int getRequestBufferSize() - { - return _requestBufferSize; - } - - public void setRequestBufferSize(int requestBufferSize) - { - _requestBufferSize = requestBufferSize; - } - - public int getResponseHeaderSize() - { - return _responseHeaderSize; - } - - public void setResponseHeaderSize(int responseHeaderSize) - { - _responseHeaderSize = responseHeaderSize; - } - - public int getResponseBufferSize() - { - return _responseBufferSize; - } - - public void setResponseBufferSize(int responseBufferSize) - { - _responseBufferSize = responseBufferSize; - } - - /* ------------------------------------------------------------ */ - /** - * Allow the Listener a chance to customise the request. before the server - * does its stuff.
- * This allows the required attributes to be set for SSL requests.
- * The requirements of the Servlet specs are: - *
    - *
  • an attribute named "javax.servlet.request.ssl_session_id" of type - * String (since Servlet Spec 3.0).
  • - *
  • an attribute named "javax.servlet.request.cipher_suite" of type - * String.
  • - *
  • an attribute named "javax.servlet.request.key_size" of type Integer.
  • - *
  • an attribute named "javax.servlet.request.X509Certificate" of type - * java.security.cert.X509Certificate[]. This is an array of objects of type - * X509Certificate, the order of this array is defined as being in ascending - * order of trust. The first certificate in the chain is the one set by the - * client, the next is the one used to authenticate the first, and so on. - *
  • - *
- */ - public void customize(Request request) throws IOException - { - if (isSecure()) - { - request.setScheme(HttpScheme.HTTPS.asString()); - SslConnection.DecryptedEndPoint ssl_endp = (SslConnection.DecryptedEndPoint)request.getHttpChannel().getEndPoint(); - SslConnection sslConnection = ssl_endp.getSslConnection(); - SSLEngine sslEngine=sslConnection.getSSLEngine(); - SslCertificates.customize(sslEngine,request); - } - - request.setTimeStamp(System.currentTimeMillis()); - if (isForwarded()) - checkForwardedHeaders(request); - } - - /* ------------------------------------------------------------ */ - protected void checkForwardedHeaders(Request request) throws IOException - { - HttpFields httpFields = request.getHttpFields(); - - // Do SSL first - if (getForwardedCipherSuiteHeader()!=null) - { - String cipher_suite=httpFields.getStringField(getForwardedCipherSuiteHeader()); - if (cipher_suite!=null) - request.setAttribute("javax.servlet.request.cipher_suite",cipher_suite); - } - if (getForwardedSslSessionIdHeader()!=null) - { - String ssl_session_id=httpFields.getStringField(getForwardedSslSessionIdHeader()); - if(ssl_session_id!=null) - { - request.setAttribute("javax.servlet.request.ssl_session_id", ssl_session_id); - request.setScheme(HttpScheme.HTTPS.asString()); - } - } - - // Retrieving headers from the request - String forwardedHost = getLeftMostFieldValue(httpFields,getForwardedHostHeader()); - String forwardedServer = getLeftMostFieldValue(httpFields,getForwardedServerHeader()); - String forwardedFor = getLeftMostFieldValue(httpFields,getForwardedForHeader()); - String forwardedProto = getLeftMostFieldValue(httpFields,getForwardedProtoHeader()); - - if (_hostHeader != null) - { - // Update host header - httpFields.put(HttpHeader.HOST.toString(),_hostHeader); - request.setServerName(null); - request.setServerPort(-1); - request.getServerName(); - } - else if (forwardedHost != null) - { - // Update host header - httpFields.put(HttpHeader.HOST.toString(),forwardedHost); - request.setServerName(null); - request.setServerPort(-1); - request.getServerName(); - } - else if (forwardedServer != null) - { - // Use provided server name - request.setServerName(forwardedServer); - } - - if (forwardedFor != null) - { - request.setRemoteAddr(new InetSocketAddress(forwardedFor,request.getRemotePort())); - } - - if (forwardedProto != null) - { - request.setScheme(forwardedProto); - } - } - - /* ------------------------------------------------------------ */ - protected String getLeftMostFieldValue(HttpFields fields, String header) - { - if (header == null) - return null; - - String headerValue = fields.getStringField(header); - - if (headerValue == null) - return null; - - int commaIndex = headerValue.indexOf(','); - - if (commaIndex == -1) - { - // Single value - return headerValue; - } - - // The left-most value is the farthest downstream client - return headerValue.substring(0,commaIndex); - } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#getConfidentialPort() - */ - public int getConfidentialPort() - { - return _confidentialPort; - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#getConfidentialScheme() - */ - public String getConfidentialScheme() - { - return _confidentialScheme; - } - - /* ------------------------------------------------------------ */ - /** - * The request is integral IFF it is secure AND the server port - * matches any configured {@link #getIntegralPort()}. - * This allows separation of listeners providing INTEGRAL versus - * CONFIDENTIAL constraints, such as one SSL listener configured to require - * client certs providing CONFIDENTIAL, whereas another SSL listener not - * requiring client certs providing mere INTEGRAL constraints. - *

- * The request is secure if it is SSL or it {@link #isForwarded()} is true - * and the scheme matches {@link #getIntegralScheme()()} - */ - public boolean isIntegral(Request request) - { - boolean https = isSecure() || _forwarded && _integralScheme.equalsIgnoreCase(request.getScheme()); - int iPort=getIntegralPort(); - boolean port = iPort<=0||iPort==request.getServerPort(); - return https && port; - } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#getConfidentialPort() - */ - public int getIntegralPort() - { - return _integralPort; - } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#getIntegralScheme() - */ - public String getIntegralScheme() - { - return _integralScheme; - } - - /* ------------------------------------------------------------ */ - /** - * The request is confidential IFF it is secure AND the server port - * matches any configured {@link #getConfidentialPort()}. - * This allows separation of listeners providing INTEGRAL versus - * CONFIDENTIAL constraints, such as one SSL listener configured to require - * client certs providing CONFIDENTIAL, whereas another SSL listener not - * requiring client certs providing mere INTEGRAL constraints. - *

- * The request is secure if it is SSL or it {@link #isForwarded()} is true - * and the scheme matches {@link #getConfidentialScheme()} - */ - public boolean isConfidential(Request request) - { - boolean https = isSecure() || _forwarded && _confidentialScheme.equalsIgnoreCase(request.getScheme()); - int confidentialPort=getConfidentialPort(); - boolean port = confidentialPort<=0||confidentialPort==request.getServerPort(); - return https && port; - } - - /* ------------------------------------------------------------ */ - /** - * @param confidentialPort - * The confidentialPort to set. - */ - public void setConfidentialPort(int confidentialPort) - { - _confidentialPort = confidentialPort; - } - - /* ------------------------------------------------------------ */ - /** - * @param confidentialScheme - * The confidentialScheme to set. - */ - public void setConfidentialScheme(String confidentialScheme) - { - _confidentialScheme = confidentialScheme; - } - - /* ------------------------------------------------------------ */ - /** - * @param integralPort - * The integralPort to set. - */ - public void setIntegralPort(int integralPort) - { - _integralPort = integralPort; - } - - /* ------------------------------------------------------------ */ - /** - * @param integralScheme - * The integralScheme to set. - */ - public void setIntegralScheme(String integralScheme) - { - _integralScheme = integralScheme; - } - - /* ------------------------------------------------------------ */ - /** - * Is reverse proxy handling on? - * - * @return true if this connector is checking the x-forwarded-for/host/server headers - */ - public boolean isForwarded() - { - return _forwarded; - } - - /* ------------------------------------------------------------ */ - /** - * Set reverse proxy handling. If set to true, then the X-Forwarded headers (or the headers set in their place) are looked for to set the request protocol, - * host, server and client ip. - * - * @param check true if this connector is checking the x-forwarded-for/host/server headers - * @see #setForwardedForHeader(String) - * @see #setForwardedHostHeader(String) - * @see #setForwardedProtoHeader(String) - * @see #setForwardedServerHeader(String) - */ - public void setForwarded(boolean check) - { - if (check) - LOG.debug("{} is forwarded",this); - _forwarded = check; - } - - /* ------------------------------------------------------------ */ - public String getHostHeader() - { - return _hostHeader; - } - - /* ------------------------------------------------------------ */ - /** - * Set a forced valued for the host header to control what is returned by {@link ServletRequest#getServerName()} and {@link ServletRequest#getServerPort()}. - * This value is only used if {@link #isForwarded()} is true. - * - * @param hostHeader - * The value of the host header to force. - */ - public void setHostHeader(String hostHeader) - { - _hostHeader = hostHeader; - } - - /* ------------------------------------------------------------ */ - /* - * - * @see #setForwarded(boolean) - */ - public String getForwardedHostHeader() - { - return _forwardedHostHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedHostHeader - * The header name for forwarded hosts (default x-forwarded-host) - * @see #setForwarded(boolean) - */ - public void setForwardedHostHeader(String forwardedHostHeader) - { - _forwardedHostHeader = forwardedHostHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @return the header name for forwarded server. - * @see #setForwarded(boolean) - */ - public String getForwardedServerHeader() - { - return _forwardedServerHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedServerHeader - * The header name for forwarded server (default x-forwarded-server) - * @see #setForwarded(boolean) - */ - public void setForwardedServerHeader(String forwardedServerHeader) - { - _forwardedServerHeader = forwardedServerHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @return the forwarded for header - * @see #setForwarded(boolean) - */ - public String getForwardedForHeader() - { - return _forwardedForHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedRemoteAddressHeader - * The header name for forwarded for (default x-forwarded-for) - * @see #setForwarded(boolean) - */ - public void setForwardedForHeader(String forwardedRemoteAddressHeader) - { - _forwardedForHeader = forwardedRemoteAddressHeader; - } - - /* ------------------------------------------------------------ */ - /** - * Get the forwardedProtoHeader. - * - * @return the forwardedProtoHeader (default X-Forwarded-For) - * @see #setForwarded(boolean) - */ - public String getForwardedProtoHeader() - { - return _forwardedProtoHeader; - } - - /* ------------------------------------------------------------ */ - /** - * Set the forwardedProtoHeader. - * - * @param forwardedProtoHeader - * the forwardedProtoHeader to set (default X-Forwarded-For) - * @see #setForwarded(boolean) - */ - public void setForwardedProtoHeader(String forwardedProtoHeader) - { - _forwardedProtoHeader = forwardedProtoHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @return The header name holding a forwarded cipher suite (default null) - */ - public String getForwardedCipherSuiteHeader() - { - return _forwardedCipherSuiteHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedCipherSuite - * The header name holding a forwarded cipher suite (default null) - */ - public void setForwardedCipherSuiteHeader(String forwardedCipherSuite) - { - _forwardedCipherSuiteHeader = forwardedCipherSuite; - } - - /* ------------------------------------------------------------ */ - /** - * @return The header name holding a forwarded SSL Session ID (default null) - */ - public String getForwardedSslSessionIdHeader() - { - return _forwardedSslSessionIdHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedSslSessionId - * The header name holding a forwarded SSL Session ID (default null) - */ - public void setForwardedSslSessionIdHeader(String forwardedSslSessionId) - { - _forwardedSslSessionIdHeader = forwardedSslSessionId; - } - - - /* ------------------------------------------------------------ */ - @Override - protected void doStart() throws Exception - { - if (_sslContextFactory!=null) - { - _sslContextFactory.checkKeyStore(); - - super.doStart(); - - SSLEngine sslEngine = _sslContextFactory.newSSLEngine(); - - sslEngine.setUseClientMode(false); - - SSLSession sslSession = sslEngine.getSession(); - - if (getRequestHeaderSize() __currentConnection = new ThreadLocal<>(); - private final HttpConfiguration _configuration; + private final HttpChannelConfig _config; private final Connector _connector; - private final ByteBufferPool _bufferPool; // TODO: remove field, use a _connector.getByteBufferPool() + private final ByteBufferPool _bufferPool; private final HttpGenerator _generator; private final HttpChannelOverHttp _channel; private final HttpParser _parser; - private ByteBuffer _requestBuffer = null; - private ByteBuffer _chunk = null; + private volatile ByteBuffer _requestBuffer = null; + private volatile ByteBuffer _chunk = null; public static HttpConnection getCurrentConnection() { @@ -67,12 +67,17 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http { __currentConnection.set(connection); } + + public HttpChannelConfig getHttpChannelConfig() + { + return _config; + } - public HttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint) + public HttpConnection(HttpChannelConfig config, Connector connector, EndPoint endPoint) { super(endPoint, connector.getExecutor()); - _configuration = config; + _config = config; _connector = connector; _bufferPool = _connector.getByteBufferPool(); _generator = new HttpGenerator(); // TODO: consider moving the generator to the transport, where it belongs @@ -98,7 +103,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http return _connector; } - public HttpChannel getHttpChannel() + public HttpChannel getHttpChannel() { return _channel; } @@ -145,8 +150,9 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http { if (_requestBuffer != null && !_requestBuffer.hasRemaining()) { - _bufferPool.release(_requestBuffer); - _requestBuffer = null; + ByteBuffer buffer=_requestBuffer; + _requestBuffer=null; + _bufferPool.release(buffer); } } @@ -175,7 +181,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http if (!event && BufferUtil.isEmpty(_requestBuffer)) { if (_requestBuffer == null) - _requestBuffer = _bufferPool.acquire(_configuration.getRequestHeaderSize(), false); + _requestBuffer = _bufferPool.acquire(getInputBufferSize(), false); int filled = getEndPoint().fill(_requestBuffer); if (filled==0) // Do a retry on fill 0 (optimisation for SSL connections) @@ -315,7 +321,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http { case NEED_HEADER: { - header = _bufferPool.acquire(_configuration.getResponseHeaderSize(), false); + header = _bufferPool.acquire(_config.getResponseHeaderSize(), false); continue; } case NEED_CHUNK: @@ -533,7 +539,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http // We will need a buffer to read into if (_requestBuffer==null) - _requestBuffer=_bufferPool.acquire(_configuration.getRequestBufferSize(),false); + _requestBuffer=_bufferPool.acquire(getInputBufferSize(),false); // read some data int filled=getEndPoint().fill(_requestBuffer); @@ -590,9 +596,9 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http private class HttpChannelOverHttp extends HttpChannel { - public HttpChannelOverHttp(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransport transport, HttpInput input) + public HttpChannelOverHttp(Connector connector, HttpChannelConfig config, EndPoint endPoint, HttpTransport transport, HttpInput input) { - super(connector,configuration,endPoint,transport,input); + super(connector,config,endPoint,transport,input); } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpServerConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java similarity index 54% rename from jetty-server/src/main/java/org/eclipse/jetty/server/HttpServerConnectionFactory.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java index 09784704d9a..9ef5d6a6b13 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpServerConnectionFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java @@ -19,39 +19,40 @@ package org.eclipse.jetty.server; -import java.nio.channels.SocketChannel; +import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; -public class HttpServerConnectionFactory implements ConnectionFactory +public class HttpConnectionFactory extends AbstractConnectionFactory implements HttpChannelConfig.ConnectionFactory { - private final Connector connector; - private final HttpConfiguration configuration; + private final HttpChannelConfig _config; - public HttpServerConnectionFactory(Connector connector) + public HttpConnectionFactory() { - this(connector, new HttpConfiguration(connector.getSslContextFactory(), connector.getSslContextFactory() != null)); + this(new HttpChannelConfig()); + setInputBufferSize(16384); } - public HttpServerConnectionFactory(Connector connector, HttpConfiguration configuration) + + public HttpConnectionFactory(HttpChannelConfig config) { - this.connector = connector; - this.configuration = configuration; + super(HttpVersion.HTTP_1_1.toString()); + _config=config; + addBean(_config); } - - public Connector getConnector() + + @Override + public HttpChannelConfig getHttpChannelConfig() { - return connector; - } - - public HttpConfiguration getHttpConfiguration() - { - return configuration; + return _config; } @Override - public Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment) + public Connection newConnection(Connector connector, EndPoint endPoint) { - return new HttpConnection(getHttpConfiguration(), getConnector(), endPoint); + HttpConnection connection = new HttpConnection(_config, connector, endPoint); + connection.setInputBufferSize(getInputBufferSize()); // TODO constructor injection + return connection; } + } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java index 3fad5007748..98a86b8a017 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server; import java.io.IOException; import java.io.InterruptedIOException; + import javax.servlet.ServletInputStream; import org.eclipse.jetty.io.EofException; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java index 1a0b845f58e..631a09ddbd5 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java @@ -22,6 +22,7 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; + import javax.servlet.RequestDispatcher; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; @@ -54,7 +55,7 @@ public class HttpOutput extends ServletOutputStream public HttpOutput(HttpChannel channel) { _channel = channel; - _bufferSize = _channel.getHttpConfiguration().getResponseBufferSize(); + _bufferSize = _channel.getHttpChannelConfig().getOutputBufferSize(); } public boolean isWritten() @@ -209,7 +210,7 @@ public class HttpOutput extends ServletOutputStream HttpContent httpContent = (HttpContent)content; Response response = _channel.getResponse(); String contentType = httpContent.getContentType(); - if (contentType != null) + if (contentType != null && !response.getHttpFields().containsKey(HttpHeader.CONTENT_TYPE.asString())) response.getHttpFields().put(HttpHeader.CONTENT_TYPE, contentType); if (httpContent.getContentLength() > 0) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpServerConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpServerConnector.java index 19db4db28e8..c7f67174379 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpServerConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpServerConnector.java @@ -27,19 +27,44 @@ import org.eclipse.jetty.util.thread.Scheduler; public class HttpServerConnector extends SelectChannelConnector { - public HttpServerConnector(Server server) + public HttpServerConnector( + @Name("server") Server server) { - this(server, null); + this(server,null,null,null,null,null,0,0); } - public HttpServerConnector(Server server, SslContextFactory sslContextFactory) + public HttpServerConnector( + @Name("server") Server server, + @Name("sslContextFactory") SslContextFactory sslContextFactory) { - this(server, null, null, null, sslContextFactory, 0, 0); + this(server,null,sslContextFactory, null, null, null, 0, 0); } - public HttpServerConnector(@Name("server") Server server, @Name("executor") Executor executor, @Name("scheduler") Scheduler scheduler, @Name("bufferPool") ByteBufferPool pool, @Name("sslContextFactory") SslContextFactory sslContextFactory, @Name("acceptors") int acceptors, @Name("selectors") int selectors) + public HttpServerConnector( + @Name("server") Server server, + @Name("connectionFactory") HttpConnectionFactory connectionFactory) { - super(server, executor, scheduler, pool, sslContextFactory, acceptors, selectors); - setDefaultConnectionFactory(new HttpServerConnectionFactory(this)); + this(server,connectionFactory,null, null, null, null, 0, 0); + } + + public HttpServerConnector( + @Name("server") Server server, + @Name("connectionFactory") HttpConnectionFactory connectionFactory, + @Name("sslContextFactory") SslContextFactory sslContextFactory) + { + this(server,connectionFactory,sslContextFactory, null, null, null, 0, 0); + } + + public HttpServerConnector( + @Name("server") Server server, + @Name("connectionFactory") HttpConnectionFactory connectionFactory, + @Name("sslContextFactory") SslContextFactory sslContextFactory, + @Name("executor") Executor executor, + @Name("scheduler") Scheduler scheduler, + @Name("bufferPool") ByteBufferPool pool, + @Name("acceptors") int acceptors, + @Name("selectors") int selectors) + { + super(server,executor,scheduler,pool,acceptors,selectors,AbstractConnectionFactory.getFactories(sslContextFactory,connectionFactory==null?new HttpConnectionFactory():connectionFactory)); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java index 9764dd32a84..0cfec6445b4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java @@ -25,13 +25,10 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLEngine; import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.Connection; -import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.io.ssl.SslConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -41,22 +38,31 @@ public class LocalConnector extends AbstractConnector { private final BlockingQueue _connects = new LinkedBlockingQueue<>(); + + public LocalConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool pool, int acceptors, ConnectionFactory... factories) + { + super(server,executor,scheduler,pool,acceptors,factories); + setIdleTimeout(30000); + } + public LocalConnector(Server server) { - this(server,null); + this(server, null, null, null, 0, new HttpConnectionFactory()); } public LocalConnector(Server server, SslContextFactory sslContextFactory) { - this(server, null, null, null, sslContextFactory, 0); + this(server, null, null, null, 0,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory())); } - public LocalConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool pool, - SslContextFactory sslContextFactory, int acceptors) + public LocalConnector(Server server, ConnectionFactory connectionFactory) { - super(server,executor,scheduler,pool, sslContextFactory, acceptors); - setIdleTimeout(30000); - setDefaultConnectionFactory(new HttpServerConnectionFactory(this)); + this(server, null, null, null, 0, connectionFactory); + } + + public LocalConnector(Server server, ConnectionFactory connectionFactory, SslContextFactory sslContextFactory) + { + this(server, null, null, null, 0,AbstractConnectionFactory.getFactories(sslContextFactory,connectionFactory)); } @Override @@ -159,29 +165,10 @@ public class LocalConnector extends AbstractConnector LocalEndPoint endPoint = _connects.take(); endPoint.onOpen(); - SslContextFactory sslContextFactory = getSslContextFactory(); - if (sslContextFactory != null) - { - SSLEngine engine = sslContextFactory.newSSLEngine(endPoint.getRemoteAddress()); - engine.setUseClientMode(false); - - SslConnection sslConnection = new SslConnection(getByteBufferPool(), getExecutor(), endPoint, engine); - endPoint.setConnection(sslConnection); - connectionOpened(sslConnection); - sslConnection.onOpen(); - - EndPoint appEndPoint = sslConnection.getDecryptedEndPoint(); - Connection connection = getDefaultConnectionFactory().newConnection(null, appEndPoint, null); - appEndPoint.setConnection(connection); - connection.onOpen(); - } - else - { - Connection connection = getDefaultConnectionFactory().newConnection(null, endPoint, null); - endPoint.setConnection(connection); - connectionOpened(connection); - connection.onOpen(); - } + Connection connection = getDefaultConnectionFactory().newConnection(this, endPoint); + endPoint.setConnection(connection); + connectionOpened(connection); + connection.onOpen(); } public class LocalEndPoint extends ByteArrayEndPoint diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java b/jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java index dadf023485c..02594402957 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java @@ -24,6 +24,7 @@ import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Locale; import java.util.TimeZone; + import javax.servlet.http.Cookie; import org.eclipse.jetty.http.HttpHeader; 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 d38187f278f..4975a2c6008 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 @@ -37,6 +37,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; + import javax.servlet.AsyncContext; import javax.servlet.AsyncListener; import javax.servlet.DispatcherType; @@ -118,28 +119,30 @@ public class Request implements HttpServletRequest private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault()); private static final int __NONE = 0, _STREAM = 1, __READER = 2; - private final HttpChannel _channel; + private final HttpChannel _channel; private final HttpFields _fields=new HttpFields(); private final List _requestAttributeListeners=new ArrayList<>(); - private final HttpInput _input; + private final HttpInput _input; + private boolean _secure; private boolean _asyncSupported = true; + private boolean _newContext; + private boolean _cookiesExtracted = false; + private boolean _handled = false; + private boolean _paramsExtracted; + private boolean _requestedSessionIdFromCookie = false; private volatile Attributes _attributes; private Authentication _authentication; private MultiMap _baseParameters; private String _characterEncoding; private ContextHandler.Context _context; - private boolean _newContext; private String _contextPath; private CookieCutter _cookies; - private boolean _cookiesExtracted = false; private DispatcherType _dispatcherType; - private boolean _handled = false; private int _inputState = __NONE; private HttpMethod _httpMethod; private String _httpMethodString; private MultiMap _parameters; - private boolean _paramsExtracted; private String _pathInfo; private int _port; private HttpVersion _httpVersion = HttpVersion.HTTP_1_1; @@ -149,7 +152,6 @@ public class Request implements HttpServletRequest private String _readerEncoding; private InetSocketAddress _remote; private String _requestedSessionId; - private boolean _requestedSessionIdFromCookie = false; private String _requestURI; private Map _savedNewSessions; private String _scheme = URIUtil.HTTP; @@ -164,7 +166,7 @@ public class Request implements HttpServletRequest private MultiPartInputStream _multiPartInputStream; //if the request is a multi-part mime /* ------------------------------------------------------------ */ - public Request(HttpChannel channel, HttpInput input) + public Request(HttpChannel channel, HttpInput input) { _channel = channel; _input = input; @@ -177,7 +179,7 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - public HttpInput getHttpInput() + public HttpInput getHttpInput() { return _input; } @@ -394,7 +396,7 @@ public class Request implements HttpServletRequest /** * @return Returns the connection. */ - public HttpChannel getHttpChannel() + public HttpChannel getHttpChannel() { return _channel; } @@ -613,7 +615,6 @@ public class Request implements HttpServletRequest return Collections.enumeration(__defaultLocale); List langs = new ArrayList<>(); - int size = acceptLanguage.size(); // convert to locals for (String language : acceptLanguage) @@ -1374,7 +1375,13 @@ public class Request implements HttpServletRequest @Override public boolean isSecure() { - return _channel.getHttpConfiguration().isConfidential(this); + return _secure; + } + + /* ------------------------------------------------------------ */ + public void setSecure(boolean secure) + { + _secure=secure; } /* ------------------------------------------------------------ */ diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 831719b1c53..d145e2173ad 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Locale; import java.util.concurrent.atomic.AtomicInteger; + import javax.servlet.RequestDispatcher; import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java new file mode 100644 index 00000000000..63b0a2ce95b --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java @@ -0,0 +1,169 @@ +// +// ======================================================================== +// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server; + +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLSession; + +import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.io.ssl.SslConnection; +import org.eclipse.jetty.io.ssl.SslConnection.DecryptedEndPoint; +import org.eclipse.jetty.server.ssl.ServletSSL; +import org.eclipse.jetty.server.ssl.SslCertificates; +import org.eclipse.jetty.util.TypeUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +public class SecureRequestCustomizer implements HttpChannelConfig.Customizer +{ + private static final Logger LOG = Log.getLogger(SecureRequestCustomizer.class); + + /** + * The name of the SSLSession attribute that will contain any cached information. + */ + public static final String CACHED_INFO_ATTR = CachedInfo.class.getName(); + + + @Override + public void customize(Connector connector, HttpChannelConfig channelConfig, Request request) + { + if (request.getHttpChannel().getEndPoint() instanceof DecryptedEndPoint) + { + request.setScheme(HttpScheme.HTTPS.asString()); + request.setSecure(true); + SslConnection.DecryptedEndPoint ssl_endp = (DecryptedEndPoint)request.getHttpChannel().getEndPoint(); + SslConnection sslConnection = ssl_endp.getSslConnection(); + SSLEngine sslEngine=sslConnection.getSSLEngine(); + customize(sslEngine,request); + } + + } + + /* ------------------------------------------------------------ */ + /* + * Allow the Listener a chance to customise the request. before the server + * does its stuff.
+ * This allows the required attributes to be set for SSL requests.
+ * The requirements of the Servlet specs are: + *

    + *
  • an attribute named "javax.servlet.request.ssl_session_id" of type + * String (since Servlet Spec 3.0).
  • + *
  • an attribute named "javax.servlet.request.cipher_suite" of type + * String.
  • + *
  • an attribute named "javax.servlet.request.key_size" of type Integer.
  • + *
  • an attribute named "javax.servlet.request.X509Certificate" of type + * java.security.cert.X509Certificate[]. This is an array of objects of type + * X509Certificate, the order of this array is defined as being in ascending + * order of trust. The first certificate in the chain is the one set by the + * client, the next is the one used to authenticate the first, and so on. + *
  • + *
+ * + * @param request + * HttpRequest to be customised. + */ + public void customize(SSLEngine sslEngine, Request request) + { + request.setScheme(HttpScheme.HTTPS.asString()); + SSLSession sslSession = sslEngine.getSession(); + + try + { + String cipherSuite=sslSession.getCipherSuite(); + Integer keySize; + X509Certificate[] certs; + String idStr; + + CachedInfo cachedInfo=(CachedInfo)sslSession.getValue(CACHED_INFO_ATTR); + if (cachedInfo!=null) + { + keySize=cachedInfo.getKeySize(); + certs=cachedInfo.getCerts(); + idStr=cachedInfo.getIdStr(); + } + else + { + keySize=new Integer(ServletSSL.deduceKeyLength(cipherSuite)); + certs=SslCertificates.getCertChain(sslSession); + byte[] bytes = sslSession.getId(); + idStr = TypeUtil.toHexString(bytes); + cachedInfo=new CachedInfo(keySize,certs,idStr); + sslSession.putValue(CACHED_INFO_ATTR,cachedInfo); + } + + if (certs!=null) + request.setAttribute("javax.servlet.request.X509Certificate",certs); + + request.setAttribute("javax.servlet.request.cipher_suite",cipherSuite); + request.setAttribute("javax.servlet.request.key_size",keySize); + request.setAttribute("javax.servlet.request.ssl_session_id", idStr); + } + catch (Exception e) + { + LOG.warn(Log.EXCEPTION,e); + } + } + + @Override + public String toString() + { + return String.format("%s@%x",this.getClass().getSimpleName(),hashCode()); + } + + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + /** + * Simple bundle of information that is cached in the SSLSession. Stores the + * effective keySize and the client certificate chain. + */ + private static class CachedInfo + { + private final X509Certificate[] _certs; + private final Integer _keySize; + private final String _idStr; + + CachedInfo(Integer keySize, X509Certificate[] certs,String idStr) + { + this._keySize=keySize; + this._certs=certs; + this._idStr=idStr; + } + + X509Certificate[] getCerts() + { + return _certs; + } + + Integer getKeySize() + { + return _keySize; + } + + String getIdStr() + { + return _idStr; + } + } + + + +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SelectChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SelectChannelConnector.java index 6aec9e8ec85..f794c70cd17 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SelectChannelConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SelectChannelConnector.java @@ -29,7 +29,6 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.concurrent.Executor; import java.util.concurrent.Future; -import javax.net.ssl.SSLEngine; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.Connection; @@ -37,9 +36,7 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.SelectChannelEndPoint; import org.eclipse.jetty.io.SelectorManager; import org.eclipse.jetty.io.SelectorManager.ManagedSelector; -import org.eclipse.jetty.io.ssl.SslConnection; import org.eclipse.jetty.util.annotation.ManagedObject; -import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.Scheduler; @@ -57,42 +54,40 @@ public class SelectChannelConnector extends AbstractNetworkConnector private volatile boolean _reuseAddress = true; private volatile int _lingerTime = -1; - public SelectChannelConnector(@Name("server") Server server) + + public SelectChannelConnector(Server server) { - this(server, null); + this(server,null,null,null,0,0,new HttpConnectionFactory()); } - - public SelectChannelConnector(@Name("server")Server server, @Name("sslContextFactory") SslContextFactory sslContextFactory) + + public SelectChannelConnector(Server server,ConnectionFactory... factories) { - this(server, null, null, null, sslContextFactory, 0, 0); + this(server,null,null,null,0,0,factories); + } + + public SelectChannelConnector(Server server,SslContextFactory sslContextFactory) + { + this(server,null,null,null,0,0,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory())); + } + + public SelectChannelConnector(Server server,SslContextFactory sslContextFactory,ConnectionFactory... factories) + { + this(server,null,null,null,0,0,AbstractConnectionFactory.getFactories(sslContextFactory,factories)); } /** * @param server The server this connector will be added to. Must not be null. + * @param factory TODO * @param executor An executor for this connector or null to use the servers executor * @param scheduler A scheduler for this connector or null to use the servers scheduler * @param pool A buffer pool for this connector or null to use a default {@link ByteBufferPool} * @param acceptors the number of acceptor threads to use, or 0 for a default value. */ - public SelectChannelConnector( - @Name("server") Server server, - @Name("executor") Executor executor, - @Name("scheduler") Scheduler scheduler, - @Name("bufferPool") ByteBufferPool pool, - @Name("sslContextFactory") SslContextFactory sslContextFactory, - @Name("acceptors") int acceptors, - @Name("selectors") int selectors) + public SelectChannelConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool pool, int acceptors,int selectors,ConnectionFactory... factories) { - super(server, executor, scheduler, pool, sslContextFactory, acceptors); + super(server,executor,scheduler,pool,acceptors,factories); _manager = new ConnectorSelectorManager(selectors > 0 ? selectors : Math.max(1, (Runtime.getRuntime().availableProcessors()) / 4)); addBean(_manager, true); - - // TODO: why we need to set the linger time when in SSL mode ? - if (sslContextFactory != null) - setSoLingerTime(30000); - - // TODO: we hardcode HTTP, but this is a generic connector that should not hardcode anything - setDefaultConnectionFactory(new HttpServerConnectionFactory(this)); } @Override @@ -257,25 +252,7 @@ public class SelectChannelConnector extends AbstractNetworkConnector protected Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment) { - SslContextFactory sslContextFactory = getSslContextFactory(); - if (sslContextFactory != null) - { - SSLEngine engine = sslContextFactory.newSSLEngine(endPoint.getRemoteAddress()); - engine.setUseClientMode(false); - - SslConnection sslConnection = new SslConnection(getByteBufferPool(), getExecutor(), endPoint, engine); - - EndPoint appEndPoint = sslConnection.getDecryptedEndPoint(); - Connection connection = getDefaultConnectionFactory().newConnection(channel, appEndPoint, attachment); - appEndPoint.setConnection(connection); - connection.onOpen(); - - return sslConnection; - } - else - { - return getDefaultConnectionFactory().newConnection(channel, endPoint, attachment); - } + return getDefaultConnectionFactory().newConnection(this, endPoint); } /** diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 8d71ba884e6..d176d73baa4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -94,7 +95,7 @@ public class Server extends HandlerWrapper implements Attributes public Server(@Name("port")int port) { this((ThreadPool)null); - SelectChannelConnector connector=new SelectChannelConnector(this); + SelectChannelConnector connector=new HttpServerConnector(this); connector.setPort(port); setConnectors(new Connector[]{connector}); } @@ -106,7 +107,7 @@ public class Server extends HandlerWrapper implements Attributes public Server(@Name("address")InetSocketAddress addr) { this((ThreadPool)null); - SelectChannelConnector connector=new SelectChannelConnector(this); + SelectChannelConnector connector=new HttpServerConnector(this); connector.setHost(addr.getHostName()); connector.setPort(addr.getPort()); setConnectors(new Connector[]{connector}); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java index f3ca9dcd06b..242a27b441f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.security.Principal; import java.util.Collection; import java.util.Enumeration; + import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletRequestWrapper; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java index 502ef1f7c7e..91278460b70 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server; import java.io.IOException; import java.util.Collection; + import javax.servlet.ServletResponse; import javax.servlet.ServletResponseWrapper; import javax.servlet.http.Cookie; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java index 83825648679..76a2eaacdd4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server; import java.util.EventListener; import java.util.Set; + import javax.servlet.SessionCookieConfig; import javax.servlet.SessionTrackingMode; import javax.servlet.http.Cookie; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SslConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SslConnectionFactory.java new file mode 100644 index 00000000000..daf25bba67e --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SslConnectionFactory.java @@ -0,0 +1,99 @@ +// +// ======================================================================== +// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + + +package org.eclipse.jetty.server; + + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLSession; + +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.io.ssl.SslConnection; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public class SslConnectionFactory extends AbstractConnectionFactory +{ + private final SslContextFactory _sslContextFactory; + private final String _nextProtocol; + + public SslConnectionFactory() + { + this(null,HttpVersion.HTTP_1_1.asString()); + } + + public SslConnectionFactory(String nextProtocol) + { + this(null,nextProtocol); + } + + public SslConnectionFactory(SslContextFactory factory,String nextProtocol) + { + super("SSL-"+nextProtocol); + _sslContextFactory=factory==null?new SslContextFactory():factory; + _nextProtocol=nextProtocol; + addBean(_sslContextFactory); + } + + public SslContextFactory getSslContextFactory() + { + return _sslContextFactory; + } + + + + @Override + protected void doStart() throws Exception + { + super.doStart(); + + SSLEngine engine = _sslContextFactory.newSSLEngine(); + engine.setUseClientMode(false); + SSLSession session=engine.getSession(); + + if (session.getPacketBufferSize()>getInputBufferSize()) + setInputBufferSize(session.getPacketBufferSize()); + } + + @Override + public Connection newConnection(Connector connector, EndPoint endPoint) + { + SSLEngine engine = _sslContextFactory.newSSLEngine(endPoint.getRemoteAddress()); + engine.setUseClientMode(false); + + SslConnection sslConnection = new SslConnection(connector.getByteBufferPool(), connector.getExecutor(), endPoint, engine); + sslConnection.setInputBufferSize(getInputBufferSize()); + EndPoint decrypted_endp = sslConnection.getDecryptedEndPoint(); + + ConnectionFactory next = connector.getConnectionFactory(_nextProtocol); + Connection connection = next.newConnection(connector, decrypted_endp); + + decrypted_endp.setConnection(connection); + connection.onOpen(); + + return sslConnection; + } + + @Override + public String toString() + { + return String.format("%s@%x{%s}",this.getClass().getSimpleName(),hashCode(),getProtocol()); + } +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java b/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java index 5c39e7f5084..90f072619dd 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server; import java.security.Principal; import java.util.Map; + import javax.security.auth.Subject; /* ------------------------------------------------------------ */ diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 22f31e99228..d97874d1ac0 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -37,6 +37,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.Future; + import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterRegistration; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java index b68575878e6..f5ced00d3ff 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; import java.util.HashMap; import java.util.Map; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java index 1664aa0b94d..a9c86c13f6b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.Locale; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java index f1298dba67b..436040eada7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; import java.io.OutputStream; import java.net.URL; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java index 71e66990161..e8d7311fe75 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java index b9e15f19c3d..2a2d8e3ba36 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; import java.util.List; import java.util.concurrent.CountDownLatch; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java index 3dca6423057..e295516198f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java index a18b937e7d8..dd5dd51fe8e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; import java.util.List; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HotSwapHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HotSwapHandler.java index ff5ce0c735f..a930c35a27d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HotSwapHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HotSwapHandler.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; import java.util.List; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java index cd5000bd809..71024db947b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java @@ -23,6 +23,7 @@ import java.net.InetSocketAddress; import java.util.Collections; import java.util.List; import java.util.Map; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java index f57ef9fbae1..c21f256c562 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java index e6ca16b7948..6131e3b3cd0 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; + import javax.servlet.DispatcherType; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java index f7ae5eaae6d..28a81149bcd 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; import java.io.OutputStream; import java.net.MalformedURLException; + import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java index a3ceb46a400..60a049dc545 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java index 972ac8ba64c..3ddfad8b2f1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/StatisticsHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/StatisticsHandler.java index 8d802eb73ab..b982b914e2e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/StatisticsHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/StatisticsHandler.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/NetworkTrafficSelectChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/NetworkTrafficSelectChannelConnector.java index f4c94cea698..1f8079e7714 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/NetworkTrafficSelectChannelConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/NetworkTrafficSelectChannelConnector.java @@ -24,14 +24,20 @@ import java.nio.channels.SocketChannel; import java.util.ConcurrentModificationException; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; +import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.NetworkTrafficListener; import org.eclipse.jetty.io.NetworkTrafficSelectChannelEndPoint; import org.eclipse.jetty.io.SelectChannelEndPoint; import org.eclipse.jetty.io.SelectorManager; +import org.eclipse.jetty.server.ConnectionFactory; +import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.Scheduler; /** *

A specialized version of {@link SelectChannelConnector} that supports {@link NetworkTrafficListener}s.

@@ -42,10 +48,30 @@ public class NetworkTrafficSelectChannelConnector extends SelectChannelConnector { private final List listeners = new CopyOnWriteArrayList(); - public NetworkTrafficSelectChannelConnector(Server server) { - super(server); + this(server,null,null,null,0,0,new HttpConnectionFactory()); + } + + public NetworkTrafficSelectChannelConnector(Server server, ConnectionFactory connectionFactory, SslContextFactory sslContextFactory) + { + super(server,sslContextFactory,connectionFactory); + } + + public NetworkTrafficSelectChannelConnector(Server server, ConnectionFactory connectionFactory) + { + super(server,connectionFactory); + } + + public NetworkTrafficSelectChannelConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool pool, int acceptors, int selectors, + ConnectionFactory... factories) + { + super(server,executor,scheduler,pool,acceptors,selectors,factories); + } + + public NetworkTrafficSelectChannelConnector(Server server, SslContextFactory sslContextFactory) + { + super(server,sslContextFactory); } /** diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java index 3dd69f4530a..79dba9b601e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java @@ -27,6 +27,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; + import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSessionActivationListener; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionIdManager.java index 0d9aa45a4ec..e26ae62ed5c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionIdManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionIdManager.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server.session; import java.security.SecureRandom; import java.util.Random; + import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.server.SessionIdManager; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java index 191836f502b..cca7aaf9109 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.server.session; +import static java.lang.Math.round; + import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; @@ -28,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; + import javax.servlet.SessionCookieConfig; import javax.servlet.SessionTrackingMode; import javax.servlet.http.HttpServletRequest; @@ -51,8 +54,6 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.statistic.CounterStatistic; import org.eclipse.jetty.util.statistic.SampleStatistic; -import static java.lang.Math.round; - /* ------------------------------------------------------------ */ /** * An Abstract implementation of SessionManager. The partial implementation of diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java index d98e353569b..b4e7850c570 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Random; import java.util.Set; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java index 7d88eae893e..878365e0517 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java @@ -31,6 +31,7 @@ import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; + import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java index 7db59d1aa92..550d0520404 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.util.Enumeration; + import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.util.IO; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java index b759b815e30..2e82d7e5c28 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Random; import java.util.Timer; import java.util.TimerTask; + import javax.naming.InitialContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java index fe32a93688f..e5d1712a593 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java @@ -35,6 +35,7 @@ import java.util.ListIterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java index cc18ab03302..bb3f020ec3d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server.session; import java.io.IOException; import java.util.EnumSet; import java.util.EventListener; + import javax.servlet.DispatcherType; import javax.servlet.ServletException; import javax.servlet.SessionTrackingMode; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java index a1829ef5cdb..3bfa33b5edf 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java @@ -19,15 +19,11 @@ package org.eclipse.jetty.server.ssl; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.security.cert.X509Certificate; -import javax.net.ssl.SSLEngine; + import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; -import org.eclipse.jetty.http.HttpScheme; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -35,11 +31,6 @@ public class SslCertificates { private static final Logger LOG = Log.getLogger(SslCertificates.class); - /** - * The name of the SSLSession attribute that will contain any cached information. - */ - static final String CACHED_INFO_ATTR = CachedInfo.class.getName(); - public static X509Certificate[] getCertChain(SSLSession sslSession) { try @@ -73,105 +64,4 @@ public class SslCertificates } - /* ------------------------------------------------------------ */ - /** - * Allow the Listener a chance to customise the request. before the server - * does its stuff.
- * This allows the required attributes to be set for SSL requests.
- * The requirements of the Servlet specs are: - *
    - *
  • an attribute named "javax.servlet.request.ssl_session_id" of type - * String (since Servlet Spec 3.0).
  • - *
  • an attribute named "javax.servlet.request.cipher_suite" of type - * String.
  • - *
  • an attribute named "javax.servlet.request.key_size" of type Integer.
  • - *
  • an attribute named "javax.servlet.request.X509Certificate" of type - * java.security.cert.X509Certificate[]. This is an array of objects of type - * X509Certificate, the order of this array is defined as being in ascending - * order of trust. The first certificate in the chain is the one set by the - * client, the next is the one used to authenticate the first, and so on. - *
  • - *
- * - * @param request - * HttpRequest to be customised. - */ - public static void customize(SSLEngine sslEngine, Request request) throws IOException - { - request.setScheme(HttpScheme.HTTPS.asString()); - SSLSession sslSession = sslEngine.getSession(); - - try - { - String cipherSuite=sslSession.getCipherSuite(); - Integer keySize; - X509Certificate[] certs; - String idStr; - - CachedInfo cachedInfo=(CachedInfo)sslSession.getValue(CACHED_INFO_ATTR); - if (cachedInfo!=null) - { - keySize=cachedInfo.getKeySize(); - certs=cachedInfo.getCerts(); - idStr=cachedInfo.getIdStr(); - } - else - { - keySize=new Integer(ServletSSL.deduceKeyLength(cipherSuite)); - certs=SslCertificates.getCertChain(sslSession); - byte[] bytes = sslSession.getId(); - idStr = TypeUtil.toHexString(bytes); - cachedInfo=new CachedInfo(keySize,certs,idStr); - sslSession.putValue(CACHED_INFO_ATTR,cachedInfo); - } - - if (certs!=null) - request.setAttribute("javax.servlet.request.X509Certificate",certs); - - request.setAttribute("javax.servlet.request.cipher_suite",cipherSuite); - request.setAttribute("javax.servlet.request.key_size",keySize); - request.setAttribute("javax.servlet.request.ssl_session_id", idStr); - } - catch (Exception e) - { - LOG.warn(Log.EXCEPTION,e); - } - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /** - * Simple bundle of information that is cached in the SSLSession. Stores the - * effective keySize and the client certificate chain. - */ - private static class CachedInfo - { - private final X509Certificate[] _certs; - private final Integer _keySize; - private final String _idStr; - - CachedInfo(Integer keySize, X509Certificate[] certs,String idStr) - { - this._keySize=keySize; - this._certs=certs; - this._idStr=idStr; - } - - X509Certificate[] getCerts() - { - return _certs; - } - - Integer getKeySize() - { - return _keySize; - } - - String getIdStr() - { - return _idStr; - } - } - } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java index 19f40ba0f9b..073080a0d37 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server.ssl; import java.io.File; import java.security.SecureRandom; import java.security.Security; + import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java index e1fff1058dc..8301bb0b534 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.server.ssl; +import org.eclipse.jetty.server.AbstractConnectionFactory; +import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -33,6 +35,6 @@ public class SslSelectChannelConnector extends SelectChannelConnector { public SslSelectChannelConnector(Server server) { - super(server,new SslContextFactory()); + super(server,null,null,null,0,0,AbstractConnectionFactory.getFactories(new SslContextFactory(),new HttpConnectionFactory())); } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/AbstractHttpTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/AbstractHttpTest.java index 0d8277a8324..1267bd9672f 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/AbstractHttpTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/AbstractHttpTest.java @@ -18,6 +18,9 @@ package org.eclipse.jetty.server; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -25,6 +28,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.net.URISyntaxException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -37,9 +41,6 @@ import org.eclipse.jetty.util.log.StdErrLog; import org.junit.After; import org.junit.Before; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - public abstract class AbstractHttpTest { protected static Server server; @@ -56,7 +57,7 @@ public abstract class AbstractHttpTest public void setUp() throws Exception { server = new Server(); - connector = new SelectChannelConnector(server); + connector = new HttpServerConnector(server); connector.setIdleTimeout(10000); server.addConnector(connector); httpParser = new SimpleHttpParser(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncRequestReadTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncRequestReadTest.java index c84fd06fe6e..6e5097b3e12 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncRequestReadTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncRequestReadTest.java @@ -18,6 +18,9 @@ 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.OutputStream; @@ -25,6 +28,7 @@ import java.net.Socket; import java.util.Arrays; import java.util.concurrent.Exchanger; import java.util.concurrent.TimeUnit; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -39,9 +43,6 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - public class AsyncRequestReadTest { private static Server server; @@ -52,7 +53,7 @@ public class AsyncRequestReadTest public static void startServer() throws Exception { server = new Server(); - connector = new SelectChannelConnector(server); + connector = new HttpServerConnector(server); connector.setIdleTimeout(10000); server.addConnector(connector); server.setHandler(new EmptyHandler()); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java index 409fcbbef6b..77829778d10 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; + import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; @@ -25,6 +27,7 @@ import java.net.Socket; import java.util.Random; import java.util.Timer; import java.util.TimerTask; + import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; @@ -44,8 +47,6 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.assertEquals; - public class AsyncStressTest { private static final Logger LOG = Log.getLogger(AsyncStressTest.class); @@ -72,7 +73,7 @@ public class AsyncStressTest { _server.manage(_threads); _threads.setMaxThreads(50); - _connector = new SelectChannelConnector(_server); + _connector = new HttpServerConnector(_server); _connector.setIdleTimeout(120000); _server.setConnectors(new Connector[]{ _connector }); _server.setHandler(_handler); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ChannelHttpServer.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ChannelHttpServer.java deleted file mode 100644 index 51842cbbb86..00000000000 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ChannelHttpServer.java +++ /dev/null @@ -1,34 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.server; - -public class ChannelHttpServer -{ - public static void main(String[] s) throws Exception - { - Server server = new Server(); - SelectChannelConnector connector = new SelectChannelConnector(server); - connector.setPort(8080); - server.addConnector(connector); - server.setHandler(new DumpHandler()); - server.start(); - server.dumpStdErr(); - server.join(); - } -} diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java index 2c0f72dff19..987b360fe0c 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java @@ -18,7 +18,12 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import java.io.IOException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -26,10 +31,6 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.handler.AbstractHandler; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - /** * */ @@ -97,11 +98,11 @@ public class CheckReverseProxyHeadersTest private void testRequest(String headers, RequestValidator requestValidator) throws Exception { Server server = new Server(); - LocalConnector connector = new LocalConnector(server); // Activate reverse proxy headers checking - HttpConfiguration httpConfiguration = new HttpConfiguration(null, false); - httpConfiguration.setForwarded(true); - connector.setDefaultConnectionFactory(new HttpServerConnectionFactory(connector, httpConfiguration)); + HttpConnectionFactory http = new HttpConnectionFactory(); + http.getHttpChannelConfig().addCustomizer(new ForwardedRequestCustomizer()); + + LocalConnector connector = new LocalConnector(server,http); server.setConnectors(new Connector[] {connector}); ValidationHandler validationHandler = new ValidationHandler(requestValidator); @@ -159,6 +160,7 @@ public class CheckReverseProxyHeadersTest return _error; } + @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ConnectorCloseTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ConnectorCloseTestBase.java index 73ddc0ca1ff..f7409ea175c 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ConnectorCloseTestBase.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ConnectorCloseTestBase.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertTrue; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -28,8 +30,6 @@ import java.util.concurrent.TimeUnit; import org.junit.Test; -import static org.junit.Assert.assertTrue; - /** * HttpServer Tester. */ diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ConnectorTimeoutTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ConnectorTimeoutTest.java index 0a1e019e171..0d8a0bc0081 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ConnectorTimeoutTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ConnectorTimeoutTest.java @@ -18,6 +18,10 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.matchers.JUnitMatchers.containsString; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -25,6 +29,7 @@ import java.net.Socket; import java.net.SocketException; import java.util.concurrent.Exchanger; import java.util.concurrent.TimeUnit; + import javax.net.ssl.SSLException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -37,10 +42,6 @@ import org.eclipse.jetty.util.IO; import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.matchers.JUnitMatchers.containsString; - public abstract class ConnectorTimeoutTest extends HttpServerTestFixture { protected static final int MAX_IDLE_TIME=500; @@ -243,14 +244,12 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture // further writes will get broken pipe or similar try { - for (int i=0;i<1000;i++) + long end=System.currentTimeMillis()+MAX_IDLE_TIME+3000; + while (System.currentTimeMillis()(null,null,null,null,null) + HttpChannel channel = new HttpChannel(null,new HttpChannelConfig(),null,null,null) { - @Override - public HttpConfiguration getHttpConfiguration() - { - return configuration; - } - @Override public ByteBufferPool getByteBufferPool() { diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/InclusiveByteRangeTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/InclusiveByteRangeTest.java index 08b94975b2a..43e46f0b82c 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/InclusiveByteRangeTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/InclusiveByteRangeTest.java @@ -18,15 +18,15 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + import java.util.List; import java.util.Vector; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - public class InclusiveByteRangeTest { @SuppressWarnings("unchecked") diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java index 3b178c10ac4..7b1c0e9ce2e 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java @@ -18,9 +18,12 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; + import java.io.IOException; import java.io.InputStream; import java.util.concurrent.atomic.AtomicInteger; + import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; @@ -37,8 +40,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.assertEquals; - public class LocalAsyncContextTest { protected Server _server = new Server(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/LocalConnectorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalConnectorTest.java index 817eb6509de..5191aaa7738 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/LocalConnectorTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalConnectorTest.java @@ -18,13 +18,13 @@ package org.eclipse.jetty.server; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; + import org.junit.After; import org.junit.Before; import org.junit.Test; -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; - public class LocalConnectorTest { private Server _server; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java index bb9d20a1846..80885c74940 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java @@ -18,6 +18,9 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -27,6 +30,7 @@ import java.nio.ByteBuffer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; + import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; @@ -41,9 +45,6 @@ import org.junit.After; import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - @Ignore public class NetworkTrafficListenerTest { diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java index de65ba3c81d..11887164f33 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java @@ -24,6 +24,11 @@ */ package org.eclipse.jetty.server; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.util.Date; import java.util.Enumeration; import java.util.List; @@ -37,11 +42,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - /** * */ 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 f2ffab3e23b..926a6ecfed7 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 @@ -18,6 +18,14 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -29,6 +37,7 @@ import java.util.Arrays; import java.util.Enumeration; import java.util.Map; import java.util.concurrent.TimeUnit; + import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; @@ -48,14 +57,6 @@ import org.junit.Assert; 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.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - public class RequestTest { private static final Logger LOG = Log.getLogger(RequestTest.class); @@ -67,15 +68,13 @@ public class RequestTest public void init() throws Exception { _server = new Server(); - _connector = new LocalConnector(_server); - HttpConfiguration httpConfiguration = new HttpConfiguration(null, false); - httpConfiguration.setRequestHeaderSize(512); - httpConfiguration.setRequestBufferSize(1024); - httpConfiguration.setResponseHeaderSize(512); - httpConfiguration.setResponseBufferSize(2048); - httpConfiguration.setForwarded(true); - HttpServerConnectionFactory defaultConnectionFactory = new HttpServerConnectionFactory(_connector, httpConfiguration); - _connector.setDefaultConnectionFactory(defaultConnectionFactory); + HttpConnectionFactory http = new HttpConnectionFactory(); + http.setInputBufferSize(1024); + http.getHttpChannelConfig().setRequestHeaderSize(512); + http.getHttpChannelConfig().setResponseHeaderSize(512); + http.getHttpChannelConfig().setOutputBufferSize(2048); + http.getHttpChannelConfig().addCustomizer(new ForwardedRequestCustomizer()); + _connector = new LocalConnector(_server,http); _server.addConnector(_connector); _handler = new RequestHandler(); _server.setHandler(_handler); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java index 5f2d81ea21a..3566366b799 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java @@ -18,6 +18,9 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; @@ -30,9 +33,6 @@ import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceCollection; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - public class ResourceCacheTest { @Test diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index 71123685f53..bfa46cc2a57 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -18,6 +18,11 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; @@ -26,6 +31,7 @@ import java.net.Socket; import java.nio.ByteBuffer; import java.util.Iterator; import java.util.Locale; + import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; @@ -49,11 +55,6 @@ import org.junit.Assert; 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; -import static org.junit.Assert.fail; - public class ResponseTest { private Server _server; @@ -65,14 +66,15 @@ public class ResponseTest { _server = new Server(); _scheduler = new TimerScheduler(); - LocalConnector connector = new LocalConnector(_server, null, _scheduler, null, null, 1); + HttpChannelConfig config = new HttpChannelConfig(); + LocalConnector connector = new LocalConnector(_server,null,_scheduler,null,1,new HttpConnectionFactory(config)); _server.addConnector(connector); _server.setHandler(new DumpHandler()); _server.start(); AbstractEndPoint endp = new ByteArrayEndPoint(_scheduler, 5000); ByteBufferHttpInput input = new ByteBufferHttpInput(); - _channel = new HttpChannel(connector, new HttpConfiguration(null, false), endp, new HttpTransport() + _channel = new HttpChannel(connector, new HttpChannelConfig(), endp, new HttpTransport() { @Override public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws IOException diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelStatisticsTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelStatisticsTest.java index b57e593833e..faa824b12fb 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelStatisticsTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelStatisticsTest.java @@ -18,6 +18,9 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -25,6 +28,7 @@ import java.io.PrintWriter; import java.net.Socket; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -41,9 +45,6 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - public class SelectChannelStatisticsTest { private static final Logger LOG = Log.getLogger(SelectChannelStatisticsTest.class); 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 a7cdfc94310..d91cf2cb539 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 @@ -18,6 +18,8 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertTrue; + import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -28,8 +30,6 @@ import org.eclipse.jetty.util.IO; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.assertTrue; - public class SelectChannelTimeoutTest extends ConnectorTimeoutTest { @Before diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java index bf55b5a7a78..8e10bc21c45 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java @@ -18,14 +18,16 @@ package org.eclipse.jetty.server; +import static org.hamcrest.Matchers.lessThan; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.nio.ByteBuffer; -import java.nio.channels.SocketChannel; import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -38,8 +40,6 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import static org.hamcrest.Matchers.lessThan; - public class SlowClientWithPipelinedRequestTest { private final AtomicInteger handles = new AtomicInteger(); @@ -49,13 +49,12 @@ public class SlowClientWithPipelinedRequestTest public void startServer(Handler handler) throws Exception { server = new Server(); - connector = new SelectChannelConnector(server); - connector.setDefaultConnectionFactory(new HttpServerConnectionFactory(connector) + connector = new SelectChannelConnector(server,new HttpConnectionFactory() { @Override - public Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment) + public Connection newConnection(Connector connector, EndPoint endPoint) { - return new HttpConnection(getHttpConfiguration(), getConnector(), endPoint) + return new HttpConnection(new HttpChannelConfig(),connector,endPoint) { @Override public void onFillable() diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/StressTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/StressTest.java index 56a90931b41..1e1e93d1e23 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/StressTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/StressTest.java @@ -18,12 +18,17 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + import java.io.IOException; import java.net.Socket; import java.util.Queue; import java.util.Random; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -41,10 +46,6 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; - @Ignore public class StressTest { @@ -93,7 +94,7 @@ public class StressTest _server = new Server(_threads); _server.manage(_threads); - _connector = new SelectChannelConnector(_server,null,null,null,null,1,1); + _connector = new SelectChannelConnector(_server,null,null,null,1, 1,new HttpConnectionFactory()); _connector.setAcceptQueueSize(5000); _connector.setIdleTimeout(30000); _server.addConnector(_connector); 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 index aafaef02ff3..c15ab9ca64f 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server; import java.io.IOException; import java.io.InputStream; + import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java index 895375d340d..589b7a08821 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java @@ -18,7 +18,12 @@ package org.eclipse.jetty.server.handler; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import java.io.IOException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -29,10 +34,6 @@ import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - public class ContextHandlerCollectionTest { @Test diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java index 49562d89d89..0831e44d9b7 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java @@ -18,12 +18,18 @@ package org.eclipse.jetty.server.handler; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.List; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -37,11 +43,6 @@ import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - /** * @version $Revision$ */ diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/IPAccessHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/IPAccessHandlerTest.java index 19d2d2a4fb6..c9e412d0e29 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/IPAccessHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/IPAccessHandlerTest.java @@ -18,6 +18,9 @@ package org.eclipse.jetty.server.handler; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.io.BufferedReader; import java.io.EOFException; import java.io.IOException; @@ -30,6 +33,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -47,9 +51,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - @RunWith(Parameterized.class) public class IPAccessHandlerTest { diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ResourceHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ResourceHandlerTest.java index f5a84b756a5..ac6f360e885 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ResourceHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ResourceHandlerTest.java @@ -22,6 +22,7 @@ import java.net.URI; import junit.framework.Assert; import junit.framework.TestCase; + import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java index 4c8f98ab355..3199ab82495 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java @@ -18,7 +18,10 @@ package org.eclipse.jetty.server.handler; +import static org.junit.Assert.assertEquals; + import java.io.IOException; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -27,8 +30,6 @@ import org.eclipse.jetty.server.Request; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.assertEquals; - public class ScopedHandlerTest { private StringBuilder _history=new StringBuilder(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ShutdownHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ShutdownHandlerTest.java index fa519bbfbfd..b5c32d77df7 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ShutdownHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ShutdownHandlerTest.java @@ -18,8 +18,13 @@ package org.eclipse.jetty.server.handler; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -31,10 +36,6 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; - public class ShutdownHandlerTest { @Mock private HttpServletRequest request; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/StatisticsHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/StatisticsHandlerTest.java index c18d438ac94..c8adcab2901 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/StatisticsHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/StatisticsHandlerTest.java @@ -18,11 +18,17 @@ package org.eclipse.jetty.server.handler; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -37,11 +43,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - public class StatisticsHandlerTest { private Server _server; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java index 71f4030b5d2..17193fcd5e8 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java @@ -18,15 +18,15 @@ package org.eclipse.jetty.server.session; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import javax.servlet.SessionCookieConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.eclipse.jetty.http.HttpCookie; import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; /** * SessionCookieTest * diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java index a9fb86689e9..b01aca39f42 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java @@ -26,6 +26,7 @@ import java.io.OutputStream; import java.net.Socket; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; + import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; @@ -34,6 +35,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; + import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Request; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java index 328b7989d58..a155e200a02 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java @@ -23,6 +23,11 @@ package org.eclipse.jetty.server.ssl; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -31,8 +36,10 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.Socket; +import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.URL; + import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; @@ -42,8 +49,7 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpServerConnectionFactory; +import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; @@ -56,11 +62,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - /** * */ @@ -74,9 +75,11 @@ public class SSLEngineTest /** The request. */ private static final String REQUEST0_HEADER="POST /r0 HTTP/1.1\n"+"Host: localhost\n"+"Content-Type: text/xml\n"+"Content-Length: "; private static final String REQUEST1_HEADER="POST /r1 HTTP/1.1\n"+"Host: localhost\n"+"Content-Type: text/xml\n"+"Connection: close\n"+"Content-Length: "; - private static final String REQUEST_CONTENT="\n" - +"\n"+""; + private static final String REQUEST_CONTENT= + "\n"+ + "\n"+ + ""; private static final String REQUEST0=REQUEST0_HEADER+REQUEST_CONTENT.getBytes().length+"\n\n"+REQUEST_CONTENT; private static final String REQUEST1=REQUEST1_HEADER+REQUEST_CONTENT.getBytes().length+"\n\n"+REQUEST_CONTENT; @@ -101,12 +104,11 @@ public class SSLEngineTest sslContextFactory.setKeyManagerPassword("keypwd"); server=new Server(); - connector=new SelectChannelConnector(server, sslContextFactory); + HttpConnectionFactory http = new HttpConnectionFactory(); + http.setInputBufferSize(512); + http.getHttpChannelConfig().setRequestHeaderSize(512); + connector=new SelectChannelConnector(server, sslContextFactory, http); connector.setPort(0); - HttpConfiguration httpConfiguration = new HttpConfiguration(sslContextFactory, true); - httpConfiguration.setRequestBufferSize(512); - httpConfiguration.setRequestHeaderSize(512); - connector.setDefaultConnectionFactory(new HttpServerConnectionFactory(connector, httpConfiguration)); server.addConnector(connector); } @@ -223,7 +225,7 @@ public class SSLEngineTest // System.err.println("read:"+i); // Read the response. String responses=readResponse(client[i]); - // Check the response + // Check the responses assertEquals(String.format("responses loop=%d connection=%d",l,i),RESPONSE0+RESPONSE0+RESPONSE1,responses); } } @@ -233,7 +235,13 @@ public class SSLEngineTest { if (client[i]!=null) { - client[i].close(); + try + { + assertEquals(-1,client[i].getInputStream().read()); + } + catch(SocketException e) + { + } } } } @@ -340,12 +348,13 @@ public class SSLEngineTest private static class HelloWorldHandler extends AbstractHandler { + @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // System.err.println("HANDLE "+request.getRequestURI()); String ssl_id = (String)request.getAttribute("javax.servlet.request.ssl_session_id"); assertNotNull(ssl_id); - + if (request.getParameter("dump")!=null) { ServletOutputStream out=response.getOutputStream(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java index 246e0955b84..f7bdbc83c5e 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java @@ -32,6 +32,7 @@ import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; + import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManagerFactory; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java index 81ef6f254b2..fde39fff675 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java @@ -18,12 +18,15 @@ package org.eclipse.jetty.server.ssl; +import static org.junit.Assert.assertEquals; + import java.io.FileInputStream; import java.io.OutputStream; import java.net.Socket; import java.net.SocketException; import java.security.KeyStore; import java.util.Arrays; + import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; @@ -37,8 +40,6 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.assertEquals; - /** * HttpServer Tester. */ @@ -109,7 +110,7 @@ public class SelectChannelServerSslTest extends HttpServerTestBase startServer(connector); KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); - keystore.load(new FileInputStream(connector.getSslContextFactory().getKeyStorePath()), "storepwd".toCharArray()); + keystore.load(new FileInputStream(sslContextFactory.getKeyStorePath()), "storepwd".toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keystore); __sslContext = SSLContext.getInstance("TLS"); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesServerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesServerTest.java index 77908e9de69..e5afb0b8e71 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesServerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesServerTest.java @@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; + import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.servlet.ServletException; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslSelectChannelTimeoutTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslSelectChannelTimeoutTest.java index 036727da2e3..84ad857d23f 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslSelectChannelTimeoutTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslSelectChannelTimeoutTest.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.server.ssl; import java.io.FileInputStream; import java.net.Socket; import java.security.KeyStore; + import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java index acea0dda80d..8008dca8d6f 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java @@ -18,12 +18,16 @@ package org.eclipse.jetty.server.ssl; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.KeyStore; import java.util.Arrays; + import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManagerFactory; @@ -34,6 +38,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -42,9 +47,6 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - /** */ public class SslUploadTest @@ -85,7 +87,8 @@ public class SslUploadTest public void test() throws Exception { KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); - keystore.load(new FileInputStream(connector.getSslContextFactory().getKeyStorePath()), "storepwd".toCharArray()); + SslContextFactory ctx=connector.getConnectionFactory(SslConnectionFactory.class).getSslContextFactory(); + keystore.load(new FileInputStream(ctx.getKeyStorePath()), "storepwd".toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keystore); SSLContext sslContext = SSLContext.getInstance("SSL"); @@ -137,13 +140,14 @@ public class SslUploadTest assertTrue (response.indexOf("200")>0); // System.err.println(response); - long end = System.nanoTime(); + // long end = System.nanoTime(); // System.out.println("upload time: " + TimeUnit.NANOSECONDS.toMillis(end - start)); assertEquals(requestContent.length, total); } private static class EmptyHandler extends AbstractHandler { + @Override public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { request.setHandled(true); diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnectionFactory.java similarity index 76% rename from jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYConnectionFactory.java rename to jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnectionFactory.java index c4f499523c5..81adcff8f0f 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYConnectionFactory.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnectionFactory.java @@ -19,13 +19,10 @@ package org.eclipse.jetty.spdy.http; -import java.util.concurrent.Executor; - -import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.spdy.ServerSPDYConnectionFactory; +import org.eclipse.jetty.server.HttpChannelConfig; +import org.eclipse.jetty.spdy.SPDYServerConnectionFactory; import org.eclipse.jetty.spdy.api.DataInfo; import org.eclipse.jetty.spdy.api.HeadersInfo; import org.eclipse.jetty.spdy.api.ReplyInfo; @@ -36,38 +33,44 @@ import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; import org.eclipse.jetty.util.Fields; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.thread.Scheduler; -public class ServerHTTPSPDYConnectionFactory extends ServerSPDYConnectionFactory +public class HTTPSPDYServerConnectionFactory extends SPDYServerConnectionFactory implements HttpChannelConfig.ConnectionFactory { private static final String CHANNEL_ATTRIBUTE = "org.eclipse.jetty.spdy.http.HTTPChannelOverSPDY"; - private static final Logger logger = Log.getLogger(ServerHTTPSPDYConnectionFactory.class); + private static final Logger logger = Log.getLogger(HTTPSPDYServerConnectionFactory.class); - private final Connector connector; private final PushStrategy pushStrategy; - private final HttpConfiguration configuration; + private final HttpChannelConfig httpChannelConfig; - public ServerHTTPSPDYConnectionFactory(short version, ByteBufferPool bufferPool, Executor threadPool, Scheduler scheduler, Connector connector, PushStrategy pushStrategy) + public HTTPSPDYServerConnectionFactory(int version, HttpChannelConfig config, PushStrategy pushStrategy) { - super(version, bufferPool, threadPool, scheduler); - this.connector = connector; + super(version); this.pushStrategy = pushStrategy; - this.configuration = new HttpConfiguration(connector.getSslContextFactory(), connector.getSslContextFactory() != null); + httpChannelConfig = config; + addBean(httpChannelConfig); } @Override - protected ServerSessionFrameListener provideServerSessionFrameListener(EndPoint endPoint, Object attachment) + public HttpChannelConfig getHttpChannelConfig() { - return new HTTPServerFrameListener(endPoint); + return httpChannelConfig; + } + + @Override + protected ServerSessionFrameListener provideServerSessionFrameListener(Connector connector, EndPoint endPoint) + { + return new HTTPServerFrameListener(connector,endPoint); } private class HTTPServerFrameListener extends ServerSessionFrameListener.Adapter implements StreamFrameListener { + private final Connector connector; private final EndPoint endPoint; - public HTTPServerFrameListener(EndPoint endPoint) + public HTTPServerFrameListener(Connector connector,EndPoint endPoint) { this.endPoint = endPoint; + this.connector=connector; } @Override @@ -82,9 +85,9 @@ public class ServerHTTPSPDYConnectionFactory extends ServerSPDYConnectionFactory logger.debug("Received {} on {}", synInfo, stream); Fields headers = synInfo.getHeaders(); - HttpTransportOverSPDY transport = new HttpTransportOverSPDY(connector, configuration, endPoint, pushStrategy, stream, headers); + HttpTransportOverSPDY transport = new HttpTransportOverSPDY(connector, httpChannelConfig, endPoint, pushStrategy, stream, headers); HttpInputOverSPDY input = new HttpInputOverSPDY(); - HttpChannelOverSPDY channel = new HttpChannelOverSPDY(connector, configuration, endPoint, transport, input, stream); + HttpChannelOverSPDY channel = new HttpChannelOverSPDY(connector, httpChannelConfig, endPoint, transport, input, stream); stream.setAttribute(CHANNEL_ATTRIBUTE, channel); channel.requestStart(headers, synInfo.isClose()); diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java index 876fb4c467f..9339b97e73f 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java @@ -22,13 +22,18 @@ package org.eclipse.jetty.spdy.http; import java.util.Collections; import java.util.Map; -import org.eclipse.jetty.server.HttpServerConnectionFactory; +import org.eclipse.jetty.server.AbstractConnectionFactory; +import org.eclipse.jetty.server.ConnectionFactory; +import org.eclipse.jetty.server.HttpChannelConfig; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.spdy.NPNServerConnectionFactory; import org.eclipse.jetty.spdy.SPDYServerConnector; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.util.ssl.SslContextFactory; -public class HTTPSPDYServerConnector extends SPDYServerConnector +public class HTTPSPDYServerConnector extends SelectChannelConnector { public HTTPSPDYServerConnector(Server server) { @@ -47,21 +52,21 @@ public class HTTPSPDYServerConnector extends SPDYServerConnector public HTTPSPDYServerConnector(Server server, SslContextFactory sslContextFactory, Map pushStrategies) { - // We pass a null ServerSessionFrameListener because for - // HTTP over SPDY we need one that references the endPoint - super(server, sslContextFactory, null); - clearConnectionFactories(); - // The "spdy/3" protocol handles HTTP over SPDY - putConnectionFactory("spdy/3", new ServerHTTPSPDYConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), this, getPushStrategy(SPDY.V3, pushStrategies))); - // The "spdy/2" protocol handles HTTP over SPDY - putConnectionFactory("spdy/2", new ServerHTTPSPDYConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, getPushStrategy(SPDY.V2, pushStrategies))); - // The "http/1.1" protocol handles browsers that support NPN but not SPDY - putConnectionFactory("http/1.1", new HttpServerConnectionFactory(this)); - // The default connection factory handles plain HTTP on non-SSL or non-NPN connections - setDefaultConnectionFactory(getConnectionFactory("http/1.1")); + this(server,new HttpChannelConfig(),sslContextFactory,pushStrategies); + } + + public HTTPSPDYServerConnector(Server server, HttpChannelConfig config, SslContextFactory sslContextFactory, Map pushStrategies) + { + super(server,AbstractConnectionFactory.getFactories(sslContextFactory, + sslContextFactory==null + ?new ConnectionFactory[] {new HttpConnectionFactory(config)} + :new ConnectionFactory[] {new NPNServerConnectionFactory("http/1.1","spdy/3","spdy/2"), + new HttpConnectionFactory(config), + new HTTPSPDYServerConnectionFactory(SPDY.V3,new HttpChannelConfig(),getPushStrategy(SPDY.V3, pushStrategies)), + new HTTPSPDYServerConnectionFactory(SPDY.V2,new HttpChannelConfig(),getPushStrategy(SPDY.V2, pushStrategies))})); } - private PushStrategy getPushStrategy(short version, Map pushStrategies) + private static PushStrategy getPushStrategy(short version, Map pushStrategies) { PushStrategy pushStrategy = pushStrategies.get(version); if (pushStrategy == null) diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HttpChannelOverSPDY.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HttpChannelOverSPDY.java index d69bbcd7738..ca6672c27bd 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HttpChannelOverSPDY.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HttpChannelOverSPDY.java @@ -28,7 +28,7 @@ import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpChannel; -import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpChannelConfig; import org.eclipse.jetty.server.HttpTransport; import org.eclipse.jetty.spdy.api.ByteBufferDataInfo; import org.eclipse.jetty.spdy.api.DataInfo; @@ -46,7 +46,7 @@ public class HttpChannelOverSPDY extends HttpChannel private boolean dispatched; // Guarded by synchronization on tasks private boolean headersComplete; - public HttpChannelOverSPDY(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransport transport, HttpInputOverSPDY input, Stream stream) + public HttpChannelOverSPDY(Connector connector, HttpChannelConfig configuration, EndPoint endPoint, HttpTransport transport, HttpInputOverSPDY input, Stream stream) { super(connector, configuration, endPoint, transport, input); this.stream = stream; diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HttpTransportOverSPDY.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HttpTransportOverSPDY.java index a74aa92d822..f8f7e4142d8 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HttpTransportOverSPDY.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HttpTransportOverSPDY.java @@ -29,7 +29,7 @@ import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpChannelConfig; import org.eclipse.jetty.server.HttpTransport; import org.eclipse.jetty.spdy.api.ByteBufferDataInfo; import org.eclipse.jetty.spdy.api.ReplyInfo; @@ -47,13 +47,13 @@ public class HttpTransportOverSPDY implements HttpTransport private static final Logger LOG = Log.getLogger(HttpTransportOverSPDY.class); private final Connector connector; - private final HttpConfiguration configuration; + private final HttpChannelConfig configuration; private final EndPoint endPoint; private final PushStrategy pushStrategy; private final Stream stream; private final Fields requestHeaders; - public HttpTransportOverSPDY(Connector connector, HttpConfiguration configuration, EndPoint endPoint, PushStrategy pushStrategy, Stream stream, Fields requestHeaders) + public HttpTransportOverSPDY(Connector connector, HttpChannelConfig configuration, EndPoint endPoint, PushStrategy pushStrategy, Stream stream, Fields requestHeaders) { this.connector = connector; this.configuration = configuration; diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java index 7f7569ec552..d135c8f177f 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java @@ -19,9 +19,9 @@ package org.eclipse.jetty.spdy.proxy; +import org.eclipse.jetty.server.HttpChannelConfig; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.spdy.SPDYServerConnector; -import org.eclipse.jetty.spdy.ServerSPDYConnectionFactory; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -35,11 +35,6 @@ public class HTTPSPDYProxyConnector extends SPDYServerConnector public HTTPSPDYProxyConnector(Server server, SslContextFactory sslContextFactory, ProxyEngineSelector proxyEngineSelector) { super(server, sslContextFactory, proxyEngineSelector); - clearConnectionFactories(); - - putConnectionFactory("spdy/3", new ServerSPDYConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), proxyEngineSelector)); - putConnectionFactory("spdy/2", new ServerSPDYConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), proxyEngineSelector)); - putConnectionFactory("http/1.1", new ProxyHTTPConnectionFactory(this, SPDY.V2, proxyEngineSelector)); - setDefaultConnectionFactory(getConnectionFactory("http/1.1")); + addConnectionFactory(new ProxyHTTPConnectionFactory(new HttpChannelConfig(), SPDY.V2, proxyEngineSelector)); } } diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPConnectionFactory.java index 85eaa34ee42..6e3380b2647 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPConnectionFactory.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPConnectionFactory.java @@ -19,29 +19,40 @@ package org.eclipse.jetty.spdy.proxy; -import java.nio.channels.SocketChannel; +import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.server.AbstractConnectionFactory; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpChannelConfig; -public class ProxyHTTPConnectionFactory implements ConnectionFactory +public class ProxyHTTPConnectionFactory extends AbstractConnectionFactory implements HttpChannelConfig.ConnectionFactory { - private final Connector connector; private final short version; private final ProxyEngineSelector proxyEngineSelector; + private final HttpChannelConfig httpChannelConfig; - public ProxyHTTPConnectionFactory(Connector connector, short version, ProxyEngineSelector proxyEngineSelector) + public ProxyHTTPConnectionFactory(HttpChannelConfig httpChannelConfig,short version, ProxyEngineSelector proxyEngineSelector) { - this.connector = connector; + // replaces http/1.1 + super(HttpVersion.HTTP_1_1.asString()); this.version = version; this.proxyEngineSelector = proxyEngineSelector; + this.httpChannelConfig=httpChannelConfig; } @Override - public Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment) + public Connection newConnection(Connector connector, EndPoint endPoint) { - return new ProxyHTTPSPDYConnection(connector, endPoint, version, proxyEngineSelector); + return new ProxyHTTPSPDYConnection(connector, httpChannelConfig, endPoint, version, proxyEngineSelector); } + + @Override + public HttpChannelConfig getHttpChannelConfig() + { + return httpChannelConfig; + } + } diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYConnection.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYConnection.java index 91c4b18263f..babb325426d 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYConnection.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYConnection.java @@ -32,8 +32,9 @@ import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpChannelConfig; import org.eclipse.jetty.server.HttpConnection; +import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.spdy.ISession; import org.eclipse.jetty.spdy.IStream; import org.eclipse.jetty.spdy.StandardSession; @@ -61,9 +62,9 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse private HTTPStream stream; private ByteBuffer content; - public ProxyHTTPSPDYConnection(Connector connector, EndPoint endPoint, short version, ProxyEngineSelector proxyEngineSelector) + public ProxyHTTPSPDYConnection(Connector connector, HttpChannelConfig config, EndPoint endPoint, short version, ProxyEngineSelector proxyEngineSelector) { - super(new HttpConfiguration(connector.getSslContextFactory(), connector.getSslContextFactory() != null), connector, endPoint); + super(config,connector,endPoint); this.version = version; this.proxyEngineSelector = proxyEngineSelector; this.session = new HTTPSession(version, connector); @@ -80,7 +81,7 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse public boolean startRequest(HttpMethod method, String methodString, String uri, HttpVersion httpVersion) { Connector connector = getConnector(); - String scheme = connector.getSslContextFactory() != null ? "https" : "http"; + String scheme = connector.getConnectionFactory(SslConnectionFactory.class) != null ? "https" : "http"; headers.put(HTTPSPDYHeader.SCHEME.name(version), scheme); headers.put(HTTPSPDYHeader.METHOD.name(version), methodString); headers.put(HTTPSPDYHeader.URI.name(version), uri); diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java index d9e44e43a9a..aa21fdfa731 100644 --- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java +++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java @@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HttpChannelConfig; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.spdy.SPDYClient; import org.eclipse.jetty.spdy.SPDYServerConnector; @@ -65,7 +66,7 @@ public abstract class AbstractHTTPSPDYTest protected final short version; protected Server server; protected SPDYClient.Factory clientFactory; - protected SPDYServerConnector connector; + protected HTTPSPDYServerConnector connector; protected AbstractHTTPSPDYTest(short version) { @@ -89,12 +90,13 @@ public abstract class AbstractHTTPSPDYTest return new InetSocketAddress("localhost", connector.getLocalPort()); } - protected SPDYServerConnector newHTTPSPDYServerConnector(short version) + protected HTTPSPDYServerConnector newHTTPSPDYServerConnector(short version) { // For these tests, we need the connector to speak HTTP over SPDY even in non-SSL - SPDYServerConnector connector = new HTTPSPDYServerConnector(server); - ConnectionFactory defaultFactory = new ServerHTTPSPDYConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, new PushStrategy.None()); - connector.setDefaultConnectionFactory(defaultFactory); + HTTPSPDYServerConnector connector = new HTTPSPDYServerConnector(server); + ConnectionFactory defaultFactory = new HTTPSPDYServerConnectionFactory(version,new HttpChannelConfig(), new PushStrategy.None()); + connector.addConnectionFactory(defaultFactory); + connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right return connector; } diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java index fc189643382..121a9ad76db 100644 --- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java +++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java @@ -29,7 +29,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import org.eclipse.jetty.npn.NextProtoNego; -import org.eclipse.jetty.server.HttpServerConnectionFactory; +import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.spdy.SPDYServerConnector; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -86,7 +86,7 @@ public class ProtocolNegotiationTest public void testServerAdvertisingHTTPSpeaksHTTP() throws Exception { InetSocketAddress address = startServer(null); - connector.putConnectionFactory("http/1.1", new HttpServerConnectionFactory(connector)); + connector.addConnectionFactory(new HttpConnectionFactory()); SslContextFactory sslContextFactory = newSslContextFactory(); sslContextFactory.start(); @@ -142,7 +142,7 @@ public class ProtocolNegotiationTest public void testServerAdvertisingSPDYAndHTTPSpeaksHTTPWhenNegotiated() throws Exception { InetSocketAddress address = startServer(null); - connector.putConnectionFactory("http/1.1", new HttpServerConnectionFactory(connector)); + connector.addConnectionFactory(new HttpConnectionFactory()); SslContextFactory sslContextFactory = newSslContextFactory(); sslContextFactory.start(); @@ -201,8 +201,7 @@ public class ProtocolNegotiationTest public void testServerAdvertisingSPDYAndHTTPSpeaksDefaultProtocolWhenNPNMissing() throws Exception { InetSocketAddress address = startServer(null); - connector.setDefaultConnectionFactory(new HttpServerConnectionFactory(connector)); - connector.putConnectionFactory("http/1.1", connector.getDefaultConnectionFactory()); + connector.addConnectionFactory(new HttpConnectionFactory()); SslContextFactory sslContextFactory = newSslContextFactory(); sslContextFactory.start(); diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java index 14d5bba2c94..8862715c192 100644 --- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java +++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.ConnectionFactory; +import org.eclipse.jetty.server.HttpChannelConfig; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.spdy.SPDYServerConnector; @@ -54,11 +55,12 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest } @Override - protected SPDYServerConnector newHTTPSPDYServerConnector(short version) + protected HTTPSPDYServerConnector newHTTPSPDYServerConnector(short version) { - SPDYServerConnector connector = super.newHTTPSPDYServerConnector(version); - ConnectionFactory defaultFactory = new ServerHTTPSPDYConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, new ReferrerPushStrategy()); - connector.setDefaultConnectionFactory(defaultFactory); + HTTPSPDYServerConnector connector = super.newHTTPSPDYServerConnector(version); + ConnectionFactory defaultFactory = new HTTPSPDYServerConnectionFactory(version,new HttpChannelConfig(), new ReferrerPushStrategy()); + connector.addConnectionFactory(defaultFactory); + connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right return connector; } @@ -70,8 +72,9 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy(); int referrerPushPeriod = 1000; pushStrategy.setReferrerPushPeriod(referrerPushPeriod); - ConnectionFactory defaultFactory = new ServerHTTPSPDYConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy); - connector.setDefaultConnectionFactory(defaultFactory); + ConnectionFactory defaultFactory = new HTTPSPDYServerConnectionFactory(version,new HttpChannelConfig(), pushStrategy); + connector.addConnectionFactory(defaultFactory); + connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right Fields mainRequestHeaders = createHeadersWithoutReferrer(mainResource); Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders); @@ -92,9 +95,9 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy(); int referrerPushPeriod = 1000; pushStrategy.setReferrerPushPeriod(referrerPushPeriod); - ConnectionFactory defaultFactory = new ServerHTTPSPDYConnectionFactory(version, - connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy); - connector.setDefaultConnectionFactory(defaultFactory); + ConnectionFactory defaultFactory = new HTTPSPDYServerConnectionFactory(version,new HttpChannelConfig(), pushStrategy); + connector.addConnectionFactory(defaultFactory); + connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right Fields mainRequestHeaders = createHeadersWithoutReferrer(mainResource); Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders); @@ -114,9 +117,9 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy(); pushStrategy.setMaxAssociatedResources(1); - ConnectionFactory defaultFactory = new ServerHTTPSPDYConnectionFactory(version, - connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy); - connector.setDefaultConnectionFactory(defaultFactory); + ConnectionFactory defaultFactory = new HTTPSPDYServerConnectionFactory(version,new HttpChannelConfig(), pushStrategy); + connector.addConnectionFactory(defaultFactory); + connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right Fields mainRequestHeaders = createHeadersWithoutReferrer(mainResource); Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders); diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYTest.java index 2753496fd4b..8ca2cdaaeba 100644 --- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYTest.java +++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYTest.java @@ -33,7 +33,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.spdy.SPDYClient; import org.eclipse.jetty.spdy.SPDYServerConnector; -import org.eclipse.jetty.spdy.ServerSPDYConnectionFactory; +import org.eclipse.jetty.spdy.SPDYServerConnectionFactory; import org.eclipse.jetty.spdy.api.BytesDataInfo; import org.eclipse.jetty.spdy.api.DataInfo; import org.eclipse.jetty.spdy.api.GoAwayInfo; @@ -100,8 +100,7 @@ public class ProxyHTTPSPDYTest { server = new Server(); SPDYServerConnector serverConnector = new SPDYServerConnector(server, listener); - serverConnector.setDefaultConnectionFactory(new ServerSPDYConnectionFactory(version, - serverConnector.getByteBufferPool(), serverConnector.getExecutor(), serverConnector.getScheduler(), listener)); + serverConnector.addConnectionFactory(new SPDYServerConnectionFactory(version,listener)); serverConnector.setPort(0); server.addConnector(serverConnector); server.start(); @@ -464,7 +463,7 @@ public class ProxyHTTPSPDYTest return null; } })); - proxyConnector.setDefaultConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); + proxyConnector.addConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); Session client = factory.newSPDYClient(version).connect(proxyAddress, null).get(5, TimeUnit.SECONDS); @@ -509,7 +508,7 @@ public class ProxyHTTPSPDYTest return null; } })); - proxyConnector.setDefaultConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); + proxyConnector.addConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); Session client = factory.newSPDYClient(version).connect(proxyAddress, null).get(5, TimeUnit.SECONDS); @@ -630,7 +629,7 @@ public class ProxyHTTPSPDYTest return null; } })); - proxyConnector.setDefaultConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); + proxyConnector.addConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); final CountDownLatch pushSynLatch = new CountDownLatch(1); final CountDownLatch pushDataLatch = new CountDownLatch(1); @@ -689,7 +688,7 @@ public class ProxyHTTPSPDYTest // We just verify that it works InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter())); - proxyConnector.setDefaultConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); + proxyConnector.addConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); final CountDownLatch pingLatch = new CountDownLatch(1); Session client = factory.newSPDYClient(version).connect(proxyAddress, new SessionFrameListener.Adapter() @@ -761,7 +760,7 @@ public class ProxyHTTPSPDYTest return null; } })); - proxyConnector.setDefaultConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); + proxyConnector.addConnectionFactory(proxyConnector.getConnectionFactory("spdy/" + version)); final CountDownLatch resetLatch = new CountDownLatch(1); Session client = factory.newSPDYClient(version).connect(proxyAddress, new SessionFrameListener.Adapter() diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/NPNServerConnectionFactory.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/NPNServerConnectionFactory.java new file mode 100644 index 00000000000..38f34482023 --- /dev/null +++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/NPNServerConnectionFactory.java @@ -0,0 +1,87 @@ +// +// ======================================================================== +// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + + +package org.eclipse.jetty.spdy; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.io.ssl.SslConnection.DecryptedEndPoint; +import org.eclipse.jetty.server.AbstractConnectionFactory; +import org.eclipse.jetty.server.Connector; + +public class NPNServerConnectionFactory extends AbstractConnectionFactory +{ + private final List _protocols; + private String _defaultProtocol; + + public NPNServerConnectionFactory() + { + this(new String[0]); + } + + /* ------------------------------------------------------------ */ + /** + * @param protocols List of supported protocols. The first of these is set as the default protocol + */ + public NPNServerConnectionFactory(String... protocols) + { + super("npn"); + _protocols=Arrays.asList(protocols); + if (_protocols.size()>0) + _defaultProtocol=_protocols.get(0); + } + + public String getDefaultProtocol() + { + return _defaultProtocol; + } + + public void setDefaultProtocol(String defaultProtocol) + { + _defaultProtocol = defaultProtocol; + } + + public List getProtocols() + { + return _protocols; + } + + @Override + public Connection newConnection(Connector connector, EndPoint endPoint) + { + List protocols=_protocols; + if (protocols==null || protocols.size()==0) + { + protocols=connector.getProtocols(); + for (Iterator i=protocols.iterator();i.hasNext();) + { + String protocol=i.next(); + if (protocol.startsWith("SSL-")||protocol.equals("NPN")) + i.remove(); + } + } + + return new NextProtoNegoServerConnection((DecryptedEndPoint)endPoint, connector,protocols,_defaultProtocol); + } + +} diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/NextProtoNegoServerConnection.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/NextProtoNegoServerConnection.java index 2526fb266be..81f2bc50442 100644 --- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/NextProtoNegoServerConnection.java +++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/NextProtoNegoServerConnection.java @@ -19,14 +19,17 @@ package org.eclipse.jetty.spdy; import java.io.IOException; -import java.nio.channels.SocketChannel; import java.util.List; +import javax.net.ssl.SSLEngine; + import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.io.ssl.SslConnection.DecryptedEndPoint; import org.eclipse.jetty.npn.NextProtoNego; import org.eclipse.jetty.server.ConnectionFactory; +import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -34,15 +37,21 @@ import org.eclipse.jetty.util.log.Logger; public class NextProtoNegoServerConnection extends AbstractConnection implements NextProtoNego.ServerProvider { private final Logger logger = Log.getLogger(getClass()); - private final SocketChannel channel; - private final SPDYServerConnector connector; + private final Connector connector; + private final SSLEngine engine; + private final List protocols; + private final String defaultProtocol; private boolean completed; // No need to be volatile: it is modified and read by the same thread - - public NextProtoNegoServerConnection(SocketChannel channel, EndPoint endPoint, SPDYServerConnector connector) + + + public NextProtoNegoServerConnection(DecryptedEndPoint endPoint, Connector connector, Listprotocols, String defaultProtocol) { super(endPoint, connector.getExecutor()); - this.channel = channel; - this.connector = connector; + this.connector = connector; + this.protocols = protocols; + this.defaultProtocol=defaultProtocol; + engine = endPoint.getSslConnection().getSSLEngine(); + NextProtoNego.put(engine,this); } @Override @@ -51,6 +60,13 @@ public class NextProtoNegoServerConnection extends AbstractConnection implements super.onOpen(); fillInterested(); } + + @Override + public void onClose() + { + NextProtoNego.remove(engine); + super.onClose(); + }; @Override public void onFillable() @@ -82,17 +98,13 @@ public class NextProtoNegoServerConnection extends AbstractConnection implements @Override public void unsupported() { - ConnectionFactory connectionFactory = connector.getDefaultConnectionFactory(); - EndPoint endPoint = getEndPoint(); - Connection connection = connectionFactory.newConnection(channel, endPoint, connector); - connector.replaceConnection(endPoint, connection); - completed = true; + protocolSelected(defaultProtocol); } @Override public List protocols() { - return connector.provideProtocols(); + return protocols; } @Override @@ -100,8 +112,9 @@ public class NextProtoNegoServerConnection extends AbstractConnection implements { ConnectionFactory connectionFactory = connector.getConnectionFactory(protocol); EndPoint endPoint = getEndPoint(); - Connection connection = connectionFactory.newConnection(channel, endPoint, connector); - connector.replaceConnection(endPoint, connection); + Connection connection = connectionFactory.newConnection(connector, endPoint); + endPoint.setConnection(connection); + NextProtoNego.remove(engine); completed = true; } } diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java index 0a064d8efee..7a3424ea213 100644 --- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java +++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java @@ -30,6 +30,7 @@ import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.Future; + import javax.net.ssl.SSLEngine; import org.eclipse.jetty.io.ByteBufferPool; @@ -40,11 +41,8 @@ import org.eclipse.jetty.io.SelectChannelEndPoint; import org.eclipse.jetty.io.SelectorManager; import org.eclipse.jetty.io.ssl.SslConnection; import org.eclipse.jetty.npn.NextProtoNego; -import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.spdy.api.Session; import org.eclipse.jetty.spdy.api.SessionFrameListener; -import org.eclipse.jetty.spdy.generator.Generator; -import org.eclipse.jetty.spdy.parser.Parser; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -53,9 +51,9 @@ import org.eclipse.jetty.util.thread.TimerScheduler; public class SPDYClient { - private final ConnectionFactory connectionFactory = new ClientSPDYConnectionFactory(); - private final short version; - private final Factory factory; + private final SPDYClientConnectionFactory connectionFactory = new SPDYClientConnectionFactory(); + final short version; + final Factory factory; private volatile SocketAddress bindAddress; private volatile long idleTimeout = -1; private volatile int initialWindowSize; @@ -135,7 +133,7 @@ public class SPDYClient return null; } - public ConnectionFactory getConnectionFactory() + public SPDYClientConnectionFactory getConnectionFactory() { return connectionFactory; } @@ -164,9 +162,9 @@ public class SPDYClient public static class Factory extends AggregateLifeCycle { private final Queue sessions = new ConcurrentLinkedQueue<>(); - private final ByteBufferPool bufferPool = new MappedByteBufferPool(); - private final Scheduler scheduler = new TimerScheduler(); - private final Executor executor; + final ByteBufferPool bufferPool = new MappedByteBufferPool(); + final Scheduler scheduler = new TimerScheduler(); + final Executor executor; private final SslContextFactory sslContextFactory; private final SelectorManager selector; private final long idleTimeout; @@ -223,13 +221,13 @@ public class SPDYClient super.doStop(); } - private boolean sessionOpened(Session session) + boolean sessionOpened(Session session) { // Add sessions only if the factory is not stopping return isRunning() && sessions.offer(session); } - private boolean sessionClosed(Session session) + boolean sessionClosed(Session session) { // Remove sessions only if the factory is not stopping // to avoid concurrent removes during iterations @@ -300,7 +298,7 @@ public class SPDYClient } else { - ConnectionFactory connectionFactory = new ClientSPDYConnectionFactory(); + SPDYClientConnectionFactory connectionFactory = new SPDYClientConnectionFactory(); return connectionFactory.newConnection(channel, endPoint, attachment); } } @@ -313,11 +311,11 @@ public class SPDYClient } } - private static class SessionPromise extends Promise + static class SessionPromise extends Promise { private final SocketChannel channel; - private final SPDYClient client; - private final SessionFrameListener listener; + final SPDYClient client; + final SessionFrameListener listener; private SessionPromise(SocketChannel channel, SPDYClient client, SessionFrameListener listener) { @@ -341,51 +339,4 @@ public class SPDYClient } } } - - private static class ClientSPDYConnectionFactory implements ConnectionFactory - { - @Override - public Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment) - { - SessionPromise sessionPromise = (SessionPromise)attachment; - SPDYClient client = sessionPromise.client; - Factory factory = client.factory; - - CompressionFactory compressionFactory = new StandardCompressionFactory(); - Parser parser = new Parser(compressionFactory.newDecompressor()); - Generator generator = new Generator(factory.bufferPool, compressionFactory.newCompressor()); - - SPDYConnection connection = new ClientSPDYConnection(endPoint, factory.bufferPool, parser, factory); - - FlowControlStrategy flowControlStrategy = client.newFlowControlStrategy(); - - StandardSession session = new StandardSession(client.version, factory.bufferPool, factory.executor, factory.scheduler, connection, connection, 1, sessionPromise.listener, generator, flowControlStrategy); - session.setWindowSize(client.getInitialWindowSize()); - parser.addListener(session); - sessionPromise.completed(session); - connection.setSession(session); - - factory.sessionOpened(session); - - return connection; - } - - private class ClientSPDYConnection extends SPDYConnection - { - private final Factory factory; - - public ClientSPDYConnection(EndPoint endPoint, ByteBufferPool bufferPool, Parser parser, Factory factory) - { - super(endPoint, bufferPool, parser, factory.executor); - this.factory = factory; - } - - @Override - public void onClose() - { - super.onClose(); - factory.sessionClosed(getSession()); - } - } - } } diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClientConnectionFactory.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClientConnectionFactory.java new file mode 100644 index 00000000000..75c4114cb91 --- /dev/null +++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClientConnectionFactory.java @@ -0,0 +1,75 @@ +// +// ======================================================================== +// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.spdy; + +import java.nio.channels.SocketChannel; + +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.spdy.SPDYClient.Factory; +import org.eclipse.jetty.spdy.SPDYClient.SessionPromise; +import org.eclipse.jetty.spdy.generator.Generator; +import org.eclipse.jetty.spdy.parser.Parser; + +public class SPDYClientConnectionFactory +{ + public Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment) + { + SessionPromise sessionPromise = (SessionPromise)attachment; + SPDYClient client = sessionPromise.client; + Factory factory = client.factory; + + CompressionFactory compressionFactory = new StandardCompressionFactory(); + Parser parser = new Parser(compressionFactory.newDecompressor()); + Generator generator = new Generator(factory.bufferPool, compressionFactory.newCompressor()); + + SPDYConnection connection = new ClientSPDYConnection(endPoint, factory.bufferPool, parser, factory); + + FlowControlStrategy flowControlStrategy = client.newFlowControlStrategy(); + + StandardSession session = new StandardSession(client.version, factory.bufferPool, factory.executor, factory.scheduler, connection, connection, 1, sessionPromise.listener, generator, flowControlStrategy); + session.setWindowSize(client.getInitialWindowSize()); + parser.addListener(session); + sessionPromise.completed(session); + connection.setSession(session); + + factory.sessionOpened(session); + + return connection; + } + + private class ClientSPDYConnection extends SPDYConnection + { + private final Factory factory; + + public ClientSPDYConnection(EndPoint endPoint, ByteBufferPool bufferPool, Parser parser, Factory factory) + { + super(endPoint, bufferPool, parser, factory.executor); + this.factory = factory; + } + + @Override + public void onClose() + { + super.onClose(); + factory.sessionClosed(getSession()); + } + } +} diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYConnection.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYConnection.java index 304a3580dd6..5a5b8ce0517 100644 --- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYConnection.java +++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYConnection.java @@ -36,15 +36,23 @@ public class SPDYConnection extends AbstractConnection implements Controller sessions = new ConcurrentLinkedQueue<>(); + + public SPDYServerConnectionFactory(int version) + { + this(version, null); + } + + public SPDYServerConnectionFactory(int version, ServerSessionFrameListener listener) + { + super("spdy/"+version); + this.version = (short)version; + this.listener = listener; + setInitialWindowSize(65536); + } + + public short getVersion() + { + return version; + } + + public ServerSessionFrameListener getServerSessionFrameListener() + { + return listener; + } + + @Override + public Connection newConnection(Connector connector, EndPoint endPoint) + { + CompressionFactory compressionFactory = new StandardCompressionFactory(); + Parser parser = new Parser(compressionFactory.newDecompressor()); + Generator generator = new Generator(connector.getByteBufferPool(), compressionFactory.newCompressor()); + + ServerSessionFrameListener listener = provideServerSessionFrameListener(connector,endPoint); + SPDYConnection connection = new ServerSPDYConnection(connector,endPoint, parser, listener, getInputBufferSize()); + + FlowControlStrategy flowControlStrategy = newFlowControlStrategy(version); + + StandardSession session = new StandardSession(getVersion(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connection, connection, 2, listener, generator, flowControlStrategy); + session.setAttribute("org.eclipse.jetty.spdy.remoteAddress", endPoint.getRemoteAddress()); // TODO: make this available through API + session.setWindowSize(getInitialWindowSize()); + parser.addListener(session); + connection.setSession(session); + + sessionOpened(session); + + return connection; + } + + protected FlowControlStrategy newFlowControlStrategy(short version) + { + return FlowControlStrategyFactory.newFlowControlStrategy(version); + } + + protected ServerSessionFrameListener provideServerSessionFrameListener(Connector connector, EndPoint endPoint) + { + return listener; + } + + public int getInitialWindowSize() + { + return initialWindowSize; + } + + public void setInitialWindowSize(int initialWindowSize) + { + this.initialWindowSize = initialWindowSize; + } + + protected boolean sessionOpened(Session session) + { + // Add sessions only if the connector is not stopping + return sessions.offer(session); + } + + protected boolean sessionClosed(Session session) + { + // Remove sessions only if the connector is not stopping + // to avoid concurrent removes during iterations + return sessions.remove(session); + } + + void closeSessions() + { + for (Session session : sessions) + session.goAway(); + sessions.clear(); + } + + @Override + protected void doStop() throws Exception + { + closeSessions(); + super.doStop(); + } + + protected Collection getSessions() + { + return Collections.unmodifiableCollection(sessions); + } + + private class ServerSPDYConnection extends SPDYConnection implements Runnable + { + private final ServerSessionFrameListener listener; + private final AtomicBoolean connected = new AtomicBoolean(); + + private ServerSPDYConnection(Connector connector,EndPoint endPoint, Parser parser, ServerSessionFrameListener listener, int bufferSize) + { + super(endPoint, connector.getByteBufferPool(), parser, connector.getExecutor(),bufferSize); + this.listener = listener; + } + + @Override + public void onOpen() + { + super.onOpen(); + if (connected.compareAndSet(false, true)) + getExecutor().execute(this); + } + + @Override + public void onClose() + { + super.onClose(); + sessionClosed(getSession()); + } + + @Override + public void run() + { + // NPE guard to support tests + if (listener != null) + listener.onConnect(getSession()); + } + } + +} diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java index f0eb71df08d..97d39d894e8 100644 --- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java +++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java @@ -18,34 +18,16 @@ package org.eclipse.jetty.spdy; -import java.io.IOException; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; -import javax.net.ssl.SSLEngine; - -import org.eclipse.jetty.io.Connection; -import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.io.ssl.SslConnection; -import org.eclipse.jetty.npn.NextProtoNego; +import org.eclipse.jetty.server.ConnectionFactory; +import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SelectChannelConnector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.spdy.api.SPDY; -import org.eclipse.jetty.spdy.api.Session; import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; -import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.ssl.SslContextFactory; public class SPDYServerConnector extends SelectChannelConnector { - private final Queue sessions = new ConcurrentLinkedQueue<>(); - private final ServerSessionFrameListener listener; - private volatile int initialWindowSize; - public SPDYServerConnector(Server server, ServerSessionFrameListener listener) { this(server, null, listener); @@ -53,131 +35,15 @@ public class SPDYServerConnector extends SelectChannelConnector public SPDYServerConnector(Server server, SslContextFactory sslContextFactory, ServerSessionFrameListener listener) { - super(server, sslContextFactory); - this.listener = listener; - setInitialWindowSize(65536); - putConnectionFactory("spdy/3", new ServerSPDYConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), listener)); - putConnectionFactory("spdy/2", new ServerSPDYConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), listener)); - setDefaultConnectionFactory(getConnectionFactory("spdy/2")); + super(server, + sslContextFactory, + sslContextFactory==null + ?new ConnectionFactory[]{new SPDYServerConnectionFactory(SPDY.V2, listener)} + :new ConnectionFactory[]{ + new NPNServerConnectionFactory("http/1.1","spdy/2","spdy/3"), + new HttpConnectionFactory(), + new SPDYServerConnectionFactory(SPDY.V2, listener), + new SPDYServerConnectionFactory(SPDY.V3, listener)}); } - public ServerSessionFrameListener getServerSessionFrameListener() - { - return listener; - } - - @Override - protected void doStart() throws Exception - { - super.doStart(); - LOG.info("SPDY support is experimental. Please report feedback at jetty-dev@eclipse.org"); - } - - @Override - protected void doStop() throws Exception - { - closeSessions(); - super.doStop(); - } - - protected List provideProtocols() - { - return new ArrayList<>(getConnectionFactories().keySet()); - } - - @Override - protected Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment) - { - SslContextFactory sslContextFactory = getSslContextFactory(); - if (sslContextFactory != null) - { - final SSLEngine engine = newSSLEngine(sslContextFactory, channel); - SslConnection sslConnection = new SslConnection(getByteBufferPool(), getExecutor(), endPoint, engine) - { - @Override - public void onClose() - { - NextProtoNego.remove(engine); - super.onClose(); - } - }; - - final EndPoint sslEndPoint = sslConnection.getDecryptedEndPoint(); - NextProtoNegoServerConnection connection = new NextProtoNegoServerConnection(channel, sslEndPoint, this); - sslEndPoint.setConnection(connection); - getSelectorManager().connectionOpened(connection); - - NextProtoNego.put(engine, connection); - - return sslConnection; - } - else - { - return super.newConnection(channel, endPoint, this); - } - } - - protected FlowControlStrategy newFlowControlStrategy(short version) - { - return FlowControlStrategyFactory.newFlowControlStrategy(version); - } - - protected SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel) - { - String peerHost = channel.socket().getInetAddress().getHostAddress(); - int peerPort = channel.socket().getPort(); - SSLEngine engine = sslContextFactory.newSSLEngine(peerHost, peerPort); - engine.setUseClientMode(false); - return engine; - } - - protected boolean sessionOpened(Session session) - { - // Add sessions only if the connector is not stopping - return isRunning() && sessions.offer(session); - } - - protected boolean sessionClosed(Session session) - { - // Remove sessions only if the connector is not stopping - // to avoid concurrent removes during iterations - return isRunning() && sessions.remove(session); - } - - private void closeSessions() - { - for (Session session : sessions) - session.goAway(); - sessions.clear(); - } - - protected Collection getSessions() - { - return Collections.unmodifiableCollection(sessions); - } - - public int getInitialWindowSize() - { - return initialWindowSize; - } - - public void setInitialWindowSize(int initialWindowSize) - { - this.initialWindowSize = initialWindowSize; - } - - public void replaceConnection(EndPoint endPoint, Connection connection) - { - Connection oldConnection = endPoint.getConnection(); - LOG.debug("Upgrading connection {} -> {} on endPoint {}", oldConnection, connection, endPoint); - endPoint.setConnection(connection); - getSelectorManager().connectionUpgraded(endPoint, oldConnection); - } - - @Override - public void dump(Appendable out, String indent) throws IOException - { - super.dump(out, indent); - AggregateLifeCycle.dump(out, indent, new ArrayList<>(sessions)); - } } diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/ServerSPDYConnectionFactory.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/ServerSPDYConnectionFactory.java deleted file mode 100644 index 57116a538dc..00000000000 --- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/ServerSPDYConnectionFactory.java +++ /dev/null @@ -1,142 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.spdy; - -import java.nio.channels.SocketChannel; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.io.Connection; -import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.server.ConnectionFactory; -import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; -import org.eclipse.jetty.spdy.generator.Generator; -import org.eclipse.jetty.spdy.parser.Parser; -import org.eclipse.jetty.util.thread.Scheduler; - -public class ServerSPDYConnectionFactory implements ConnectionFactory -{ - private final ByteBufferPool bufferPool; - private final Executor executor; - private final Scheduler scheduler; - private final short version; - private final ServerSessionFrameListener listener; - - public ServerSPDYConnectionFactory(short version, ByteBufferPool bufferPool, Executor executor, Scheduler scheduler) - { - this(version, bufferPool, executor, scheduler, null); - } - - public ServerSPDYConnectionFactory(short version, ByteBufferPool bufferPool, Executor executor, Scheduler scheduler, ServerSessionFrameListener listener) - { - this.version = version; - this.bufferPool = bufferPool; - this.executor = executor; - this.scheduler = scheduler; - this.listener = listener; - } - - public short getVersion() - { - return version; - } - - @Override - public Connection newConnection(SocketChannel channel, EndPoint endPoint, Object attachment) - { - CompressionFactory compressionFactory = new StandardCompressionFactory(); - Parser parser = new Parser(compressionFactory.newDecompressor()); - Generator generator = new Generator(bufferPool, compressionFactory.newCompressor()); - - SPDYServerConnector connector = (SPDYServerConnector)attachment; - - ServerSessionFrameListener listener = provideServerSessionFrameListener(endPoint, attachment); - SPDYConnection connection = new ServerSPDYConnection(endPoint, bufferPool, parser, listener, connector); - - FlowControlStrategy flowControlStrategy = connector.newFlowControlStrategy(version); - - StandardSession session = new StandardSession(getVersion(), getBufferPool(), getExecutor(), getScheduler(), connection, connection, 2, listener, generator, flowControlStrategy); - session.setAttribute("org.eclipse.jetty.spdy.remoteAddress", endPoint.getRemoteAddress()); // TODO: make this available through API - session.setWindowSize(connector.getInitialWindowSize()); - parser.addListener(session); - connection.setSession(session); - - connector.sessionOpened(session); - - return connection; - } - - protected ServerSessionFrameListener provideServerSessionFrameListener(EndPoint endPoint, Object attachment) - { - return listener; - } - - protected ByteBufferPool getBufferPool() - { - return bufferPool; - } - - protected Executor getExecutor() - { - return executor; - } - - public Scheduler getScheduler() - { - return scheduler; - } - - private static class ServerSPDYConnection extends SPDYConnection implements Runnable - { - private final ServerSessionFrameListener listener; - private final SPDYServerConnector connector; - private final AtomicBoolean connected = new AtomicBoolean(); - - private ServerSPDYConnection(EndPoint endPoint, ByteBufferPool bufferPool, Parser parser, ServerSessionFrameListener listener, SPDYServerConnector connector) - { - super(endPoint, bufferPool, parser, connector.getExecutor()); - this.listener = listener; - this.connector = connector; - } - - @Override - public void onOpen() - { - super.onOpen(); - if (connected.compareAndSet(false, true)) - getExecutor().execute(this); - } - - @Override - public void onClose() - { - super.onClose(); - connector.sessionClosed(getSession()); - } - - @Override - public void run() - { - // NPE guard to support tests - if (listener != null) - listener.onConnect(getSession()); - } - } -} diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java index c5ba9af3860..b1c4228bf2c 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java @@ -23,6 +23,7 @@ import java.net.InetSocketAddress; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.spdy.api.Session; @@ -66,8 +67,10 @@ public abstract class AbstractTest if (connector == null) connector = newSPDYServerConnector(server, listener); if (listener == null) - listener = connector.getServerSessionFrameListener(); - connector.setDefaultConnectionFactory(new ServerSPDYConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), listener)); + listener = connector.getConnectionFactory(SPDYServerConnectionFactory.class).getServerSessionFrameListener(); + + ConnectionFactory spdy = new SPDYServerConnectionFactory(version, listener); + connector.addConnectionFactory(spdy); connector.setPort(0); server.addConnector(connector); server.start(); diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java index 65a1edce603..49ddc2c661d 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java @@ -18,6 +18,10 @@ package org.eclipse.jetty.spdy; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThat; + import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; @@ -52,10 +56,6 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertThat; - public class ClosedStreamTest extends AbstractTest { //TODO: Right now it sends a rst as the stream is unknown to the session once it's closed. diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java index 39b1c6842a3..15f91c94e59 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java @@ -19,6 +19,9 @@ package org.eclipse.jetty.spdy; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + import java.nio.ByteBuffer; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; @@ -45,9 +48,6 @@ import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; import org.junit.Assert; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - public class FlowControlTest extends AbstractTest { @Test diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java index 302a2ffbffb..f3fdb626c4d 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java @@ -18,6 +18,9 @@ package org.eclipse.jetty.spdy; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; @@ -46,9 +49,6 @@ import org.eclipse.jetty.util.Fields; import org.junit.Assert; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - public class ProtocolViolationsTest extends AbstractTest { @Test diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java index 01967c3c925..84fbc1de144 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java @@ -19,6 +19,12 @@ package org.eclipse.jetty.spdy; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.sameInstance; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; @@ -63,12 +69,6 @@ import org.eclipse.jetty.util.Fields; import org.junit.Assert; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.sameInstance; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - public class PushStreamTest extends AbstractTest { @Test diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java index 83cbda285bb..51793191b6c 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java @@ -18,6 +18,12 @@ package org.eclipse.jetty.spdy; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -35,12 +41,6 @@ import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; import org.eclipse.jetty.util.Callback; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - public class ResetStreamTest extends AbstractTest { @Test diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java index e324601c561..8bba13d6e67 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java @@ -23,6 +23,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import junit.framework.Assert; + import org.eclipse.jetty.spdy.api.GoAwayInfo; import org.eclipse.jetty.spdy.api.Session; import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java index 02f3d65b0b7..8b6906bebd6 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java @@ -23,6 +23,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import junit.framework.Assert; + import org.eclipse.jetty.spdy.api.GoAwayInfo; import org.eclipse.jetty.spdy.api.Session; import org.eclipse.jetty.spdy.api.SessionFrameListener; @@ -50,7 +51,7 @@ public class SPDYServerConnectorTest extends AbstractTest connector.stop(); Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); - Assert.assertTrue(connector.getSessions().isEmpty()); + Assert.assertTrue(connector.getConnectionFactory(SPDYServerConnectionFactory.class).getSessions().isEmpty()); } @Test @@ -64,6 +65,6 @@ public class SPDYServerConnectorTest extends AbstractTest // since it is done asynchronously by the selector thread TimeUnit.SECONDS.sleep(1); - Assert.assertTrue(connector.getSessions().isEmpty()); + Assert.assertTrue(connector.getConnectionFactory(SPDYServerConnectionFactory.class).getSessions().isEmpty()); } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayUtil.java index 74151ea2bf2..740599d7e8d 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayUtil.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; + /* ------------------------------------------------------------ */ /** */ @@ -73,12 +74,37 @@ public class ArrayUtil } else { - // TODO: Replace with Arrays.copyOf(T[] original, int newLength) from Java 1.6+ + T[] na = Arrays.copyOf(array,array.length+1); + na[array.length]=item; + return na; + } + } + + /* ------------------------------------------------------------ */ + /** Add element to the start of an array + * @param array The array to add to (or null) + * @param item The item to add + * @param type The type of the array (in case of null array) + * @return new array with contents of array plus item + */ + public static T[] prependToArray(T item, T[] array, Class type) + { + if (array==null) + { + if (type==null && item!=null) + type= item.getClass(); + @SuppressWarnings("unchecked") + T[] na = (T[])Array.newInstance(type, 1); + na[0]=item; + return na; + } + else + { Class c = array.getClass().getComponentType(); @SuppressWarnings("unchecked") T[] na = (T[])Array.newInstance(c, Array.getLength(array)+1); - System.arraycopy(array, 0, na, 0, array.length); - na[array.length]=item; + System.arraycopy(array, 0, na, 1, array.length); + na[0]=item; return na; } } @@ -94,6 +120,23 @@ public class ArrayUtil return new ArrayList(); return new ArrayList(Arrays.asList(array)); } + + /* ------------------------------------------------------------ */ + public static T[] removeNulls(T[] array) + { + for (T t : array) + { + if (t==null) + { + List list = new ArrayList<>(); + for (T t2:array) + if (t2!=null) + list.add(t2); + return list.toArray(Arrays.copyOf(array,list.size())); + } + } + return array; + } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ExecutorCallback.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ExecutorCallback.java index c90b7515161..0db02579b96 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/ExecutorCallback.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ExecutorCallback.java @@ -90,6 +90,11 @@ public abstract class ExecutorCallback implements Callback { @Override public void run() { onCompleted(context);} + @Override + public String toString() + { + return String.format("ExectorCB$Completed@%x{%s}",hashCode(),context); + } }); } @@ -110,7 +115,7 @@ public abstract class ExecutorCallback implements Callback @Override public String toString() { - return String.format("%s@%x{%s,%s}",ExecutorCallback.class.getSimpleName(),hashCode(),context,x); + return String.format("ExectorCB$Failed@%x{%s,%s}",hashCode(),context,x); } }; diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java index 5c1bf9d711e..611bf05b9c2 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java @@ -48,16 +48,19 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable private final List _beans = new CopyOnWriteArrayList<>(); private boolean _started = false; + enum Managed { MANAGED, UNMANAGED, AUTO }; + private class Bean { private final Object _bean; - private volatile boolean _managed = true; + private volatile Managed _managed = Managed.AUTO; private Bean(Object b) { _bean = b; } + @Override public String toString() { return String.format("{%s,%b}", _bean, _managed); @@ -70,26 +73,34 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable @Override protected void doStart() throws Exception { + // indicate that we are started, so that addBean will start other beans added. + _started = true; + + // start our managed and auto beans for (Bean b : _beans) { if (b._bean instanceof LifeCycle) { LifeCycle l = (LifeCycle)b._bean; - if (!l.isRunning()) + switch(b._managed) { - if (b._managed) - l.start(); + case MANAGED: + if (!l.isRunning()) + l.start(); + break; + case AUTO: + if (l.isRunning()) + b._managed=Managed.UNMANAGED; + else + { + b._managed=Managed.MANAGED; + l.start(); + } + break; } } - if (b._managed && b._bean instanceof LifeCycle) - { - LifeCycle l = (LifeCycle)b._bean; - if (!l.isRunning()) - l.start(); - } } - // indicate that we are started, so that addBean will start other beans added. - _started = true; + super.doStart(); } @@ -105,7 +116,7 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable Collections.reverse(reverse); for (Bean b : reverse) { - if (b._managed && b._bean instanceof LifeCycle) + if (b._managed==Managed.MANAGED && b._bean instanceof LifeCycle) { LifeCycle l = (LifeCycle)b._bean; if (l.isRunning()) @@ -117,13 +128,14 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable /** * Destroys the managed Destroyable beans in the reverse order they were added. */ + @Override public void destroy() { List reverse = new ArrayList<>(_beans); Collections.reverse(reverse); for (Bean b : reverse) { - if (b._bean instanceof Destroyable && b._managed) + if (b._bean instanceof Destroyable && b._managed==Managed.MANAGED) { Destroyable d = (Destroyable)b._bean; d.destroy(); @@ -154,7 +166,7 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable { for (Bean b : _beans) if (b._bean == bean) - return b._managed; + return b._managed==Managed.MANAGED; return false; } @@ -171,8 +183,12 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable */ public boolean addBean(Object o) { - // beans are joined unless they are started lifecycles - return addBean(o, !((o instanceof LifeCycle) && ((LifeCycle)o).isStarted())); + if (o instanceof LifeCycle) + { + LifeCycle l = (LifeCycle)o; + return addBean(o,l.isRunning()?Managed.UNMANAGED:Managed.AUTO); + } + return addBean(o,Managed.MANAGED); } /** @@ -183,6 +199,11 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable * @return true if the bean was added, false if it was already present */ public boolean addBean(Object o, boolean managed) + { + return addBean(o,managed?Managed.MANAGED:Managed.UNMANAGED); + } + + public boolean addBean(Object o, Managed managed) { if (contains(o)) return false; @@ -191,26 +212,41 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable b._managed = managed; _beans.add(b); - if (o instanceof LifeCycle) + if (_started) { - LifeCycle l = (LifeCycle)o; - - // Start the bean if we are started - if (managed && _started) + try { - try + if (o instanceof LifeCycle) { - l.start(); - } - catch (Exception e) - { - throw new RuntimeException(e); + LifeCycle l = (LifeCycle)o; + + switch(b._managed) + { + case MANAGED: + if (!l.isRunning()) + l.start(); + break; + case AUTO: + if (l.isRunning()) + b._managed=Managed.UNMANAGED; + else + { + b._managed=Managed.MANAGED; + l.start(); + } + break; + } } } + catch (Exception e) + { + throw new RuntimeException(e); + } } return true; } - + + /** * Manages a bean already contained by this aggregate, so that it is started/stopped/destroyed with this * aggregate. @@ -223,7 +259,7 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable { if (b._bean == bean) { - b._managed = true; + b._managed = Managed.MANAGED; return; } } @@ -242,7 +278,7 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable { if (b._bean == bean) { - b._managed = false; + b._managed = Managed.UNMANAGED; return; } } @@ -389,6 +425,7 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable } } + @Override public void dump(Appendable out, String indent) throws IOException { dumpThis(out); @@ -400,18 +437,29 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable { i++; - if (b._managed) + switch(b._managed) { - out.append(indent).append(" +- "); - if (b._bean instanceof Dumpable) - ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | ")); - else + case MANAGED: + out.append(indent).append(" +- "); + if (b._bean instanceof Dumpable) + ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | ")); + else + dumpObject(out, b._bean); + break; + + case UNMANAGED: + out.append(indent).append(" +~ "); dumpObject(out, b._bean); - } - else - { - out.append(indent).append(" +~ "); - dumpObject(out, b._bean); + break; + + case AUTO: + out.append(indent).append(" += "); + if (b._bean instanceof Dumpable) + ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | ")); + else + dumpObject(out, b._bean); + break; + } } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java index 78e47e97893..e912c56393b 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java @@ -70,9 +70,9 @@ public class BufferUtilTest for (int i=0;i