diff --git a/jetty-spdy/pom.xml b/jetty-spdy/pom.xml index e48b9469f44..0be6c639b51 100644 --- a/jetty-spdy/pom.xml +++ b/jetty-spdy/pom.xml @@ -24,13 +24,17 @@ spdy-example-webapp - - - org.eclipse.jetty.toolchain - jetty-test-helper - test - - + + + jdk7-npn + + [1.7,1.8) + + + spdy-npn-tests + + + @@ -71,16 +75,12 @@ - - - jdk7-npn - - [1.7,1.8) - - - spdy-npn-tests - - - + + + org.eclipse.jetty.toolchain + jetty-test-helper + test + + diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnection.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnection.java index fc288894d6a..c8e85f2c0ea 100644 --- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnection.java +++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnection.java @@ -18,87 +18,28 @@ package org.eclipse.jetty.spdy.client; -import java.io.IOException; import java.util.List; import java.util.Map; - +import java.util.concurrent.Executor; import javax.net.ssl.SSLEngine; -import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.ClientConnectionFactory; -import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.npn.NextProtoNego; -import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -public class NPNClientConnection extends AbstractConnection implements NextProtoNego.ClientProvider +public class NPNClientConnection extends NegotiatingClientConnection implements NextProtoNego.ClientProvider { - private final Logger LOG = Log.getLogger(getClass()); - private final SPDYClient client; - private final ClientConnectionFactory connectionFactory; - private final SSLEngine engine; - private final Map context; - private volatile boolean completed; + private static final Logger LOG = Log.getLogger(NPNClientConnection.class); - public NPNClientConnection(EndPoint endPoint, SPDYClient client, ClientConnectionFactory connectionFactory, SSLEngine sslEngine, Map context) - { - super(endPoint, client.getFactory().getExecutor()); - this.client = client; - this.connectionFactory = connectionFactory; - this.engine = sslEngine; - this.context = context; - NextProtoNego.put(engine, this); - } + private final String protocol; - @Override - public void onOpen() + public NPNClientConnection(EndPoint endPoint, Executor executor, ClientConnectionFactory connectionFactory, SSLEngine sslEngine, Map context, String protocol) { - super.onOpen(); - try - { - getEndPoint().flush(BufferUtil.EMPTY_BUFFER); - if (completed) - replaceConnection(); - else - fillInterested(); - } - catch(IOException e) - { - throw new RuntimeIOException(e); - } - } - - @Override - public void onFillable() - { - while (true) - { - int filled = fill(); - if (filled == 0 && !completed) - fillInterested(); - if (filled <= 0 || completed) - break; - } - if (completed) - replaceConnection(); - } - - private int fill() - { - try - { - return getEndPoint().fill(BufferUtil.EMPTY_BUFFER); - } - catch (IOException x) - { - LOG.debug(x); - NextProtoNego.remove(engine); - close(); - return -1; - } + super(endPoint, executor, sslEngine, connectionFactory, context); + this.protocol = protocol; + NextProtoNego.put(sslEngine, this); } @Override @@ -110,31 +51,31 @@ public class NPNClientConnection extends AbstractConnection implements NextProto @Override public void unsupported() { - NextProtoNego.remove(engine); - completed = true; + NextProtoNego.remove(getSSLEngine()); + completed(); } @Override public String selectProtocol(List protocols) { - NextProtoNego.remove(engine); - completed = true; - return client.selectProtocol(protocols); + if (protocols.contains(protocol)) + { + NextProtoNego.remove(getSSLEngine()); + completed(); + return protocol; + } + else + { + LOG.info("Could not negotiate protocol: server {} - client {}", protocols, protocol); + close(); + return null; + } } - private void replaceConnection() + @Override + public void close() { - EndPoint endPoint = getEndPoint(); - try - { - Connection oldConnection = endPoint.getConnection(); - Connection newConnection = connectionFactory.newConnection(endPoint, context); - ClientConnectionFactory.Helper.replaceConnection(oldConnection, newConnection); - } - catch (Throwable x) - { - LOG.debug(x); - close(); - } + NextProtoNego.remove(getSSLEngine()); + super.close(); } } diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnectionFactory.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnectionFactory.java index ec81cab1565..d0458010c9f 100644 --- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnectionFactory.java +++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnectionFactory.java @@ -20,7 +20,7 @@ package org.eclipse.jetty.spdy.client; import java.io.IOException; import java.util.Map; - +import java.util.concurrent.Executor; import javax.net.ssl.SSLEngine; import org.eclipse.jetty.io.ClientConnectionFactory; @@ -28,21 +28,22 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.ssl.SslClientConnectionFactory; -public class NPNClientConnectionFactory implements ClientConnectionFactory +public class NPNClientConnectionFactory extends NegotiatingClientConnectionFactory { - private final SPDYClient client; - private final ClientConnectionFactory connectionFactory; + private final Executor executor; + private final String protocol; - public NPNClientConnectionFactory(SPDYClient client, ClientConnectionFactory connectionFactory) + public NPNClientConnectionFactory(Executor executor, ClientConnectionFactory connectionFactory, String protocol) { - this.client = client; - this.connectionFactory = connectionFactory; + super(connectionFactory); + this.executor = executor; + this.protocol = protocol; } @Override public Connection newConnection(EndPoint endPoint, Map context) throws IOException { - return new NPNClientConnection(endPoint, client, connectionFactory, - (SSLEngine)context.get(SslClientConnectionFactory.SSL_ENGINE_CONTEXT_KEY), context); + return new NPNClientConnection(endPoint, executor, getClientConnectionFactory(), + (SSLEngine)context.get(SslClientConnectionFactory.SSL_ENGINE_CONTEXT_KEY), context, protocol); } } diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnection.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnection.java new file mode 100644 index 00000000000..a2fc8511f4a --- /dev/null +++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnection.java @@ -0,0 +1,133 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 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.client; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.Executor; +import javax.net.ssl.SSLEngine; + +import org.eclipse.jetty.io.AbstractConnection; +import org.eclipse.jetty.io.ClientConnectionFactory; +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.io.RuntimeIOException; +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +public abstract class NegotiatingClientConnection extends AbstractConnection +{ + private static final Logger LOG = Log.getLogger(NegotiatingClientConnection.class); + + private final SSLEngine engine; + private final ClientConnectionFactory connectionFactory; + private final Map context; + private volatile boolean completed; + + protected NegotiatingClientConnection(EndPoint endp, Executor executor, SSLEngine sslEngine, ClientConnectionFactory connectionFactory, Map context) + { + super(endp, executor); + this.engine = sslEngine; + this.connectionFactory = connectionFactory; + this.context = context; + } + + protected SSLEngine getSSLEngine() + { + return engine; + } + + protected void completed() + { + completed = true; + } + + @Override + public void onOpen() + { + super.onOpen(); + try + { + getEndPoint().flush(BufferUtil.EMPTY_BUFFER); + if (completed) + replaceConnection(); + else + fillInterested(); + } + catch (IOException x) + { + close(); + throw new RuntimeIOException(x); + } + } + + @Override + public void onFillable() + { + while (true) + { + int filled = fill(); + if (filled == 0 && !completed) + fillInterested(); + if (filled <= 0 || completed) + break; + } + if (completed) + replaceConnection(); + } + + private int fill() + { + try + { + return getEndPoint().fill(BufferUtil.EMPTY_BUFFER); + } + catch (IOException x) + { + LOG.debug(x); + close(); + return -1; + } + } + + private void replaceConnection() + { + EndPoint endPoint = getEndPoint(); + try + { + Connection oldConnection = endPoint.getConnection(); + Connection newConnection = connectionFactory.newConnection(endPoint, context); + ClientConnectionFactory.Helper.replaceConnection(oldConnection, newConnection); + } + catch (Throwable x) + { + LOG.debug(x); + close(); + } + } + + @Override + public void close() + { + // Gentler close for SSL. + getEndPoint().shutdownOutput(); + super.close(); + } +} diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java new file mode 100644 index 00000000000..50a1e5b2233 --- /dev/null +++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java @@ -0,0 +1,36 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 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.client; + +import org.eclipse.jetty.io.ClientConnectionFactory; + +public abstract class NegotiatingClientConnectionFactory implements ClientConnectionFactory +{ + private final ClientConnectionFactory connectionFactory; + + protected NegotiatingClientConnectionFactory(ClientConnectionFactory connectionFactory) + { + this.connectionFactory = connectionFactory; + } + + public ClientConnectionFactory getClientConnectionFactory() + { + return connectionFactory; + } +} diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java index 678aa2aac60..d30bc99f4ea 100644 --- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java +++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java @@ -26,7 +26,6 @@ import java.nio.channels.SocketChannel; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -86,10 +85,6 @@ public class SPDYClient this.factory = factory; setInitialWindowSize(65536); setDispatchIO(true); - ClientConnectionFactory connectionFactory = new SPDYClientConnectionFactory(); - if (factory.sslContextFactory != null) - connectionFactory = new SslClientConnectionFactory(factory.getSslContextFactory(), factory.getByteBufferPool(), factory.getExecutor(), new NPNClientConnectionFactory(this, connectionFactory)); - setClientConnectionFactory(connectionFactory); } public short getVersion() @@ -239,17 +234,6 @@ public class SPDYClient this.connectionFactory = connectionFactory; } - protected String selectProtocol(List serverProtocols) - { - String protocol = "spdy/" + version; - for (String serverProtocol : serverProtocols) - { - if (serverProtocol.equals(protocol)) - return protocol; - } - return null; - } - protected FlowControlStrategy newFlowControlStrategy() { return FlowControlStrategyFactory.newFlowControlStrategy(version); @@ -357,7 +341,19 @@ public class SPDYClient public SPDYClient newSPDYClient(short version) { - return new SPDYClient(version, this); + return newSPDYClient(version, new NPNClientConnectionFactory(getExecutor(), new SPDYClientConnectionFactory(), "spdy/" + version)); + } + + public SPDYClient newSPDYClient(short version, NegotiatingClientConnectionFactory negotiatingFactory) + { + SPDYClient client = new SPDYClient(version, this); + + ClientConnectionFactory connectionFactory = negotiatingFactory.getClientConnectionFactory(); + if (sslContextFactory != null) + connectionFactory = new SslClientConnectionFactory(getSslContextFactory(), getByteBufferPool(), getExecutor(), negotiatingFactory); + + client.setClientConnectionFactory(connectionFactory); + return client; } @Override diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToHTTPTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToHTTPTest.java index 56ee8184759..700d560150a 100644 --- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToHTTPTest.java +++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToHTTPTest.java @@ -77,16 +77,15 @@ import static org.junit.Assert.assertThat; @RunWith(value = Parameterized.class) public abstract class ProxySPDYToHTTPTest { - @Rule - public final TestTracker tracker = new TestTracker(); - private final short version; - @Parameterized.Parameters public static Collection parameters() { return Arrays.asList(new Short[]{SPDY.V2}, new Short[]{SPDY.V3}); } + @Rule + public final TestTracker tracker = new TestTracker(); + private final short version; private SPDYClient.Factory factory; private Server server; private Server proxy; diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToSPDYLoadTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToSPDYLoadTest.java index 564b32dc9ef..89f0eced800 100644 --- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToSPDYLoadTest.java +++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToSPDYLoadTest.java @@ -67,16 +67,15 @@ import static org.junit.Assert.assertThat; @RunWith(value = Parameterized.class) public abstract class ProxySPDYToSPDYLoadTest { - @Rule - public final TestTracker tracker = new TestTracker(); - private final short version; - @Parameterized.Parameters public static Collection parameters() { return Arrays.asList(new Short[]{SPDY.V2}, new Short[]{SPDY.V3}); } + @Rule + public final TestTracker tracker = new TestTracker(); + private final short version; private static final String UUID_HEADER_NAME = "uuidHeader"; private static final String SERVER_ID_HEADER = "serverId"; private SPDYClient.Factory factory; diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToSPDYTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToSPDYTest.java index 186afbe29ea..04e9551cd55 100644 --- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToSPDYTest.java +++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToSPDYTest.java @@ -68,16 +68,15 @@ import static org.junit.Assert.assertThat; @RunWith(value = Parameterized.class) public abstract class ProxySPDYToSPDYTest { - @Rule - public final TestTracker tracker = new TestTracker(); - private final short version; - @Parameterized.Parameters public static Collection parameters() { return Arrays.asList(new Short[]{SPDY.V2}, new Short[]{SPDY.V3}); } + @Rule + public final TestTracker tracker = new TestTracker(); + private final short version; private SPDYClient.Factory factory; private Server server; private Server proxy; diff --git a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnection.java b/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnection.java index 01652df7c5d..b1fb87eb5ed 100644 --- a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnection.java +++ b/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnection.java @@ -42,7 +42,7 @@ public abstract class NegotiatingServerConnection extends AbstractConnection private final String defaultProtocol; private String protocol; // No need to be volatile: it is modified and read by the same thread - public NegotiatingServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List protocols, String defaultProtocol) + protected NegotiatingServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List protocols, String defaultProtocol) { super(endPoint, connector.getExecutor()); this.connector = connector; diff --git a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlAppendableTest.java b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlAppendableTest.java index 2639b10deac..6a1556e4ddd 100644 --- a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlAppendableTest.java +++ b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlAppendableTest.java @@ -18,7 +18,7 @@ package org.eclipse.jetty.xml; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import org.junit.Assert; @@ -31,24 +31,40 @@ public class XmlAppendableTest { StringBuilder b = new StringBuilder(); XmlAppendable out = new XmlAppendable(b); - Map attr = new HashMap<>(); - + Map attr = new LinkedHashMap<>(); + out.open("test"); - - attr.put("name","attr value"); - attr.put("noval",null); - attr.put("quotes","'\""); - + + attr.put("name", "attr value"); + attr.put("noval", null); + attr.put("quotes", "'\""); + out.tag("tag"); - out.tag("tag",attr); - out.tag("tag",attr,"content"); - - out.open("level1").tag("tag","content").tag("tag","content").close(); - out.open("level1",attr).open("level2").tag("tag","content").tag("tag","content").close().close(); - + out.tag("tag", attr); + out.tag("tag", attr, "content"); + + out.open("level1").tag("tag", "content").tag("tag", "content").close(); + out.open("level1", attr).open("level2").tag("tag", "content").tag("tag", "content").close().close(); + out.close(); - - String s = b.toString(); - Assert.assertEquals("\n\n \n \n content\n \n content\n content\n \n \n \n content\n content\n \n \n\n",s); + + String expected = "" + + "\n" + + "\n" + + " \n" + + " \n" + + " content\n" + + " \n" + + " content\n" + + " content\n" + + " \n" + + " \n" + + " \n" + + " content\n" + + " content\n" + + " \n" + + " \n" + + "\n"; + Assert.assertEquals(expected, b.toString()); } } diff --git a/pom.xml b/pom.xml index fa396835a64..38d61b508c9 100644 --- a/pom.xml +++ b/pom.xml @@ -814,13 +814,13 @@ - osgi - - [1.7,1.8) - - - jetty-osgi - + osgi + + [1.7,1.8) + + + jetty-osgi + 7u9