diff --git a/jetty-rhttp/README.TXT b/jetty-rhttp/README.TXT deleted file mode 100644 index 46ca4e743e4..00000000000 --- a/jetty-rhttp/README.TXT +++ /dev/null @@ -1,33 +0,0 @@ -Reverse HTTP - -The HTTP server paradigm is a valuable abstraction for browsing and accessing data and applications in a RESTful fashion from thin clients or -other applications. However, when it comes to mobile devices, the server paradigm is often not available because those devices exist on -restricted networks that do not allow inbound connections. These devices (eg. phones, tablets, industrial controllers, etc.) often have -signficant content (eg. photos, video, music, contacts, etc.) and services (eg. GPS, phone, modem, camera, sound) that are worthwile to access -remotely and often the HTTP server model is very applicable. - -The Jetty reverse HTTP module provides a gateway that efficiently allows HTTP connectivety to servers running in outbound-only networks. There are two key components: - -The reverse HTTP connector is a jetty connector (like the HTTP, SSL, AJP connectors) that accepts HTTP requests for the Jetty server instance. However, the reverse HTTP connector does not accept inbound TCP/IP connections. Instead it makes an outbound HTTP connection to the reverse HTTP gateway and uses a long polling mechanism to efficiently and asynchronously fetch requests and send responses. - -The reverse HTTP gateway is a jetty server that accepts inbound connections from one or more Reverse HTTP connectors and makes them available as normal HTTP targets. - -To demonstrate this from a source release, first run a gateway instance: - - cd jetty-reverse-http/reverse-http-gateway - mvn exec:java - -In another window, you can run 3 test servers with reverse connectors with: - - cd jetty-reverse-http/reverse-http-connector - mvn exec:java - - -The three servers are using context path ID's at the gateway (virtual host and cookie based mappings can also be done), so you can access the -three servers via the gateway at: - - http://localhost:8080/gw/A - http://localhost:8080/gw/B - http://localhost:8080/gw/C - - diff --git a/jetty-rhttp/jetty-rhttp-client/pom.xml b/jetty-rhttp/jetty-rhttp-client/pom.xml deleted file mode 100644 index 14dc5b31f0a..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/pom.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - org.eclipse.jetty.rhttp - jetty-rhttp-project - 9.0.0-SNAPSHOT - - - 4.0.0 - reverse-http-client - jar - Jetty :: Reverse HTTP :: Client - - - ${project.groupId}.rhttp.client - - - - - - org.apache.felix - maven-bundle-plugin - true - - - - manifest - - - - * - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - - - - - - org.eclipse.jetty - jetty-util - - - org.eclipse.jetty - jetty-io - - - org.eclipse.jetty - jetty-client - ${project.version} - - - org.eclipse.jetty - jetty-http - ${project.version} - - - org.apache.httpcomponents - httpclient - 4.0 - - - net.jcip - jcip-annotations - 1.0 - provided - - - org.eclipse.jetty.toolchain - jetty-test-helper - test - - - org.eclipse.jetty - jetty-server - ${project.version} - test - - - - diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/AbstractClient.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/AbstractClient.java deleted file mode 100644 index cecc330a1dc..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/AbstractClient.java +++ /dev/null @@ -1,270 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.eclipse.jetty.util.component.AbstractLifeCycle; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - * @version $Revision$ $Date$ - */ -public abstract class AbstractClient extends AbstractLifeCycle implements RHTTPClient -{ - private final Logger logger = Log.getLogger("org.mortbay.jetty.rhttp.client"); - private final List listeners = new CopyOnWriteArrayList(); - private final List clientListeners = new CopyOnWriteArrayList(); - private final String targetId; - private volatile Status status = Status.DISCONNECTED; - - public AbstractClient(String targetId) - { - this.targetId = targetId; - } - - public String getGatewayURI() - { - return "http://"+getHost()+":"+getPort()+getPath(); - } - - public String getTargetId() - { - return targetId; - } - - public Logger getLogger() - { - return logger; - } - - public void addListener(RHTTPListener listener) - { - listeners.add(listener); - } - - public void removeListener(RHTTPListener listener) - { - listeners.remove(listener); - } - - public void addClientListener(ClientListener listener) - { - clientListeners.add(listener); - } - - public void removeClientListener(ClientListener listener) - { - clientListeners.remove(listener); - } - - protected void notifyRequests(List requests) - { - for (RHTTPRequest request : requests) - { - for (RHTTPListener listener : listeners) - { - try - { - listener.onRequest(request); - } - catch (Throwable x) - { - logger.warn("Listener " + listener + " threw", x); - try - { - deliver(newExceptionResponse(request.getId(), x)); - } - catch (IOException xx) - { - logger.debug("Could not deliver exception response", xx); - } - } - } - } - } - - protected RHTTPResponse newExceptionResponse(int requestId, Throwable x) - { - try - { - int statusCode = 500; - String statusMessage = "Internal Server Error"; - Map headers = new HashMap(); - byte[] body = x.toString().getBytes("UTF-8"); - return new RHTTPResponse(requestId, statusCode, statusMessage, headers, body); - } - catch (UnsupportedEncodingException xx) - { - throw new AssertionError(xx); - } - } - - protected void notifyConnectRequired() - { - for (ClientListener listener : clientListeners) - { - try - { - listener.connectRequired(); - } - catch (Throwable x) - { - logger.warn("ClientListener " + listener + " threw", x); - } - } - } - - protected void notifyConnectException() - { - for (ClientListener listener : clientListeners) - { - try - { - listener.connectException(); - } - catch (Throwable x) - { - logger.warn("ClientListener " + listener + " threw", x); - } - } - } - - protected void notifyConnectClosed() - { - for (ClientListener listener : clientListeners) - { - try - { - listener.connectClosed(); - } - catch (Throwable xx) - { - logger.warn("ClientListener " + listener + " threw", xx); - } - } - } - - protected void notifyDeliverException(RHTTPResponse response) - { - for (ClientListener listener : clientListeners) - { - try - { - listener.deliverException(response); - } - catch (Throwable x) - { - logger.warn("ClientListener " + listener + " threw", x); - } - } - } - - protected String urlEncode(String value) - { - try - { - return URLEncoder.encode(value, "UTF-8"); - } - catch (UnsupportedEncodingException x) - { - getLogger().debug("", x); - return null; - } - } - - protected boolean isConnected() - { - return status == Status.CONNECTED; - } - - protected boolean isDisconnecting() - { - return status == Status.DISCONNECTING; - } - - protected boolean isDisconnected() - { - return status == Status.DISCONNECTED; - } - - public void connect() throws IOException - { - if (isDisconnected()) - status = Status.CONNECTING; - - syncHandshake(); - this.status = Status.CONNECTED; - - asyncConnect(); - } - - public void disconnect() throws IOException - { - if (isConnected()) - { - status = Status.DISCONNECTING; - try - { - syncDisconnect(); - } - finally - { - status = Status.DISCONNECTED; - } - } - } - - public void deliver(RHTTPResponse response) throws IOException - { - asyncDeliver(response); - } - - protected abstract void syncHandshake() throws IOException; - - protected abstract void asyncConnect(); - - protected abstract void syncDisconnect() throws IOException; - - protected abstract void asyncDeliver(RHTTPResponse response); - - protected void connectComplete(byte[] responseContent) throws IOException - { - List requests = RHTTPRequest.fromFrameBytes(responseContent); - getLogger().debug("Client {} connect returned from gateway, requests {}", getTargetId(), requests); - - // Requests are arrived, reconnect while we process them - if (!isDisconnecting() && !isDisconnected()) - asyncConnect(); - - notifyRequests(requests); - } - - protected enum Status - { - CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/ApacheClient.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/ApacheClient.java deleted file mode 100644 index b21d1cdd1d1..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/ApacheClient.java +++ /dev/null @@ -1,156 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.IOException; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.NoHttpResponseException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.util.EntityUtils; - -/** - * Implementation of {@link RHTTPClient} that uses Apache's HttpClient. - * - * @version $Revision$ $Date$ - */ -public class ApacheClient extends AbstractClient -{ - private final HttpClient httpClient; - private final String gatewayPath; - - public ApacheClient(HttpClient httpClient, String gatewayPath, String targetId) - { - super(targetId); - this.httpClient = httpClient; - this.gatewayPath = gatewayPath; - } - - public String getHost() - { - return ((HttpHost)httpClient.getParams().getParameter("http.default-host")).getHostName(); - } - - public int getPort() - { - return ((HttpHost)httpClient.getParams().getParameter("http.default-host")).getPort(); - } - - public String getPath() - { - return gatewayPath; - } - - protected void syncHandshake() throws IOException - { - HttpPost handshake = new HttpPost(gatewayPath + "/" + urlEncode(getTargetId()) + "/handshake"); - HttpResponse response = httpClient.execute(handshake); - int statusCode = response.getStatusLine().getStatusCode(); - HttpEntity entity = response.getEntity(); - if (entity != null) - entity.consumeContent(); - if (statusCode != HttpStatus.SC_OK) - throw new IOException("Handshake failed"); - getLogger().debug("Client {} handshake returned from gateway", getTargetId(), null); - } - - protected void asyncConnect() - { - new Thread() - { - @Override - public void run() - { - try - { - HttpPost connect = new HttpPost(gatewayPath + "/" + urlEncode(getTargetId()) + "/connect"); - getLogger().debug("Client {} connect sent to gateway", getTargetId(), null); - HttpResponse response = httpClient.execute(connect); - int statusCode = response.getStatusLine().getStatusCode(); - HttpEntity entity = response.getEntity(); - byte[] responseContent = EntityUtils.toByteArray(entity); - if (statusCode == HttpStatus.SC_OK) - connectComplete(responseContent); - else if (statusCode == HttpStatus.SC_UNAUTHORIZED) - notifyConnectRequired(); - else - notifyConnectException(); - } - catch (NoHttpResponseException x) - { - notifyConnectClosed(); - } - catch (IOException x) - { - getLogger().debug("", x); - notifyConnectException(); - } - } - }.start(); - } - - protected void syncDisconnect() throws IOException - { - HttpPost disconnect = new HttpPost(gatewayPath + "/" + urlEncode(getTargetId()) + "/disconnect"); - HttpResponse response = httpClient.execute(disconnect); - int statusCode = response.getStatusLine().getStatusCode(); - HttpEntity entity = response.getEntity(); - if (entity != null) - entity.consumeContent(); - if (statusCode != HttpStatus.SC_OK) - throw new IOException("Disconnect failed"); - getLogger().debug("Client {} disconnect returned from gateway", getTargetId(), null); - } - - protected void asyncDeliver(final RHTTPResponse response) - { - new Thread() - { - @Override - public void run() - { - try - { - HttpPost deliver = new HttpPost(gatewayPath + "/" + urlEncode(getTargetId()) + "/deliver"); - deliver.setEntity(new ByteArrayEntity(response.getFrameBytes())); - getLogger().debug("Client {} deliver sent to gateway, response {}", getTargetId(), response); - HttpResponse httpResponse = httpClient.execute(deliver); - int statusCode = httpResponse.getStatusLine().getStatusCode(); - HttpEntity entity = httpResponse.getEntity(); - if (entity != null) - entity.consumeContent(); - if (statusCode == HttpStatus.SC_UNAUTHORIZED) - notifyConnectRequired(); - else if (statusCode != HttpStatus.SC_OK) - notifyDeliverException(response); - } - catch (IOException x) - { - getLogger().debug("", x); - notifyDeliverException(response); - } - } - }.start(); - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/ClientListener.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/ClientListener.java deleted file mode 100644 index dcb2940250a..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/ClientListener.java +++ /dev/null @@ -1,67 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -/** - * A listener for network-related events happening on the gateway client. - * - * @version $Revision$ $Date$ - */ -public interface ClientListener -{ - /** - * Called when the client detects that the server requested a new connect. - */ - public void connectRequired(); - - /** - * Called when the client detects that the connection has been closed by the server. - */ - public void connectClosed(); - - /** - * Called when the client detects a generic exception while trying to connect to the server. - */ - public void connectException(); - - /** - * Called when the client detects a generic exception while tryint to deliver to the server. - * @param response the Response object that should have been sent to the server - */ - public void deliverException(RHTTPResponse response); - - public static class Adapter implements ClientListener - { - public void connectRequired() - { - } - - public void connectClosed() - { - } - - public void connectException() - { - } - - public void deliverException(RHTTPResponse response) - { - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/JettyClient.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/JettyClient.java deleted file mode 100644 index 637b8fb39d4..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/JettyClient.java +++ /dev/null @@ -1,306 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.IOException; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpExchange; -import org.eclipse.jetty.http.HttpMethods; -import org.eclipse.jetty.http.HttpURI; -import org.eclipse.jetty.io.Buffer; -import org.eclipse.jetty.io.ByteArrayBuffer; -import org.eclipse.jetty.io.EofException; - -/** - * Implementation of {@link RHTTPClient} that uses Jetty's HttpClient. - * - * @version $Revision$ $Date$ - */ -public class JettyClient extends AbstractClient -{ - private final HttpClient httpClient; - private final Address gatewayAddress; - private final String gatewayPath; - - public JettyClient(HttpClient httpClient, Address gatewayAddress, String gatewayPath, String targetId) - { - super(targetId); - this.httpClient = httpClient; - this.gatewayAddress = gatewayAddress; - this.gatewayPath = gatewayPath; - } - - public JettyClient(HttpClient httpClient, String gatewayURI, String targetId) - { - super(targetId); - - HttpURI uri = new HttpURI(gatewayURI); - - this.httpClient = httpClient; - this.gatewayAddress = new Address(uri.getHost(),uri.getPort()); - this.gatewayPath = uri.getPath(); - } - - public String getHost() - { - return gatewayAddress.getHost(); - } - - public int getPort() - { - return gatewayAddress.getPort(); - } - - public String getPath() - { - return gatewayPath; - } - - @Override - protected void doStart() throws Exception - { - httpClient.start(); - super.doStart(); - } - - @Override - protected void doStop() throws Exception - { - super.doStop(); - httpClient.stop(); - } - - protected void syncHandshake() throws IOException - { - HandshakeExchange exchange = new HandshakeExchange(); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(gatewayAddress); - exchange.setURI(gatewayPath + "/" + urlEncode(getTargetId()) + "/handshake"); - httpClient.send(exchange); - getLogger().debug("Client {} handshake sent to gateway", getTargetId(), null); - - try - { - int exchangeStatus = exchange.waitForDone(); - if (exchangeStatus != HttpExchange.STATUS_COMPLETED) - throw new IOException("Handshake failed"); - if (exchange.getResponseStatus() != 200) - throw new IOException("Handshake failed"); - getLogger().debug("Client {} handshake returned from gateway", getTargetId(), null); - } - catch (InterruptedException x) - { - Thread.currentThread().interrupt(); - throw newIOException(x); - } - } - - private IOException newIOException(Throwable x) - { - return (IOException)new IOException().initCause(x); - } - - protected void asyncConnect() - { - try - { - ConnectExchange exchange = new ConnectExchange(); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(gatewayAddress); - exchange.setURI(gatewayPath + "/" + urlEncode(getTargetId()) + "/connect"); - httpClient.send(exchange); - getLogger().debug("Client {} connect sent to gateway", getTargetId(), null); - } - catch (IOException x) - { - getLogger().debug("Could not send exchange", x); - throw new RuntimeException(x); - } - } - - protected void syncDisconnect() throws IOException - { - DisconnectExchange exchange = new DisconnectExchange(); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(gatewayAddress); - exchange.setURI(gatewayPath + "/" + urlEncode(getTargetId()) + "/disconnect"); - httpClient.send(exchange); - getLogger().debug("Client {} disconnect sent to gateway", getTargetId(), null); - try - { - int status = exchange.waitForDone(); - if (status != HttpExchange.STATUS_COMPLETED) - throw new IOException("Disconnect failed"); - if (exchange.getResponseStatus() != 200) - throw new IOException("Disconnect failed"); - getLogger().debug("Client {} disconnect returned from gateway", getTargetId(), null); - } - catch (InterruptedException x) - { - Thread.currentThread().interrupt(); - throw newIOException(x); - } - } - - protected void asyncDeliver(RHTTPResponse response) - { - try - { - DeliverExchange exchange = new DeliverExchange(response); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(gatewayAddress); - exchange.setURI(gatewayPath + "/" + urlEncode(getTargetId()) + "/deliver"); - exchange.setRequestContent(new ByteArrayBuffer(response.getFrameBytes())); - httpClient.send(exchange); - getLogger().debug("Client {} deliver sent to gateway, response {}", getTargetId(), response); - } - catch (IOException x) - { - getLogger().debug("Could not send exchange", x); - throw new RuntimeException(x); - } - } - - protected class HandshakeExchange extends ContentExchange - { - protected HandshakeExchange() - { - super(true); - } - - @Override - protected void onConnectionFailed(Throwable x) - { - getLogger().warn(x.toString()); - getLogger().debug(x); - } - } - - protected class ConnectExchange extends ContentExchange - { - private final ByteArrayOutputStream content = new ByteArrayOutputStream(); - - protected ConnectExchange() - { - super(true); - } - - @Override - protected void onResponseContent(Buffer buffer) throws IOException - { - buffer.writeTo(content); - } - - @Override - protected void onResponseComplete() - { - int responseStatus = getResponseStatus(); - if (responseStatus == 200) - { - try - { - connectComplete(content.toByteArray()); - } - catch (IOException x) - { - onException(x); - } - } - else if (responseStatus == 401) - { - notifyConnectRequired(); - } - else - { - notifyConnectException(); - } - } - - @Override - protected void onException(Throwable x) - { - getLogger().debug(x); - if (x instanceof EofException || x instanceof EOFException) - { - notifyConnectClosed(); - } - else - { - notifyConnectException(); - } - } - - @Override - protected void onConnectionFailed(Throwable x) - { - getLogger().debug(x); - } - } - - protected class DisconnectExchange extends ContentExchange - { - protected DisconnectExchange() - { - super(true); - } - } - - protected class DeliverExchange extends ContentExchange - { - private final RHTTPResponse response; - - protected DeliverExchange(RHTTPResponse response) - { - super(true); - this.response = response; - } - - @Override - protected void onResponseComplete() throws IOException - { - int responseStatus = getResponseStatus(); - if (responseStatus == 401) - { - notifyConnectRequired(); - } - else if (responseStatus != 200) - { - notifyDeliverException(response); - } - } - - @Override - protected void onException(Throwable x) - { - getLogger().debug(x); - notifyDeliverException(response); - } - - @Override - protected void onConnectionFailed(Throwable x) - { - getLogger().debug(x); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPClient.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPClient.java deleted file mode 100644 index 2888beef149..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPClient.java +++ /dev/null @@ -1,133 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.IOException; - -/** - *

RHTTPClient represent a client of the gateway server.

- *

A Client has a server side counterpart with which communicates - * using a comet protocol.
The Client, its server-side - * counterpart and the comet protocol form the Half-Object plus Protocol - * pattern.

- *

A Client must first connect to the gateway server, to let the gateway - * server know its targetId, an identifier that uniquely distinguish this - * Client from other Clients.

- *

Once connected, the gateway server will use a comet procotol to notify the - * Client of server-side events, and the Client can send - * information to the gateway server to notify it of client-side events.

- *

Server-side event are notified to {@link RHTTPListener}s, while relevant - * network events are communicated to {@link ClientListener}s.

- * - * @version $Revision$ $Date$ - */ -public interface RHTTPClient -{ - /** - * @return The gateway uri, typically "http://gatewayhost:gatewayport/gatewaypath". - */ - public String getGatewayURI(); - - /** - * @return The gateway host - */ - public String getHost(); - - /** - * @return The gateway port - */ - public int getPort(); - - /** - * @return The gateway path - */ - public String getPath(); - - /** - * @return the targetId that uniquely identifies this client. - */ - public String getTargetId(); - - /** - *

Connects to the gateway server, establishing the long poll communication - * with the gateway server to be notified of server-side events.

- *

The connect is performed in two steps: - *

    - *
  • first, a connect message is sent to the gateway server; the gateway server - * will notice this is a first connect message and reply immediately with - * an empty response
  • - *
  • second, another connect message is sent to the gateway server which interprets - * it as a long poll request
  • - *
- * The long poll request may return either because one or more server-side events - * happened, or because it expired.

- *

Any connect message after the first is treated as a long poll request.

- * - * @throws IOException if it is not possible to connect to the gateway server - * @see #disconnect() - */ - public void connect() throws IOException; - - /** - *

Disconnects from the gateway server.

- *

Just after the disconnect request is processed by to the gateway server, it will - * return the currently outstanding long poll request.

- *

If this client is not connected, it does nothing

- * - * @throws IOException if it is not possible to contact the gateway server to disconnect - * @see #connect() - */ - public void disconnect() throws IOException; - - /** - *

Sends a response to the gateway server.

- * - * @param response the response to send - * @throws IOException if it is not possible to contact the gateway server - */ - public void deliver(RHTTPResponse response) throws IOException; - - /** - *

Adds the given listener to this client.

- * @param listener the listener to add - * @see #removeListener(RHTTPListener) - */ - public void addListener(RHTTPListener listener); - - /** - *

Removes the given listener from this client.

- * @param listener the listener to remove - * @see #addListener(RHTTPListener) - */ - public void removeListener(RHTTPListener listener); - - /** - *

Adds the given client listener to this client.

- * @param listener the client listener to add - * @see #removeClientListener(ClientListener) - */ - public void addClientListener(ClientListener listener); - - /** - *

Removes the given client listener from this client.

- * @param listener the client listener to remove - * @see #addClientListener(ClientListener) - */ - public void removeClientListener(ClientListener listener); -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPListener.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPListener.java deleted file mode 100644 index 5c4aa84fd06..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPListener.java +++ /dev/null @@ -1,36 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -/** - *

Implementations of this class listen for requests arriving from the gateway server - * and notified by {@link RHTTPClient}.

- * - * @version $Revision$ $Date$ - */ -public interface RHTTPListener -{ - /** - * Callback method called by {@link RHTTPClient} to inform that the gateway server - * sent a request to the gateway client. - * @param request the request sent by the gateway server. - * @throws Exception allowed to be thrown by implementations - */ - public void onRequest(RHTTPRequest request) throws Exception; -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPRequest.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPRequest.java deleted file mode 100644 index c77f06a2cb4..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPRequest.java +++ /dev/null @@ -1,266 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.eclipse.jetty.http.HttpParser; -import org.eclipse.jetty.io.Buffer; -import org.eclipse.jetty.io.ByteArrayBuffer; - -/** - *

Represents the external request information that is carried over the comet protocol.

- *

Instances of this class are converted into an opaque byte array of the form:

- *
- * <request-id> SPACE <request-length> CRLF
- * <external-request>
- * 
- *

The byte array form is carried as body of a normal HTTP response returned by the gateway server - * to the gateway client.

- * @see RHTTPResponse - * @version $Revision$ $Date$ - */ -public class RHTTPRequest -{ - private static final String CRLF = "\r\n"; - private static final byte[] CRLF_BYTES = CRLF.getBytes(); - - private final int id; - private final byte[] requestBytes; - private final byte[] frameBytes; - private volatile String method; - private volatile String uri; - private volatile Map headers; - private volatile byte[] body; - - public static List fromFrameBytes(byte[] bytes) - { - List result = new ArrayList(); - int start = 0; - while (start < bytes.length) - { - // Scan until we find the space - int end = start; - while (bytes[end] != ' ') ++end; - int requestId = Integer.parseInt(new String(bytes, start, end - start)); - start = end + 1; - - // Scan until end of line - while (bytes[end] != '\n') ++end; - int length = Integer.parseInt(new String(bytes, start, end - start - 1)); - start = end + 1; - - byte[] requestBytes = new byte[length]; - System.arraycopy(bytes, start, requestBytes, 0, length); - RHTTPRequest request = fromRequestBytes(requestId, requestBytes); - result.add(request); - start += length; - } - return result; - } - - public static RHTTPRequest fromRequestBytes(int requestId, byte[] requestBytes) - { - return new RHTTPRequest(requestId, requestBytes); - } - - public RHTTPRequest(int id, String method, String uri, Map headers, byte[] body) - { - this.id = id; - this.method = method; - this.uri = uri; - this.headers = headers; - this.body = body; - this.requestBytes = toRequestBytes(); - this.frameBytes = toFrameBytes(requestBytes); - } - - private RHTTPRequest(int id, byte[] requestBytes) - { - this.id = id; - this.requestBytes = requestBytes; - this.frameBytes = toFrameBytes(requestBytes); - // Other fields are lazily initialized - } - - private void initialize() - { - try - { - final ByteArrayOutputStream body = new ByteArrayOutputStream(); - HttpParser parser = new HttpParser(new ByteArrayBuffer(requestBytes), new HttpParser.EventHandler() - { - @Override - public void startRequest(Buffer method, Buffer uri, Buffer httpVersion) throws IOException - { - RHTTPRequest.this.method = method.toString("UTF-8"); - RHTTPRequest.this.uri = uri.toString("UTF-8"); - RHTTPRequest.this.headers = new LinkedHashMap(); - } - - @Override - public void startResponse(Buffer httpVersion, int statusCode, Buffer statusMessage) throws IOException - { - } - - @Override - public void parsedHeader(Buffer name, Buffer value) throws IOException - { - RHTTPRequest.this.headers.put(name.toString("UTF-8"), value.toString("UTF-8")); - } - - @Override - public void content(Buffer content) throws IOException - { - content.writeTo(body); - } - }); - parser.parse(); - this.body = body.toByteArray(); - } - catch (IOException x) - { - // Cannot happen: we're parsing from a byte[], not from an I/O stream - throw new AssertionError(x); - } - } - - public int getId() - { - return id; - } - - public byte[] getRequestBytes() - { - return requestBytes; - } - - public byte[] getFrameBytes() - { - return frameBytes; - } - - public String getMethod() - { - if (method == null) - initialize(); - return method; - } - - public String getURI() - { - if (uri == null) - initialize(); - return uri; - } - - public Map getHeaders() - { - if (headers == null) - initialize(); - return headers; - } - - public byte[] getBody() - { - if (body == null) - initialize(); - return body; - } - - private byte[] toRequestBytes() - { - try - { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(method.getBytes("UTF-8")); - bytes.write(' '); - bytes.write(uri.getBytes("UTF-8")); - bytes.write(' '); - bytes.write("HTTP/1.1".getBytes("UTF-8")); - bytes.write(CRLF_BYTES); - for (Map.Entry entry : headers.entrySet()) - { - bytes.write(entry.getKey().getBytes("UTF-8")); - bytes.write(':'); - bytes.write(' '); - bytes.write(entry.getValue().getBytes("UTF-8")); - bytes.write(CRLF_BYTES); - } - bytes.write(CRLF_BYTES); - bytes.write(body); - bytes.close(); - return bytes.toByteArray(); - } - catch (IOException x) - { - throw new AssertionError(x); - } - } - - private byte[] toFrameBytes(byte[] requestBytes) - { - try - { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(String.valueOf(id).getBytes("UTF-8")); - bytes.write(' '); - bytes.write(String.valueOf(requestBytes.length).getBytes("UTF-8")); - bytes.write(CRLF_BYTES); - bytes.write(requestBytes); - bytes.close(); - return bytes.toByteArray(); - } - catch (IOException x) - { - throw new AssertionError(x); - } - } - - @Override - public String toString() - { - // Use fields to avoid initialization - StringBuilder builder = new StringBuilder(); - builder.append(id).append(" "); - builder.append(method).append(" "); - builder.append(uri).append(" "); - builder.append(requestBytes.length).append("/"); - builder.append(frameBytes.length); - return builder.toString(); - } - - public String toLongString() - { - // Use getters to trigger initialization - StringBuilder builder = new StringBuilder(); - builder.append(id).append(" "); - builder.append(getMethod()).append(" "); - builder.append(getURI()).append(CRLF); - for (Map.Entry header : getHeaders().entrySet()) - builder.append(header.getKey()).append(": ").append(header.getValue()).append(CRLF); - builder.append(getBody().length).append(" body bytes").append(CRLF); - return builder.toString(); - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPResponse.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPResponse.java deleted file mode 100644 index f9dd30eb318..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RHTTPResponse.java +++ /dev/null @@ -1,256 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.eclipse.jetty.http.HttpParser; -import org.eclipse.jetty.io.Buffer; -import org.eclipse.jetty.io.ByteArrayBuffer; - -/** - *

Represents the resource provider response information that is carried over the comet protocol.

- *

Instances of this class are converted into an opaque byte array of the form:

- *
- * <request-id> SPACE <response-length> CRLF
- * <resource-response>
- * 
- *

The byte array form is carried as body of a normal HTTP request made by the gateway client to - * the gateway server.

- * @see RHTTPRequest - * @version $Revision$ $Date$ - */ -public class RHTTPResponse -{ - private static final String CRLF = "\r\n"; - private static final byte[] CRLF_BYTES = CRLF.getBytes(); - - private final int id; - private final byte[] responseBytes; - private final byte[] frameBytes; - private volatile int code; - private volatile String message; - private volatile Map headers; - private volatile byte[] body; - - public static RHTTPResponse fromFrameBytes(byte[] bytes) - { - int start = 0; - // Scan until we find the space - int end = start; - while (bytes[end] != ' ') ++end; - int responseId = Integer.parseInt(new String(bytes, start, end - start)); - start = end + 1; - - // Scan until end of line - while (bytes[end] != '\n') ++end; - int length = Integer.parseInt(new String(bytes, start, end - start - 1)); - start = end + 1; - - byte[] responseBytes = new byte[length]; - System.arraycopy(bytes, start, responseBytes, 0, length); - return fromResponseBytes(responseId, responseBytes); - } - - public static RHTTPResponse fromResponseBytes(int id, byte[] responseBytes) - { - return new RHTTPResponse(id, responseBytes); - } - - public RHTTPResponse(int id, int code, String message, Map headers, byte[] body) - { - this.id = id; - this.code = code; - this.message = message; - this.headers = headers; - this.body = body; - this.responseBytes = toResponseBytes(); - this.frameBytes = toFrameBytes(responseBytes); - } - - private RHTTPResponse(int id, byte[] responseBytes) - { - this.id = id; - this.responseBytes = responseBytes; - this.frameBytes = toFrameBytes(responseBytes); - // Other fields are lazily initialized - } - - private void initialize() - { - try - { - final ByteArrayOutputStream body = new ByteArrayOutputStream(); - HttpParser parser = new HttpParser(new ByteArrayBuffer(responseBytes), new HttpParser.EventHandler() - { - @Override - public void startRequest(Buffer method, Buffer uri, Buffer httpVersion) throws IOException - { - } - - @Override - public void startResponse(Buffer httpVersion, int statusCode, Buffer statusMessage) throws IOException - { - RHTTPResponse.this.code = statusCode; - RHTTPResponse.this.message = statusMessage.toString("UTF-8"); - RHTTPResponse.this.headers = new LinkedHashMap(); - } - - @Override - public void parsedHeader(Buffer name, Buffer value) throws IOException - { - RHTTPResponse.this.headers.put(name.toString("UTF-8"), value.toString("UTF-8")); - } - - @Override - public void content(Buffer content) throws IOException - { - content.writeTo(body); - } - }); - parser.parse(); - this.body = body.toByteArray(); - } - catch (IOException x) - { - // Cannot happen: we're parsing from a byte[], not from an I/O stream - throw new AssertionError(x); - } - } - - public int getId() - { - return id; - } - - public byte[] getResponseBytes() - { - return responseBytes; - } - - public byte[] getFrameBytes() - { - return frameBytes; - } - - public int getStatusCode() - { - if (code == 0) - initialize(); - return code; - } - - public String getStatusMessage() - { - if (message == null) - initialize(); - return message; - } - - public Map getHeaders() - { - if (headers == null) - initialize(); - return headers; - } - - public byte[] getBody() - { - if (body == null) - initialize(); - return body; - } - - private byte[] toResponseBytes() - { - try - { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write("HTTP/1.1".getBytes("UTF-8")); - bytes.write(' '); - bytes.write(String.valueOf(code).getBytes("UTF-8")); - bytes.write(' '); - bytes.write(message.getBytes("UTF-8")); - bytes.write(CRLF_BYTES); - for (Map.Entry entry : headers.entrySet()) - { - bytes.write(entry.getKey().getBytes("UTF-8")); - bytes.write(':'); - bytes.write(' '); - bytes.write(entry.getValue().getBytes("UTF-8")); - bytes.write(CRLF_BYTES); - } - bytes.write(CRLF_BYTES); - bytes.write(body); - bytes.close(); - return bytes.toByteArray(); - } - catch (IOException x) - { - throw new AssertionError(x); - } - } - - private byte[] toFrameBytes(byte[] responseBytes) - { - try - { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(String.valueOf(id).getBytes("UTF-8")); - bytes.write(' '); - bytes.write(String.valueOf(responseBytes.length).getBytes("UTF-8")); - bytes.write(CRLF_BYTES); - bytes.write(responseBytes); - return bytes.toByteArray(); - } - catch (IOException x) - { - throw new AssertionError(x); - } - } - - @Override - public String toString() - { - // Use fields to avoid initialization - StringBuilder builder = new StringBuilder(); - builder.append(id).append(" "); - builder.append(code).append(" "); - builder.append(message).append(" "); - builder.append(responseBytes.length).append("/"); - builder.append(frameBytes.length); - return builder.toString(); - } - - public String toLongString() - { - // Use getters to trigger initialization - StringBuilder builder = new StringBuilder(); - builder.append(id).append(" "); - builder.append(getStatusCode()).append(" "); - builder.append(getStatusMessage()).append(CRLF); - for (Map.Entry header : getHeaders().entrySet()) - builder.append(header.getKey()).append(": ").append(header.getValue()).append(CRLF); - builder.append(getBody().length).append(" body bytes").append(CRLF); - return builder.toString(); - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RetryingApacheClient.java b/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RetryingApacheClient.java deleted file mode 100644 index 45f8d8ee293..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/main/java/org/eclipse/jetty/rhttp/client/RetryingApacheClient.java +++ /dev/null @@ -1,112 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.IOException; - -import org.apache.http.client.HttpClient; - -/** - * @version $Revision$ $Date$ - */ -public class RetryingApacheClient extends ApacheClient -{ - public RetryingApacheClient(HttpClient httpClient, String gatewayURI, String targetId) - { - super(httpClient, gatewayURI, targetId); - addClientListener(new RetryClientListener()); - } - - @Override - protected void syncHandshake() throws IOException - { - while (true) - { - try - { - super.syncHandshake(); - break; - } - catch (IOException x) - { - getLogger().debug("Handshake failed, backing off and retrying"); - try - { - Thread.sleep(1000); - } - catch (InterruptedException xx) - { - throw (IOException)new IOException().initCause(xx); - } - } - } - } - - private class RetryClientListener implements ClientListener - { - public void connectRequired() - { - getLogger().debug("Connect requested by server"); - try - { - connect(); - } - catch (IOException x) - { - // The connect() method is retried, so if it fails, it's a hard failure - getLogger().debug("Connect failed after server required connect, giving up"); - } - } - - public void connectClosed() - { - connectException(); - } - - public void connectException() - { - getLogger().debug("Connect failed, backing off and retrying"); - try - { - Thread.sleep(1000); - asyncConnect(); - } - catch (InterruptedException x) - { - // Ignore and stop retrying - Thread.currentThread().interrupt(); - } - } - - public void deliverException(RHTTPResponse response) - { - getLogger().debug("Deliver failed, backing off and retrying"); - try - { - Thread.sleep(1000); - asyncDeliver(response); - } - catch (InterruptedException x) - { - // Ignore and stop retrying - Thread.currentThread().interrupt(); - } - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ApacheClientTest.java b/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ApacheClientTest.java deleted file mode 100644 index dc4a1c4a718..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ApacheClientTest.java +++ /dev/null @@ -1,75 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.IOException; - -import org.apache.http.HttpHost; -import org.apache.http.client.HttpRequestRetryHandler; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.conn.scheme.PlainSocketFactory; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.scheme.SchemeRegistry; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpParams; -import org.apache.http.protocol.HttpContext; -import org.eclipse.jetty.rhttp.client.ApacheClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.StdErrLog; - - -/** - * @version $Revision$ $Date$ - */ -public class ApacheClientTest extends ClientTest -{ - { - ((StdErrLog)Log.getLog()).setHideStacks(!Log.getLog().isDebugEnabled()); - } - - private ClientConnectionManager connectionManager; - - protected RHTTPClient createClient(int port, String targetId) throws Exception - { - SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), port)); - connectionManager = new ThreadSafeClientConnManager(new BasicHttpParams(), schemeRegistry); - HttpParams httpParams = new BasicHttpParams(); - httpParams.setParameter("http.default-host", new HttpHost("localhost", port)); - DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager, httpParams); - httpClient.setHttpRequestRetryHandler(new NoRetryHandler()); - return new ApacheClient(httpClient, "", targetId); - } - - protected void destroyClient(RHTTPClient client) throws Exception - { - connectionManager.shutdown(); - } - - private class NoRetryHandler implements HttpRequestRetryHandler - { - public boolean retryRequest(IOException x, int failedAttempts, HttpContext httpContext) - { - return false; - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ClientTest.java b/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ClientTest.java deleted file mode 100644 index 5412ac72249..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ClientTest.java +++ /dev/null @@ -1,299 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import junit.framework.TestCase; - -import org.eclipse.jetty.rhttp.client.ClientListener; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.bio.SocketConnector; -import org.eclipse.jetty.server.handler.AbstractHandler; -import org.eclipse.jetty.server.nio.SelectChannelConnector; -import org.eclipse.jetty.util.log.Log; - - -/** - * @version $Revision$ $Date$ - */ -public abstract class ClientTest extends TestCase -{ - protected abstract RHTTPClient createClient(int port, String targetId) throws Exception; - - protected abstract void destroyClient(RHTTPClient client) throws Exception; - - public void testConnectNoServer() throws Exception - { - RHTTPClient client = createClient(8080, "test1"); - try - { - client.connect(); - fail(); - } - catch (IOException x) - { - } - finally - { - destroyClient(client); - } - } - - public void testServerExceptionOnHandshake() throws Exception - { - final CountDownLatch serverLatch = new CountDownLatch(1); - - Server server = new Server(); - Connector connector = new SelectChannelConnector(); - server.addConnector(connector); - server.setHandler(new AbstractHandler() - { - public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException - { - request.setHandled(true); - if (target.endsWith("/handshake")) - { - serverLatch.countDown(); - throw new TestException(); - } - } - }); - server.start(); - try - { - RHTTPClient client = createClient(connector.getLocalPort(), "test2"); - try - { - try - { - client.connect(); - fail(); - } - catch (IOException x) - { - } - - assertTrue(serverLatch.await(1000, TimeUnit.MILLISECONDS)); - } - finally - { - destroyClient(client); - } - } - finally - { - server.stop(); - } - } - - public void testServerExceptionOnConnect() throws Exception - { - final CountDownLatch serverLatch = new CountDownLatch(1); - - Server server = new Server(); - Connector connector = new SelectChannelConnector(); - server.addConnector(connector); - server.setHandler(new AbstractHandler() - { - public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException - { - request.setHandled(true); - if (target.endsWith("/connect")) - { - serverLatch.countDown(); - throw new TestException(); - } - } - }); - server.start(); - try - { - RHTTPClient client = createClient(connector.getLocalPort(), "test3"); - try - { - final CountDownLatch connectLatch = new CountDownLatch(1); - client.addClientListener(new ClientListener.Adapter() - { - @Override - public void connectException() - { - connectLatch.countDown(); - } - }); - client.connect(); - - assertTrue(serverLatch.await(1000, TimeUnit.MILLISECONDS)); - assertTrue(connectLatch.await(1000, TimeUnit.MILLISECONDS)); - } - finally - { - destroyClient(client); - } - } - finally - { - server.stop(); - } - } - - public void testServerExceptionOnDeliver() throws Exception - { - final CountDownLatch serverLatch = new CountDownLatch(1); - - Server server = new Server(); - Connector connector = new SelectChannelConnector(); - server.addConnector(connector); - server.setHandler(new AbstractHandler() - { - public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException - { - request.setHandled(true); - if (target.endsWith("/connect")) - { - serverLatch.countDown(); - try - { - // Simulate a long poll timeout - Thread.sleep(10000); - } - catch (InterruptedException x) - { - Thread.currentThread().interrupt(); - } - } - else if (target.endsWith("/deliver")) - { - // Throw an exception on deliver - throw new TestException(); - } - } - }); - server.start(); - try - { - RHTTPClient client = createClient(connector.getLocalPort(), "test4"); - try - { - final CountDownLatch deliverLatch = new CountDownLatch(1); - client.addClientListener(new ClientListener.Adapter() - { - @Override - public void deliverException(RHTTPResponse response) - { - deliverLatch.countDown(); - } - }); - client.connect(); - - assertTrue(serverLatch.await(1000, TimeUnit.MILLISECONDS)); - - client.deliver(new RHTTPResponse(1, 200, "OK", new LinkedHashMap(), new byte[0])); - - assertTrue(deliverLatch.await(1000, TimeUnit.MILLISECONDS)); - } - finally - { - destroyClient(client); - } - } - finally - { - server.stop(); - } - } - - public void testServerShutdownAfterConnect() throws Exception - { - final CountDownLatch connectLatch = new CountDownLatch(1); - final CountDownLatch stopLatch = new CountDownLatch(1); - - Server server = new Server(); - Connector connector = new SocketConnector(); - server.addConnector(connector); - server.setHandler(new AbstractHandler() - { - public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException - { - request.setHandled(true); - if (target.endsWith("/connect")) - { - connectLatch.countDown(); - try - { - Thread.sleep(10000); - } - catch (InterruptedException e) - { - stopLatch.countDown(); - } - } - } - }); - server.start(); - try - { - RHTTPClient client = createClient(connector.getLocalPort(), "test5"); - try - { - final CountDownLatch serverLatch = new CountDownLatch(1); - client.addClientListener(new ClientListener.Adapter() - { - @Override - public void connectClosed() - { - serverLatch.countDown(); - } - }); - client.connect(); - - assertTrue(connectLatch.await(2000, TimeUnit.MILLISECONDS)); - - server.stop(); - assertTrue(stopLatch.await(2000, TimeUnit.MILLISECONDS)); - - assertTrue(serverLatch.await(2000, TimeUnit.MILLISECONDS)); - } - finally - { - destroyClient(client); - } - } - finally - { - server.stop(); - } - } - - public static class TestException extends NullPointerException - { - - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/JettyClientTest.java b/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/JettyClientTest.java deleted file mode 100644 index 761f0005e91..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/JettyClientTest.java +++ /dev/null @@ -1,52 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.StdErrLog; - - -/** - * @version $Revision$ $Date$ - */ -public class JettyClientTest extends ClientTest -{ - { - ((StdErrLog)Log.getLog()).setHideStacks(!Log.getLog().isDebugEnabled()); - } - - private HttpClient httpClient; - - protected RHTTPClient createClient(int port, String targetId) throws Exception - { - ((StdErrLog)Log.getLog()).setSource(true); - httpClient = new HttpClient(); - httpClient.start(); - return new JettyClient(httpClient, new Address("localhost", port), "", targetId); - } - - protected void destroyClient(RHTTPClient client) throws Exception - { - httpClient.stop(); - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/RequestTest.java b/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/RequestTest.java deleted file mode 100644 index 8fbf7359533..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/RequestTest.java +++ /dev/null @@ -1,85 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.eclipse.jetty.rhttp.client.RHTTPRequest; - -import junit.framework.TestCase; - -/** - * @version $Revision$ $Date$ - */ -public class RequestTest extends TestCase -{ - public void testRequestConversions() throws Exception - { - int id = 1; - String method = "GET"; - String uri = "/test"; - Map headers = new LinkedHashMap(); - headers.put("X", "X"); - headers.put("Y", "Y"); - headers.put("Z", "Z"); - byte[] body = "BODY".getBytes("UTF-8"); - headers.put("Content-Length", String.valueOf(body.length)); - RHTTPRequest request1 = new RHTTPRequest(id, method, uri, headers, body); - byte[] requestBytes1 = request1.getRequestBytes(); - RHTTPRequest request2 = RHTTPRequest.fromRequestBytes(id, requestBytes1); - assertEquals(id, request2.getId()); - assertEquals(method, request2.getMethod()); - assertEquals(uri, request2.getURI()); - assertEquals(headers, request2.getHeaders()); - assertTrue(Arrays.equals(request2.getBody(), body)); - - byte[] requestBytes2 = request2.getRequestBytes(); - assertTrue(Arrays.equals(requestBytes1, requestBytes2)); - } - - public void testFrameConversions() throws Exception - { - int id = 1; - String method = "GET"; - String uri = "/test"; - Map headers = new LinkedHashMap(); - headers.put("X", "X"); - headers.put("Y", "Y"); - headers.put("Z", "Z"); - byte[] body = "BODY".getBytes("UTF-8"); - headers.put("Content-Length", String.valueOf(body.length)); - RHTTPRequest request1 = new RHTTPRequest(id, method, uri, headers, body); - byte[] frameBytes1 = request1.getFrameBytes(); - List requests = RHTTPRequest.fromFrameBytes(frameBytes1); - assertNotNull(requests); - assertEquals(1, requests.size()); - RHTTPRequest request2 = requests.get(0); - assertEquals(id, request2.getId()); - assertEquals(method, request2.getMethod()); - assertEquals(uri, request2.getURI()); - assertEquals(headers, request2.getHeaders()); - assertTrue(Arrays.equals(request2.getBody(), body)); - - byte[] frameBytes2 = request2.getFrameBytes(); - assertTrue(Arrays.equals(frameBytes1, frameBytes2)); - } -} diff --git a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ResponseTest.java b/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ResponseTest.java deleted file mode 100644 index c2e90f90996..00000000000 --- a/jetty-rhttp/jetty-rhttp-client/src/test/java/org/eclipse/jetty/rhttp/client/ResponseTest.java +++ /dev/null @@ -1,85 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.client; - -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.StdErrLog; - -import junit.framework.TestCase; - -/** - * @version $Revision$ $Date$ - */ -public class ResponseTest extends TestCase -{ - { - ((StdErrLog)Log.getLog()).setHideStacks(!Log.getLog().isDebugEnabled()); - } - - public void testResponseConversions() throws Exception - { - int id = 1; - int statusCode = 200; - String statusMessage = "OK"; - Map headers = new LinkedHashMap(); - headers.put("X", "X"); - headers.put("Y", "Y"); - headers.put("Z", "Z"); - byte[] body = "BODY".getBytes("UTF-8"); - RHTTPResponse response1 = new RHTTPResponse(id, statusCode, statusMessage, headers, body); - byte[] responseBytes1 = response1.getResponseBytes(); - RHTTPResponse response2 = RHTTPResponse.fromResponseBytes(id, responseBytes1); - assertEquals(id, response2.getId()); - assertEquals(statusCode, response2.getStatusCode()); - assertEquals(statusMessage, response2.getStatusMessage()); - assertEquals(headers, response2.getHeaders()); - assertTrue(Arrays.equals(response2.getBody(), body)); - - byte[] responseBytes2 = response2.getResponseBytes(); - assertTrue(Arrays.equals(responseBytes1, responseBytes2)); - } - - public void testFrameConversions() throws Exception - { - int id = 1; - int statusCode = 200; - String statusMessage = "OK"; - Map headers = new LinkedHashMap(); - headers.put("X", "X"); - headers.put("Y", "Y"); - headers.put("Z", "Z"); - byte[] body = "BODY".getBytes("UTF-8"); - RHTTPResponse response1 = new RHTTPResponse(id, statusCode, statusMessage, headers, body); - byte[] frameBytes1 = response1.getFrameBytes(); - RHTTPResponse response2 = RHTTPResponse.fromFrameBytes(frameBytes1); - assertEquals(id, response2.getId()); - assertEquals(statusCode, response2.getStatusCode()); - assertEquals(response2.getStatusMessage(), statusMessage); - assertEquals(headers, response2.getHeaders()); - assertTrue(Arrays.equals(response2.getBody(), body)); - - byte[] frameBytes2 = response2.getFrameBytes(); - assertTrue(Arrays.equals(frameBytes1, frameBytes2)); - } -} diff --git a/jetty-rhttp/jetty-rhttp-connector/pom.xml b/jetty-rhttp/jetty-rhttp-connector/pom.xml deleted file mode 100644 index b248c482105..00000000000 --- a/jetty-rhttp/jetty-rhttp-connector/pom.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - org.eclipse.jetty.rhttp - jetty-rhttp-project - 9.0.0-SNAPSHOT - - - 4.0.0 - reverse-http-connector - jar - Jetty :: Reverse HTTP :: Connector - - - ${project.groupId}.rhttp.connector - - - - - - org.codehaus.mojo - exec-maven-plugin - - test - org.eclipse.jetty.rhttp.connector.TestReverseServer - - - - org.apache.felix - maven-bundle-plugin - true - - - - manifest - - - - * - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - - - - - - org.eclipse.jetty - reverse-http-client - ${project.version} - - - org.eclipse.jetty - jetty-util - - - org.eclipse.jetty - jetty-io - - - org.eclipse.jetty - jetty-server - - - org.eclipse.jetty - example-jetty-embedded - ${project.version} - test - - - org.eclipse.jetty.toolchain - jetty-test-helper - test - - - javax.servlet - javax.servlet-api - test - - - - diff --git a/jetty-rhttp/jetty-rhttp-connector/src/main/config/etc/jetty-rhttp.xml b/jetty-rhttp/jetty-rhttp-connector/src/main/config/etc/jetty-rhttp.xml deleted file mode 100644 index 7d7a9b491e0..00000000000 --- a/jetty-rhttp/jetty-rhttp-connector/src/main/config/etc/jetty-rhttp.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - http://localhost:8888/ - nodeA - - - - - diff --git a/jetty-rhttp/jetty-rhttp-connector/src/main/java/org/eclipse/jetty/rhttp/connector/ReverseHTTPConnector.java b/jetty-rhttp/jetty-rhttp-connector/src/main/java/org/eclipse/jetty/rhttp/connector/ReverseHTTPConnector.java deleted file mode 100644 index 895ba43b21a..00000000000 --- a/jetty-rhttp/jetty-rhttp-connector/src/main/java/org/eclipse/jetty/rhttp/connector/ReverseHTTPConnector.java +++ /dev/null @@ -1,170 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.connector; - -import java.io.IOException; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import org.eclipse.jetty.io.ByteArrayEndPoint; -import org.eclipse.jetty.io.Connection; -import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPListener; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.server.AbstractConnector; -import org.eclipse.jetty.server.AbstractHttpConnection; -import org.eclipse.jetty.server.BlockingHttpConnection; -import org.eclipse.jetty.util.component.LifeCycle; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - * An implementation of a Jetty connector that uses a {@link RHTTPClient} connected - * to a gateway server to receive requests, feed them to the Jetty server, and - * forward responses from the Jetty server to the gateway server. - * - * @version $Revision$ $Date$ - */ -public class ReverseHTTPConnector extends AbstractConnector implements RHTTPListener -{ - private static final Logger LOG = Log.getLogger(ReverseHTTPConnector.class); - - private final BlockingQueue requests = new LinkedBlockingQueue(); - private final RHTTPClient client; - - public ReverseHTTPConnector(RHTTPClient client) - { - this.client = client; - super.setHost(client.getHost()); - super.setPort(client.getPort()); - } - - @Override - public void setHost(String host) - { - throw new UnsupportedOperationException(); - } - - @Override - public void setPort(int port) - { - throw new UnsupportedOperationException(); - } - - @Override - protected void doStart() throws Exception - { - if (client instanceof LifeCycle) - ((LifeCycle)client).start(); - super.doStart(); - client.connect(); - } - - @Override - protected void doStop() throws Exception - { - client.disconnect(); - super.doStop(); - if (client instanceof LifeCycle) - ((LifeCycle)client).stop(); - } - - public void open() - { - client.addListener(this); - } - - public void close() - { - client.removeListener(this); - } - - public int getLocalPort() - { - return -1; - } - - public Object getConnection() - { - return this; - } - - @Override - protected void accept(int acceptorId) throws IOException, InterruptedException - { - RHTTPRequest request = requests.take(); - IncomingRequest incomingRequest = new IncomingRequest(request); - getThreadPool().dispatch(incomingRequest); - } - - @Override - public void persist(EndPoint endpoint) throws IOException - { - // Signals that the connection should not be closed - // Do nothing in this case, as we run from memory - } - - public void onRequest(RHTTPRequest request) throws Exception - { - requests.add(request); - } - - private class IncomingRequest implements Runnable - { - private final RHTTPRequest request; - - private IncomingRequest(RHTTPRequest request) - { - this.request = request; - } - - public void run() - { - byte[] requestBytes = request.getRequestBytes(); - - ByteArrayEndPoint endPoint = new ByteArrayEndPoint(requestBytes, 1024); - endPoint.setGrowOutput(true); - - AbstractHttpConnection connection = new BlockingHttpConnection(ReverseHTTPConnector.this, endPoint, getServer()); - - connectionOpened(connection); - try - { - // Loop over the whole content, since handle() only - // reads up to the connection buffer's capacities - while (endPoint.getIn().length() > 0) - connection.handle(); - - byte[] responseBytes = endPoint.getOut().asArray(); - RHTTPResponse response = RHTTPResponse.fromResponseBytes(request.getId(), responseBytes); - client.deliver(response); - } - catch (Exception x) - { - LOG.debug(x); - } - finally - { - connectionClosed(connection); - } - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-connector/src/test/java/org/eclipse/jetty/rhttp/connector/ReverseHTTPConnectorTest.java b/jetty-rhttp/jetty-rhttp-connector/src/test/java/org/eclipse/jetty/rhttp/connector/ReverseHTTPConnectorTest.java deleted file mode 100644 index 994466323ab..00000000000 --- a/jetty-rhttp/jetty-rhttp-connector/src/test/java/org/eclipse/jetty/rhttp/connector/ReverseHTTPConnectorTest.java +++ /dev/null @@ -1,187 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.connector; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.concurrent.CountDownLatch; -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; - -import junit.framework.TestCase; - -import org.eclipse.jetty.rhttp.client.ClientListener; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPListener; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.rhttp.connector.ReverseHTTPConnector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.AbstractHandler; - -/** - * @version $Revision$ $Date$ - */ -public class ReverseHTTPConnectorTest extends TestCase -{ - public void testGatewayConnectorWithoutRequestBody() throws Exception - { - testGatewayConnector(false); - } - - public void testGatewayConnectorWithRequestBody() throws Exception - { - testGatewayConnector(true); - } - - private void testGatewayConnector(boolean withRequestBody) throws Exception - { - Server server = new Server(); - final CountDownLatch handlerLatch = new CountDownLatch(1); - CountDownLatch clientLatch = new CountDownLatch(1); - AtomicReference responseRef = new AtomicReference(); - ReverseHTTPConnector connector = new ReverseHTTPConnector(new TestClient(clientLatch, responseRef)); - server.addConnector(connector); - final String method = "POST"; - final String uri = "/test"; - final byte[] requestBody = withRequestBody ? "REQUEST-BODY".getBytes("UTF-8") : new byte[0]; - final int statusCode = HttpServletResponse.SC_CREATED; - final String headerName = "foo"; - final String headerValue = "bar"; - final byte[] responseBody = "RESPONSE-BODY".getBytes("UTF-8"); - server.setHandler(new AbstractHandler() - { - public void handle(String pathInfo, org.eclipse.jetty.server.Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException - { - assertEquals(method, httpRequest.getMethod()); - assertEquals(uri, httpRequest.getRequestURI()); - assertEquals(headerValue, httpRequest.getHeader(headerName)); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InputStream input = httpRequest.getInputStream(); - int read; - while ((read = input.read()) >= 0) - baos.write(read); - baos.close(); - assertTrue(Arrays.equals(requestBody, baos.toByteArray())); - - httpResponse.setStatus(statusCode); - httpResponse.setHeader(headerName, headerValue); - OutputStream output = httpResponse.getOutputStream(); - output.write(responseBody); - output.flush(); - request.setHandled(true); - handlerLatch.countDown(); - } - }); - server.start(); - - HashMap headers = new HashMap(); - headers.put("Host", "localhost"); - headers.put(headerName, headerValue); - headers.put("Content-Length", String.valueOf(requestBody.length)); - RHTTPRequest request = new RHTTPRequest(1, method, uri, headers, requestBody); - request = RHTTPRequest.fromRequestBytes(request.getId(), request.getRequestBytes()); - connector.onRequest(request); - - assertTrue(handlerLatch.await(1000, TimeUnit.MILLISECONDS)); - assertTrue(clientLatch.await(1000, TimeUnit.MILLISECONDS)); - RHTTPResponse response = responseRef.get(); - assertEquals(request.getId(), response.getId()); - assertEquals(statusCode, response.getStatusCode()); - assertEquals(headerValue, response.getHeaders().get(headerName)); - assertTrue(Arrays.equals(response.getBody(), responseBody)); - } - - private class TestClient implements RHTTPClient - { - private final CountDownLatch latch; - private final AtomicReference responseRef; - - private TestClient(CountDownLatch latch, AtomicReference response) - { - this.latch = latch; - this.responseRef = response; - } - - public String getTargetId() - { - return null; - } - - public void connect() throws IOException - { - } - - public void disconnect() throws IOException - { - } - - public void deliver(RHTTPResponse response) throws IOException - { - responseRef.set(response); - latch.countDown(); - } - - public void addListener(RHTTPListener listener) - { - } - - public void removeListener(RHTTPListener listener) - { - } - - public void addClientListener(ClientListener listener) - { - } - - public void removeClientListener(ClientListener listener) - { - } - - public String getHost() - { - return null; - } - - public int getPort() - { - return 0; - } - - public String getGatewayURI() - { - // TODO Auto-generated method stub - return null; - } - - public String getPath() - { - // TODO Auto-generated method stub - return null; - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-connector/src/test/java/org/eclipse/jetty/rhttp/connector/TestReverseServer.java b/jetty-rhttp/jetty-rhttp-connector/src/test/java/org/eclipse/jetty/rhttp/connector/TestReverseServer.java deleted file mode 100644 index 8ff810717c7..00000000000 --- a/jetty-rhttp/jetty-rhttp-connector/src/test/java/org/eclipse/jetty/rhttp/connector/TestReverseServer.java +++ /dev/null @@ -1,58 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.connector; - -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.embedded.HelloHandler; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.connector.ReverseHTTPConnector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.util.log.Log; - -/** - * A Test content server that uses a {@link ReverseHTTPConnector}. - * The main of this class starts 3 TestReversionServers with IDs A, B and C. - */ -public class TestReverseServer extends Server -{ - TestReverseServer(String targetId) - { - setHandler(new HelloHandler("Hello "+targetId,"Hi from "+targetId)); - - HttpClient httpClient = new HttpClient(); - RHTTPClient client = new JettyClient(httpClient,"http://localhost:8080/__rhttp",targetId); - ReverseHTTPConnector connector = new ReverseHTTPConnector(client); - - addConnector(connector); - } - - public static void main(String... args) throws Exception - { - Log.getLogger("org.mortbay.jetty.rhttp.client").setDebugEnabled(true); - - TestReverseServer[] node = new TestReverseServer[] { new TestReverseServer("A"),new TestReverseServer("B"),new TestReverseServer("C") }; - - for (TestReverseServer s : node) - s.start(); - - for (TestReverseServer s : node) - s.join(); - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/pom.xml b/jetty-rhttp/jetty-rhttp-gateway/pom.xml deleted file mode 100644 index 054bbd55bf3..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/pom.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - org.eclipse.jetty.rhttp - jetty-rhttp-project - 9.0.0-SNAPSHOT - - - 4.0.0 - reverse-http-gateway - jar - Jetty :: Reverse HTTP :: Gateway - - - ${project.groupId}.rhttp.gateway - - - - - - org.codehaus.mojo - exec-maven-plugin - - org.mortbay.jetty.rhttp.gateway.Main - - - - - - org.apache.felix - maven-bundle-plugin - true - - - - manifest - - - - * - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - - - - - - org.eclipse.jetty - reverse-http-client - ${project.version} - - - javax.servlet - javax.servlet-api - - - org.eclipse.jetty - jetty-io - - - org.eclipse.jetty - jetty-continuation - ${project.version} - - - org.eclipse.jetty - jetty-server - - - org.eclipse.jetty - jetty-servlet - ${project.version} - - - org.eclipse.jetty - jetty-client - - - org.eclipse.jetty.toolchain - jetty-test-helper - test - - - diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ClientDelegate.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ClientDelegate.java deleted file mode 100644 index 192bf1f4ebc..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ClientDelegate.java +++ /dev/null @@ -1,92 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -import org.eclipse.jetty.rhttp.client.RHTTPRequest; - - -/** - *

A ClientDelegate is the server-side counterpart of a gateway client.

- *

The gateway client, the comet protocol and the ClientDelegate form the - * Half-Object plus Protocol pattern that is used between the gateway server - * and the gateway client.

- *

ClientDelegate offers a server-side API on top of the comet communication.
- * The API allows to enqueue server-side events to the gateway client, allows to - * flush them to the gateway client, and allows to close and dispose server-side - * resources when the gateway client disconnects.

- * - * @version $Revision$ $Date$ - */ -public interface ClientDelegate -{ - /** - * @return the targetId that uniquely identifies this client delegate. - */ - public String getTargetId(); - - /** - *

Enqueues the given request to the delivery queue so that it will be sent to the - * gateway client on the first flush occasion.

- *

Requests may fail to be queued, for example because the gateway client disconnected - * concurrently.

- * - * @param request the request to add to the delivery queue - * @return whether the request has been queued or not - * @see #process(HttpServletRequest) - */ - public boolean enqueue(RHTTPRequest request); - - /** - *

Flushes the requests that have been {@link #enqueue(RHTTPRequest) enqueued}.

- *

If no requests have been enqueued, then this method may suspend the current request for - * the long poll timeout.
- * The request is suspended only if all these conditions holds true: - *

    - *
  • it is not the first time that this method is called for this client delegate
  • - *
  • no requests have been enqueued
  • - *
  • this client delegate is not closed
  • - *
  • the previous call to this method did not suspend the request
  • - *
- * In all other cases, a response if sent to the gateway client, possibly containing no requests. - * - * @param httpRequest the HTTP request for the long poll request from the gateway client - * @return the list of requests to send to the gateway client, or null if no response should be sent - * to the gateway client - * @throws IOException in case of I/O exception while flushing content to the gateway client - * @see #enqueue(RHTTPRequest) - */ - public List process(HttpServletRequest httpRequest) throws IOException; - - /** - *

Closes this client delegate, in response to a gateway client request to disconnect.

- * @see #isClosed() - */ - public void close(); - - /** - * @return whether this delegate client is closed - * @see #close() - */ - public boolean isClosed(); -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ConnectorServlet.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ConnectorServlet.java deleted file mode 100644 index d477375e32d..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ConnectorServlet.java +++ /dev/null @@ -1,224 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - * The servlet that handles the communication with the gateway clients. - * @version $Revision$ $Date$ - */ -public class ConnectorServlet extends HttpServlet -{ - private final Logger logger = Log.getLogger(getClass().toString()); - private final TargetIdRetriever targetIdRetriever = new StandardTargetIdRetriever(); - private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); - private final ConcurrentMap> expirations = new ConcurrentHashMap>(); - private final Gateway gateway; - private long clientTimeout=15000; - - public ConnectorServlet(Gateway gateway) - { - this.gateway = gateway; - } - - @Override - public void init() throws ServletException - { - String t = getInitParameter("clientTimeout"); - if (t!=null && !"".equals(t)) - clientTimeout=Long.parseLong(t); - } - - @Override - protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - String targetId = targetIdRetriever.retrieveTargetId(request); - - String uri = request.getRequestURI(); - String path = uri.substring(request.getServletPath().length()); - String[] segments = path.split("/"); - if (segments.length < 3) - throw new ServletException("Invalid request to " + getClass().getSimpleName() + ": " + uri); - - String action = segments[2]; - if ("handshake".equals(action)) - serviceHandshake(targetId, request, response); - else if ("connect".equals(action)) - serviceConnect(targetId, request, response); - else if ("deliver".equals(action)) - serviceDeliver(targetId, request, response); - else if ("disconnect".equals(action)) - serviceDisconnect(targetId, request, response); - else - throw new ServletException("Invalid request to " + getClass().getSimpleName() + ": " + uri); - } - - private void serviceHandshake(String targetId, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException - { - ClientDelegate client = gateway.getClientDelegate(targetId); - if (client != null) - throw new IOException("Client with targetId " + targetId + " is already connected"); - - client = gateway.newClientDelegate(targetId); - ClientDelegate existing = gateway.addClientDelegate(targetId, client); - if (existing != null) - throw new IOException("Client with targetId " + targetId + " is already connected"); - - flush(client, httpRequest, httpResponse); - } - - private void flush(ClientDelegate client, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException - { - List requests = client.process(httpRequest); - if (requests != null) - { - // Schedule before sending the requests, to avoid that the remote client - // reconnects before we have scheduled the expiration timeout. - if (!client.isClosed()) - schedule(client); - - ServletOutputStream output = httpResponse.getOutputStream(); - for (RHTTPRequest request : requests) - output.write(request.getFrameBytes()); - // I could count the framed bytes of all requests and set a Content-Length header, - // but the implementation of ServletOutputStream takes care of everything: - // if the request was HTTP/1.1, then flushing result in a chunked response, but the - // client know how to handle it; if the request was HTTP/1.0, then no chunking. - // To avoid chunking in HTTP/1.1 I must set the Content-Length header. - output.flush(); - logger.debug("Delivered to device {} requests {} ", client.getTargetId(), requests); - } - } - - private void schedule(ClientDelegate client) - { - Future task = scheduler.schedule(new ClientExpirationTask(client), clientTimeout, TimeUnit.MILLISECONDS); - Future existing = expirations.put(client.getTargetId(), task); - assert existing == null; - } - - private void unschedule(String targetId) - { - Future task = expirations.remove(targetId); - if (task != null) - task.cancel(false); - } - - private void serviceConnect(String targetId, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException - { - unschedule(targetId); - - ClientDelegate client = gateway.getClientDelegate(targetId); - if (client == null) - { - // Expired client tries to connect without handshake - httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); - return; - } - - flush(client, httpRequest, httpResponse); - - if (client.isClosed()) - gateway.removeClientDelegate(targetId); - } - - private void expireConnect(ClientDelegate client, long time) - { - String targetId = client.getTargetId(); - logger.info("Client with targetId {} missing, last seen {} ms ago, closing it", targetId, System.currentTimeMillis() - time); - client.close(); - // If the client expired, means that it did not connect, - // so there no request to resume, and we cleanup here - // (while normally this cleanup is done in serviceConnect()) - unschedule(targetId); - gateway.removeClientDelegate(targetId); - } - - private void serviceDeliver(String targetId, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException - { - if (gateway.getClientDelegate(targetId) == null) - { - // Expired client tries to deliver without handshake - httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); - return; - } - - byte[] body = Utils.read(httpRequest.getInputStream()); - - RHTTPResponse response = RHTTPResponse.fromFrameBytes(body); - - ExternalRequest externalRequest = gateway.removeExternalRequest(response.getId()); - if (externalRequest != null) - { - externalRequest.respond(response); - logger.debug("Deliver request from device {}, gateway request {}, response {}", new Object[] {targetId, externalRequest, response}); - } - else - { - // We can arrive here for a race with the continuation expiration, which expired just before - // the gateway client responded with a valid response; log this case ignore it. - logger.debug("Deliver request from device {}, missing gateway request, response {}", targetId, response); - } - } - - private void serviceDisconnect(String targetId, HttpServletRequest request, HttpServletResponse response) - { - // Do not remove the ClientDelegate from the gateway here, - // since closing the ClientDelegate will resume the connect request - // and we remove the ClientDelegate from the gateway there - ClientDelegate client = gateway.getClientDelegate(targetId); - if (client != null) - client.close(); - } - - private class ClientExpirationTask implements Runnable - { - private final long time = System.currentTimeMillis(); - private final ClientDelegate client; - - public ClientExpirationTask(ClientDelegate client) - { - this.client = client; - } - - public void run() - { - expireConnect(client, time); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ExternalRequest.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ExternalRequest.java deleted file mode 100644 index 314279501c9..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ExternalRequest.java +++ /dev/null @@ -1,54 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; - -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; - - -/** - *

ExternalRequest represent an external request made to the gateway server.

- *

ExternalRequests that arrive to the gateway server are suspended, waiting - * for a response from the corresponding gateway client.

- * - * @version $Revision$ $Date$ - */ -public interface ExternalRequest -{ - /** - *

Suspends this ExternalRequest waiting for a response from the gateway client.

- * @return true if the ExternalRequest has been suspended, false if the - * ExternalRequest has already been responded. - */ - public boolean suspend(); - - /** - *

Responds to the original external request with the response arrived from the gateway client.

- * @param response the response arrived from the gateway client - * @throws IOException if responding to the original external request fails - */ - public void respond(RHTTPResponse response) throws IOException; - - /** - * @return the request to be sent to the gateway client - */ - public RHTTPRequest getRequest(); -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ExternalServlet.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ExternalServlet.java deleted file mode 100644 index 6bda7231468..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/ExternalServlet.java +++ /dev/null @@ -1,88 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - * The servlet that handles external requests. - * - * @version $Revision$ $Date$ - */ -public class ExternalServlet extends HttpServlet -{ - private final Logger logger = Log.getLogger(getClass().toString()); - private final Gateway gateway; - private TargetIdRetriever targetIdRetriever; - - public ExternalServlet(Gateway gateway, TargetIdRetriever targetIdRetriever) - { - this.gateway = gateway; - this.targetIdRetriever = targetIdRetriever; - } - - public TargetIdRetriever getTargetIdRetriever() - { - return targetIdRetriever; - } - - public void setTargetIdRetriever(TargetIdRetriever targetIdRetriever) - { - this.targetIdRetriever = targetIdRetriever; - } - - @Override - protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException - { - logger.debug("External http request: {}", httpRequest.getRequestURL()); - - String targetId = targetIdRetriever.retrieveTargetId(httpRequest); - if (targetId == null) - throw new ServletException("Invalid request to " + getClass().getSimpleName() + ": " + httpRequest.getRequestURI()); - - ClientDelegate client = gateway.getClientDelegate(targetId); - if (client == null) throw new ServletException("Client with targetId " + targetId + " is not connected"); - - ExternalRequest externalRequest = gateway.newExternalRequest(httpRequest, httpResponse); - RHTTPRequest request = externalRequest.getRequest(); - ExternalRequest existing = gateway.addExternalRequest(request.getId(), externalRequest); - assert existing == null; - logger.debug("External request {} for device {}", request, targetId); - - boolean delivered = client.enqueue(request); - if (delivered) - { - externalRequest.suspend(); - } - else - { - // TODO: improve this: we can temporarly queue this request elsewhere and wait for the client to reconnect ? - throw new ServletException("Could not enqueue request to client with targetId " + targetId); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Gateway.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Gateway.java deleted file mode 100644 index 83bd22c8620..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Gateway.java +++ /dev/null @@ -1,99 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - *

Gateway instances are responsible of holding the state of the gateway server.

- *

The state is composed by: - *

    - *
  • {@link ExternalRequest external requests} that are suspended waiting for the response
  • - *
  • {@link ClientDelegate gateway clients} that are connected with the gateway server
  • - *

- *

Instances of this class are created by the {@link GatewayServer}.

- * - * @version $Revision$ $Date$ - */ -public interface Gateway -{ - /** - *

Returns the {@link ClientDelegate} with the given targetId.
- * If there is no such ClientDelegate returns null.

- * - * @param targetId the targetId of the ClientDelegate to return - * @return the ClientDelegate associated with the given targetId - */ - public ClientDelegate getClientDelegate(String targetId); - - /** - *

Creates and configures a new {@link ClientDelegate} with the given targetId.

- * @param targetId the targetId of the ClientDelegate to create - * @return a newly created ClientDelegate - * @see #addClientDelegate(String, ClientDelegate) - */ - public ClientDelegate newClientDelegate(String targetId); - - /** - *

Maps the given ClientDelegate to the given targetId.

- * @param targetId the targetId of the given ClientDelegate - * @param client the ClientDelegate to map - * @return the previously existing ClientDelegate mapped to the same targetId - * @see #removeClientDelegate(String) - */ - public ClientDelegate addClientDelegate(String targetId, ClientDelegate client); - - /** - *

Removes the {@link ClientDelegate} associated with the given targetId.

- * @param targetId the targetId of the ClientDelegate to remove - * @return the removed ClientDelegate, or null if no ClientDelegate was removed - * @see #addClientDelegate(String, ClientDelegate) - */ - public ClientDelegate removeClientDelegate(String targetId); - - /** - *

Creates a new {@link ExternalRequest} from the given HTTP request and HTTP response.

- * @param httpRequest the HTTP request of the external request - * @param httpResponse the HTTP response of the external request - * @return a newly created ExternalRequest - * @throws IOException in case of failures creating the ExternalRequest - * @see #addExternalRequest(int, ExternalRequest) - */ - public ExternalRequest newExternalRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException; - - /** - * Maps the given ExternalRequest with the given requestId into the gateway state. - * @param requestId the id of the ExternalRequest - * @param externalRequest the ExternalRequest to map - * @return the previously existing ExternalRequest mapped to the same requestId - * @see #removeExternalRequest(int) - */ - public ExternalRequest addExternalRequest(int requestId, ExternalRequest externalRequest); - - /** - * Removes the ExternalRequest mapped to the given requestId from the gateway state. - * @param requestId the id of the ExternalRequest - * @return the removed ExternalRequest - * @see #addExternalRequest(int, ExternalRequest) - */ - public ExternalRequest removeExternalRequest(int requestId); -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayProxyServer.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayProxyServer.java deleted file mode 100644 index d446f69b435..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayProxyServer.java +++ /dev/null @@ -1,228 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpExchange; -import org.eclipse.jetty.io.Buffer; -import org.eclipse.jetty.io.ByteArrayBuffer; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPListener; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.nio.SelectChannelConnector; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - *

This class combines a gateway server and a gateway client to obtain the functionality of a simple proxy server.

- *

This gateway proxy server starts on port 8080 and can be set as http proxy in browsers such as Firefox, and used - * to browse the internet.

- *

Its functionality is limited (for example, it only supports http, and not https).

- * @version $Revision$ $Date$ - */ -public class GatewayProxyServer -{ - private static final Logger logger = Log.getLogger(GatewayProxyServer.class.toString()); - - public static void main(String[] args) throws Exception - { - GatewayServer server = new GatewayServer(); - - Connector plainConnector = new SelectChannelConnector(); - plainConnector.setPort(8080); - server.addConnector(plainConnector); - - ((StandardGateway)server.getGateway()).setExternalTimeout(180000); - ((StandardGateway)server.getGateway()).setGatewayTimeout(20000); - server.setTargetIdRetriever(new ProxyTargetIdRetriever()); - server.start(); - - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET); - httpClient.start(); - - RHTTPClient client = new JettyClient(httpClient, new Address("localhost", plainConnector.getPort()), server.getContext().getContextPath() + "/gw", "proxy"); - client.addListener(new ProxyListener(httpClient, client)); - client.connect(); - - Runtime.getRuntime().addShutdownHook(new Shutdown(server, httpClient, client)); - logger.info("{} started", GatewayProxyServer.class.getSimpleName()); - } - - private static class Shutdown extends Thread - { - private final GatewayServer server; - private final HttpClient httpClient; - private final RHTTPClient client; - - public Shutdown(GatewayServer server, HttpClient httpClient, RHTTPClient client) - { - this.server = server; - this.httpClient = httpClient; - this.client = client; - } - - @Override - public void run() - { - try - { - client.disconnect(); - httpClient.stop(); - server.stop(); - logger.info("{} stopped", GatewayProxyServer.class.getSimpleName()); - } - catch (Exception x) - { - logger.debug("Exception while stopping " + GatewayProxyServer.class.getSimpleName(), x); - } - } - } - - private static class ProxyListener implements RHTTPListener - { - private final HttpClient httpClient; - private final RHTTPClient client; - - private ProxyListener(HttpClient httpClient, RHTTPClient client) - { - this.httpClient = httpClient; - this.client = client; - } - - public void onRequest(RHTTPRequest request) throws Exception - { - ProxyExchange exchange = new ProxyExchange(); - Address address = Address.from(request.getHeaders().get("Host")); - if (address.getPort() == 0) address = new Address(address.getHost(), 80); - exchange.setAddress(address); - exchange.setMethod(request.getMethod()); - exchange.setURI(request.getURI()); - for (Map.Entry header : request.getHeaders().entrySet()) - exchange.setRequestHeader(header.getKey(), header.getValue()); - exchange.setRequestContent(new ByteArrayBuffer(request.getBody())); - int status = syncSend(exchange); - if (status == HttpExchange.STATUS_COMPLETED) - { - int statusCode = exchange.getResponseStatus(); - String statusMessage = exchange.getResponseMessage(); - Map responseHeaders = exchange.getResponseHeaders(); - byte[] responseBody = exchange.getResponseBody(); - RHTTPResponse response = new RHTTPResponse(request.getId(), statusCode, statusMessage, responseHeaders, responseBody); - client.deliver(response); - } - else - { - int statusCode = HttpServletResponse.SC_SERVICE_UNAVAILABLE; - String statusMessage = "Gateway error"; - HashMap responseHeaders = new HashMap(); - responseHeaders.put("Connection", "close"); - byte[] responseBody = new byte[0]; - RHTTPResponse response = new RHTTPResponse(request.getId(), statusCode, statusMessage, responseHeaders, responseBody); - client.deliver(response); - } - } - - private int syncSend(ProxyExchange exchange) throws Exception - { - long start = System.nanoTime(); - httpClient.send(exchange); - int status = exchange.waitForDone(); - long end = System.nanoTime(); - long millis = TimeUnit.NANOSECONDS.toMillis(end - start); - long micros = TimeUnit.NANOSECONDS.toMicros(end - start - TimeUnit.MILLISECONDS.toNanos(millis)); - logger.debug("Proxied request took {}.{} ms", millis, micros); - return status; - } - } - - private static class ProxyExchange extends ContentExchange - { - private String responseMessage; - private Map responseHeaders = new HashMap(); - private ByteArrayOutputStream responseBody = new ByteArrayOutputStream(); - - private ProxyExchange() - { - super(true); - } - - public String getResponseMessage() - { - return responseMessage; - } - - public Map getResponseHeaders() - { - return responseHeaders; - } - - public byte[] getResponseBody() - { - return responseBody.toByteArray(); - } - - @Override - protected void onResponseStatus(Buffer version, int code, Buffer message) throws IOException - { - super.onResponseStatus(version, code, message); - this.responseMessage = message.toString("UTF-8"); - } - - @Override - protected void onResponseHeader(Buffer nameBuffer, Buffer valueBuffer) throws IOException - { - super.onResponseHeader(nameBuffer, valueBuffer); - String name = nameBuffer.toString("UTF-8"); - String value = valueBuffer.toString("UTF-8"); - // Skip chunked header, since we read the whole body and will not re-chunk it - if (!name.equalsIgnoreCase("Transfer-Encoding") || !value.equalsIgnoreCase("chunked")) - responseHeaders.put(name, value); - } - - @Override - protected void onResponseContent(Buffer buffer) throws IOException - { - responseBody.write(buffer.asArray()); - super.onResponseContent(buffer); - } - } - - public static class ProxyTargetIdRetriever implements TargetIdRetriever - { - public String retrieveTargetId(HttpServletRequest httpRequest) - { - return "proxy"; - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayServer.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayServer.java deleted file mode 100644 index 5c86cd42181..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayServer.java +++ /dev/null @@ -1,171 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.jetty.http.MimeTypes; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.HandlerCollection; -import org.eclipse.jetty.servlet.DefaultServlet; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - *

The gateway server is a server component that acts as intermediary between - * external clients which perform requests for resources, and the - * resource providers.

- *

The particularity of the gateway server is that the resource providers - * connect to the gateway using a comet protocol.
- * The comet procotol functionality is implemented by a gateway client.
- * This is quite different from a normal proxy server where it is the proxy that - * connects to the resource providers.

- *

Schematically, this is how the gateway server works:

- *
- * External Client       Gateway Server         Gateway Client         Resource Provider
- *                              |                      |
- *                              | <-- comet req. 1 --- |
- *        | --- ext. req. 1 --> |                      |
- *        |                     | --- comet res. 1 --> |
- *        |                     | <-- comet req. 2 --- |
- *        |                                            | --- ext. req. 1 --> |
- *                                                                           |
- *        |                                            | <-- ext. res. 1 --- |
- *        |                     | <-- ext.  res. 1 --- |
- *        | <-- ext. res. 1 --- |
- *
- *        | --- ext. req. 2 --> |
- *        |                     | --- comet res. 2 --> |
- *        .                     .                      .
- * 
- *

The gateway server is made of two servlets: - *

    - *
  • the external servlet, that handles external requests
  • - *
  • the gateway servlet, that handles the communication with the gateway client
  • - *
- *

- *

External requests are suspended using Jetty continuations until a response for - * that request arrives from the resource provider, or a - * {@link #getExternalTimeout() configurable timeout} expires.
- * Comet requests made by the gateway client also expires after a (different) - * {@link #getGatewayTimeout() configurable timeout}.

- *

External requests are packed into {@link RHTTPRequest} objects, converted into an - * opaque byte array and sent as the body of the comet reponse to the gateway - * {@link RHTTPClient}.

- *

The gateway client uses a notification mechanism to alert listeners interested - * in external requests that have been forwarded through the gateway. It is up to the - * listeners to connect to the resource provider however they like.

- *

When the gateway client receives a response from the resource provider, it packs - * the response into a {@link RHTTPResponse} object, converts it into an opaque byte array - * and sends it as the body of a normal HTTP request to the gateway server.

- *

It is possible to connect more than one gateway client to a gateway server; each - * gateway client is identified by a unique targetId.
- * External requests must specify a targetId that allows the gateway server to forward - * the requests to the specific gateway client; how the targetId is retrieved from an - * external request is handled by {@link TargetIdRetriever} implementations.

- * - * @version $Revision$ $Date$ - */ -public class GatewayServer extends Server -{ - public final static String DFT_EXT_PATH="/gw"; - public final static String DFT_CONNECT_PATH="/__rhttp"; - private final Logger logger = Log.getLogger(getClass().toString()); - private final Gateway gateway; - private final ServletHolder externalServletHolder; - private final ServletHolder connectorServletHolder; - private final ServletContextHandler context; - - public GatewayServer() - { - this("",DFT_EXT_PATH,DFT_CONNECT_PATH,new StandardTargetIdRetriever()); - } - - public GatewayServer(String contextPath, String externalServletPath,String gatewayServletPath, TargetIdRetriever targetIdRetriever) - { - HandlerCollection handlers = new HandlerCollection(); - setHandler(handlers); - context = new ServletContextHandler(handlers, contextPath, ServletContextHandler.SESSIONS); - - // Setup the gateway - gateway = createGateway(); - - // Setup external servlet - ExternalServlet externalServlet = new ExternalServlet(gateway, targetIdRetriever); - externalServletHolder = new ServletHolder(externalServlet); - context.addServlet(externalServletHolder, externalServletPath + "/*"); - logger.debug("External servlet mapped to {}/*", externalServletPath); - - // Setup gateway servlet - ConnectorServlet gatewayServlet = new ConnectorServlet(gateway); - connectorServletHolder = new ServletHolder(gatewayServlet); - connectorServletHolder.setInitParameter("clientTimeout", "15000"); - context.addServlet(connectorServletHolder, gatewayServletPath + "/*"); - logger.debug("Gateway servlet mapped to {}/*", gatewayServletPath); - } - - /** - * Creates and configures a {@link Gateway} object. - * @return the newly created and configured Gateway object. - */ - protected Gateway createGateway() - { - StandardGateway gateway = new StandardGateway(); - return gateway; - } - - public ServletContextHandler getContext() - { - return context; - } - - public Gateway getGateway() - { - return gateway; - } - - public ServletHolder getExternalServlet() - { - return externalServletHolder; - } - - public ServletHolder getConnectorServlet() - { - return connectorServletHolder; - } - - public void setTargetIdRetriever(TargetIdRetriever retriever) - { - ((ExternalServlet)externalServletHolder.getServletInstance()).setTargetIdRetriever(retriever); - } - - public TargetIdRetriever getTargetIdRetriever() - { - return ((ExternalServlet)externalServletHolder.getServletInstance()).getTargetIdRetriever(); - } - -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/HostTargetIdRetriever.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/HostTargetIdRetriever.java deleted file mode 100644 index 7c80795315c..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/HostTargetIdRetriever.java +++ /dev/null @@ -1,54 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import javax.servlet.http.HttpServletRequest; - -/** - * @version $Revision$ $Date$ - */ -public class HostTargetIdRetriever implements TargetIdRetriever -{ - private final String suffix; - - public HostTargetIdRetriever(String suffix) - { - this.suffix = suffix; - } - - public String retrieveTargetId(HttpServletRequest httpRequest) - { - String host = httpRequest.getHeader("Host"); - if (host != null) - { - // Strip the port - int colon = host.indexOf(':'); - if (colon > 0) - { - host = host.substring(0, colon); - } - - if (suffix != null && host.endsWith(suffix)) - { - return host.substring(0, host.length() - suffix.length()); - } - } - return host; - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Main.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Main.java deleted file mode 100644 index b21ce11f55b..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Main.java +++ /dev/null @@ -1,128 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.nio.SelectChannelConnector; -import org.eclipse.jetty.servlet.DefaultServlet; -import org.eclipse.jetty.servlet.ServletHolder; - -/** - *

Main class that starts the gateway server.

- *

This class supports the following arguments:

- *
    - *
  • --port=<port> specifies the port on which the gateway server listens to, by default 8080
  • - *
  • --retriever=<retriever> specifies the - * {@link GatewayServer#setTargetIdRetriever(TargetIdRetriever) target id retriever}
  • - *
  • --resources=<resources file path> specifies the resource file path for the gateway
  • - *
- *

Examples

- *

java --port=8080

- *

java --port=8080 --resources=/tmp/gateway-resources

- *

java --port=8080 --retriever=standard

- *

java --port=8080 --retriever=host,.rhttp.example.com

- *

The latter example specifies the {@link HostTargetIdRetriever} with a suffix of .rhttp.example.com

- * - * @see GatewayServer - * @version $Revision$ $Date$ - */ -public class Main -{ - private static final String PORT_ARG = "port"; - private static final String RESOURCES_ARG = "resources"; - private static final String RETRIEVER_ARG = "retriever"; - - public static void main(String[] args) throws Exception - { - Map arguments = parse(args); - - int port = 8080; - if (arguments.containsKey(PORT_ARG)) - port = (Integer)arguments.get(PORT_ARG); - - String resources = null; - if (arguments.containsKey(RESOURCES_ARG)) - resources = (String)arguments.get(RESOURCES_ARG); - - TargetIdRetriever retriever = null; - if (arguments.containsKey(RETRIEVER_ARG)) - retriever = (TargetIdRetriever)arguments.get(RETRIEVER_ARG); - - GatewayServer server = new GatewayServer(); - - Connector connector = new SelectChannelConnector(); - connector.setPort(port); - server.addConnector(connector); - - if (resources != null) - { - server.getContext().setResourceBase(resources); - ServletHolder resourcesServletHolder = server.getContext().addServlet(DefaultServlet.class,"__r/*"); - resourcesServletHolder.setInitParameter("dirAllowed", "true"); - } - - if (retriever != null) - server.setTargetIdRetriever(retriever); - - server.start(); - } - - private static Map parse(String[] args) - { - Map result = new HashMap(); - - Pattern pattern = Pattern.compile("--([^=]+)=(.+)"); - for (String arg : args) - { - Matcher matcher = pattern.matcher(arg); - if (matcher.matches()) - { - String argName = matcher.group(1); - if (PORT_ARG.equals(argName)) - { - result.put(PORT_ARG, Integer.parseInt(matcher.group(2))); - } - else if (RESOURCES_ARG.equals(argName)) - { - String argValue = matcher.group(2); - result.put(RESOURCES_ARG, argValue); - } - else if (RETRIEVER_ARG.equals(argName)) - { - String argValue = matcher.group(2); - if (argValue.startsWith("host,")) - { - String[] typeAndSuffix = StringUtil.split(argValue); - if (typeAndSuffix.length != 2) - throw new IllegalArgumentException("Invalid option " + arg + ", must be of the form --" + RETRIEVER_ARG + "=host,suffix"); - - result.put(RETRIEVER_ARG, new HostTargetIdRetriever(typeAndSuffix[1])); - } - } - } - } - - return result; - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardClientDelegate.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardClientDelegate.java deleted file mode 100644 index f8749fb72b8..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardClientDelegate.java +++ /dev/null @@ -1,172 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -import org.eclipse.jetty.continuation.Continuation; -import org.eclipse.jetty.continuation.ContinuationSupport; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - *

Default implementation of {@link ClientDelegate}.

- * - * @version $Revision$ $Date$ - */ -public class StandardClientDelegate implements ClientDelegate -{ - private final Logger logger = Log.getLogger(getClass().toString()); - private final Object lock = new Object(); - private final List requests = new ArrayList(); - private final String targetId; - private volatile boolean firstFlush = true; - private volatile long timeout; - private volatile boolean closed; - private Continuation continuation; - - public StandardClientDelegate(String targetId) - { - this.targetId = targetId; - } - - public String getTargetId() - { - return targetId; - } - - public long getTimeout() - { - return timeout; - } - - public void setTimeout(long timeout) - { - this.timeout = timeout; - } - - public boolean enqueue(RHTTPRequest request) - { - if (isClosed()) - return false; - - synchronized (lock) - { - requests.add(request); - resume(); - } - - return true; - } - - private void resume() - { - synchronized (lock) - { - // Continuation may be null in several cases: - // 1. there always is something to deliver so we never suspend - // 2. concurrent calls to add() and close() - // 3. concurrent close() with a long poll that expired - // 4. concurrent close() with a long poll that resumed - if (continuation != null) - { - continuation.resume(); - // Null the continuation, as there is no point is resuming multiple times - continuation = null; - } - } - } - - public List process(HttpServletRequest httpRequest) throws IOException - { - // We want to respond in the following cases: - // 1. It's the first time we process: the client will wait for a response before issuing another connect. - // 2. The client disconnected, so we want to return from this connect before it times out. - // 3. We've been woken up because there are responses to send. - // 4. The continuation was suspended but timed out. - // The timeout case is different from a non-first connect, in that we want to return - // a (most of the times empty) response and we do not want to wait again. - // The order of these if statements is important, as the continuation timed out only if - // the client is not closed and there are no responses to send - List result = Collections.emptyList(); - if (firstFlush) - { - firstFlush = false; - logger.debug("Connect request (first) from device {}, delivering requests {}", targetId, result); - } - else - { - // Synchronization is crucial here, since we don't want to suspend if there is something to deliver - synchronized (lock) - { - int size = requests.size(); - if (size > 0) - { - assert continuation == null; - result = new ArrayList(size); - result.addAll(requests); - requests.clear(); - logger.debug("Connect request (resumed) from device {}, delivering requests {}", targetId, result); - } - else - { - if (continuation != null) - { - continuation = null; - logger.debug("Connect request (expired) from device {}, delivering requests {}", targetId, result); - } - else - { - if (isClosed()) - { - logger.debug("Connect request (closed) from device {}, delivering requests {}", targetId, result); - } - else - { - // Here we need to suspend - continuation = ContinuationSupport.getContinuation(httpRequest); - continuation.setTimeout(getTimeout()); - continuation.suspend(); - result = null; - logger.debug("Connect request (suspended) from device {}", targetId); - } - } - } - } - } - return result; - } - - public void close() - { - closed = true; - resume(); - } - - public boolean isClosed() - { - return closed; - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardExternalRequest.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardExternalRequest.java deleted file mode 100644 index df12111b66c..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardExternalRequest.java +++ /dev/null @@ -1,189 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; -import java.util.Map; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.continuation.Continuation; -import org.eclipse.jetty.continuation.ContinuationListener; -import org.eclipse.jetty.continuation.ContinuationSupport; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - * Default implementation of {@link ExternalRequest}. - * - * @version $Revision$ $Date$ - */ -public class StandardExternalRequest implements ExternalRequest -{ - private final Logger logger = Log.getLogger(getClass().toString()); - private final RHTTPRequest request; - private final HttpServletRequest httpRequest; - private final HttpServletResponse httpResponse; - private final Gateway gateway; - private final Object lock = new Object(); - private volatile long timeout; - private Continuation continuation; - private boolean responded; - - public StandardExternalRequest(RHTTPRequest request, HttpServletRequest httpRequest, HttpServletResponse httpResponse, Gateway gateway) - { - this.request = request; - this.httpRequest = httpRequest; - this.httpResponse = httpResponse; - this.gateway = gateway; - } - - public long getTimeout() - { - return timeout; - } - - public void setTimeout(long timeout) - { - this.timeout = timeout; - } - - public boolean suspend() - { - synchronized (lock) - { - // We suspend only if we have no responded yet - if (!responded) - { - assert continuation == null; - continuation = ContinuationSupport.getContinuation(httpRequest); - continuation.setTimeout(getTimeout()); - continuation.addContinuationListener(new TimeoutListener()); - continuation.suspend(httpResponse); - logger.debug("Request {} suspended", getRequest()); - } - else - { - logger.debug("Request {} already responded", getRequest()); - } - return !responded; - } - } - - public void respond(RHTTPResponse response) throws IOException - { - responseCompleted(response); - } - - private void responseCompleted(RHTTPResponse response) throws IOException - { - synchronized (lock) - { - // Could be that we complete exactly when the response is being expired - if (!responded) - { - httpResponse.setStatus(response.getStatusCode()); - - for (Map.Entry header : response.getHeaders().entrySet()) - httpResponse.setHeader(header.getKey(), header.getValue()); - - ServletOutputStream output = httpResponse.getOutputStream(); - output.write(response.getBody()); - output.flush(); - - // It may happen that the continuation is null, - // because the response arrived before we had the chance to suspend - if (continuation != null) - { - continuation.complete(); - continuation = null; - } - - // Mark as responded, so we know we don't have to suspend - // or respond with an expired response - responded = true; - - if (logger.isDebugEnabled()) - { - String eol = System.getProperty("line.separator"); - logger.debug("Request {} responded {}{}{}{}{}", new Object[]{request, response, eol, request.toLongString(), eol, response.toLongString()}); - } - } - } - } - - private void responseExpired() throws IOException - { - synchronized (lock) - { - // Could be that we expired exactly when the response is being completed - if (!responded) - { - httpResponse.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT, "Gateway Time-out"); - - continuation.complete(); - continuation = null; - - // Mark as responded, so we know we don't have to respond with a completed response - responded = true; - - logger.debug("Request {} expired", getRequest()); - } - } - } - - public RHTTPRequest getRequest() - { - return request; - } - - @Override - public String toString() - { - return request.toString(); - } - - private class TimeoutListener implements ContinuationListener - { - public void onComplete(Continuation continuation) - { - } - - public void onTimeout(Continuation continuation) - { - ExternalRequest externalRequest = gateway.removeExternalRequest(getRequest().getId()); - // The gateway request can be null for a race with delivery - if (externalRequest != null) - { - try - { - responseExpired(); - } - catch (Exception x) - { - logger.warn("Request " + getRequest() + " expired but failed", x); - } - } - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardGateway.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardGateway.java deleted file mode 100644 index 1e39889f7ff..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardGateway.java +++ /dev/null @@ -1,131 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -/** - * Default implementation of {@link Gateway}. - * - * @version $Revision$ $Date$ - */ -public class StandardGateway implements Gateway -{ - private final Logger logger = Log.getLogger(getClass().toString()); - private final ConcurrentMap clients = new ConcurrentHashMap(); - private final ConcurrentMap requests = new ConcurrentHashMap(); - private final AtomicInteger requestIds = new AtomicInteger(); - private volatile long gatewayTimeout=20000; - private volatile long externalTimeout=60000; - - public long getGatewayTimeout() - { - return gatewayTimeout; - } - - public void setGatewayTimeout(long timeout) - { - this.gatewayTimeout = timeout; - } - - public long getExternalTimeout() - { - return externalTimeout; - } - - public void setExternalTimeout(long externalTimeout) - { - this.externalTimeout = externalTimeout; - } - - public ClientDelegate getClientDelegate(String targetId) - { - return clients.get(targetId); - } - - public ClientDelegate newClientDelegate(String targetId) - { - StandardClientDelegate client = new StandardClientDelegate(targetId); - client.setTimeout(getGatewayTimeout()); - return client; - } - - public ClientDelegate addClientDelegate(String targetId, ClientDelegate client) - { - return clients.putIfAbsent(targetId, client); - } - - public ClientDelegate removeClientDelegate(String targetId) - { - return clients.remove(targetId); - } - - public ExternalRequest newExternalRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException - { - int requestId = requestIds.incrementAndGet(); - RHTTPRequest request = convertHttpRequest(requestId, httpRequest); - StandardExternalRequest gatewayRequest = new StandardExternalRequest(request, httpRequest, httpResponse, this); - gatewayRequest.setTimeout(getExternalTimeout()); - return gatewayRequest; - } - - protected RHTTPRequest convertHttpRequest(int requestId, HttpServletRequest httpRequest) throws IOException - { - Map headers = new HashMap(); - for (Enumeration headerNames = httpRequest.getHeaderNames(); headerNames.hasMoreElements();) - { - String name = (String)headerNames.nextElement(); - // TODO: improve by supporting getHeaders(name) - String value = httpRequest.getHeader(name); - headers.put(name, value); - } - - byte[] body = Utils.read(httpRequest.getInputStream()); - return new RHTTPRequest(requestId, httpRequest.getMethod(), httpRequest.getRequestURI(), headers, body); - } - - public ExternalRequest addExternalRequest(int requestId, ExternalRequest externalRequest) - { - ExternalRequest existing = requests.putIfAbsent(requestId, externalRequest); - if (existing == null) - logger.debug("Added external request {}/{} - {}", new Object[]{requestId, requests.size(), externalRequest}); - return existing; - } - - public ExternalRequest removeExternalRequest(int requestId) - { - ExternalRequest externalRequest = requests.remove(requestId); - if (externalRequest != null) - logger.debug("Removed external request {}/{} - {}", new Object[]{requestId, requests.size(), externalRequest}); - return externalRequest; - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardTargetIdRetriever.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardTargetIdRetriever.java deleted file mode 100644 index c1d4a620760..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/StandardTargetIdRetriever.java +++ /dev/null @@ -1,40 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import javax.servlet.http.HttpServletRequest; - -/** - *

This implementation retrieves the targetId from the request URI following this pattern:

- *
- * /contextPath/servletPath/<targetId>/other/paths
- * 
- * @version $Revision$ $Date$ - */ -public class StandardTargetIdRetriever implements TargetIdRetriever -{ - public String retrieveTargetId(HttpServletRequest httpRequest) - { - String uri = httpRequest.getRequestURI(); - String path = uri.substring(httpRequest.getServletPath().length()); - String[] segments = path.split("/"); - if (segments.length < 2) return null; - return segments[1]; - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/TargetIdRetriever.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/TargetIdRetriever.java deleted file mode 100644 index 53a36bd46aa..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/TargetIdRetriever.java +++ /dev/null @@ -1,40 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import javax.servlet.http.HttpServletRequest; - -/** - *

Implementations should retrieve a targetId from an external request.

- *

Implementations of this class may return a fixed value, or inspect the request - * looking for URL patterns (e.g. "/<targetId>/resource.jsp"), or looking for request - * parameters (e.g. "/resource.jsp?targetId=<targetId>), or looking for virtual host - * naming patterns (e.g. "http://<targetId>.host.com/resource.jsp"), etc.

- * - * @version $Revision$ $Date$ - */ -public interface TargetIdRetriever -{ - /** - * Extracts and returns the targetId. - * @param httpRequest the external request from where the targetId could be extracted - * @return the extracted targetId - */ - public String retrieveTargetId(HttpServletRequest httpRequest); -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Utils.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Utils.java deleted file mode 100644 index 325232a0430..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/Utils.java +++ /dev/null @@ -1,40 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * @version $Revision$ $Date$ - */ -class Utils -{ - static byte[] read(InputStream input) throws IOException - { - ByteArrayOutputStream body = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int read; - while ((read = input.read(buffer)) >= 0) - body.write(buffer, 0, read); - body.close(); - return body.toByteArray(); - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ClientTimeoutTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ClientTimeoutTest.java deleted file mode 100644 index ad87f827d31..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ClientTimeoutTest.java +++ /dev/null @@ -1,115 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.rhttp.client.ClientListener; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.rhttp.gateway.StandardGateway; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - - -/** - * @version $Revision$ $Date$ - */ -public class ClientTimeoutTest extends TestCase -{ - public void testClientTimeout() throws Exception - { - GatewayServer server = new GatewayServer(); - Connector connector = new SelectChannelConnector(); - server.addConnector(connector); - final long clientTimeout = 2000L; - server.getConnectorServlet().setInitParameter("clientTimeout",""+clientTimeout); - final long gatewayTimeout = 4000L; - ((StandardGateway)server.getGateway()).setGatewayTimeout(gatewayTimeout); - server.start(); - try - { - Address address = new Address("localhost", connector.getLocalPort()); - - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - try - { - String targetId = "1"; - final RHTTPClient client = new JettyClient(httpClient, address, server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, targetId) - { - private final AtomicInteger connects = new AtomicInteger(); - - @Override - protected void asyncConnect() - { - if (connects.incrementAndGet() == 2) - { - try - { - // Wait here instead of connecting, so that the client expires on the server - Thread.sleep(clientTimeout * 2); - } - catch (InterruptedException x) - { - throw new RuntimeException(x); - } - } - super.asyncConnect(); - } - }; - - final CountDownLatch connectLatch = new CountDownLatch(1); - client.addClientListener(new ClientListener.Adapter() - { - @Override - public void connectRequired() - { - connectLatch.countDown(); - } - }); - client.connect(); - try - { - assertTrue(connectLatch.await(gatewayTimeout + clientTimeout * 3, TimeUnit.MILLISECONDS)); - } - finally - { - client.disconnect(); - } - } - finally - { - httpClient.stop(); - } - } - finally - { - server.stop(); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/DisconnectClientTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/DisconnectClientTest.java deleted file mode 100644 index 89f4281c1ad..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/DisconnectClientTest.java +++ /dev/null @@ -1,93 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - - -/** - * @version $Revision$ $Date$ - */ -public class DisconnectClientTest extends TestCase -{ - public void testDifferentClientDisconnects() throws Exception - { - GatewayServer server = new GatewayServer(); - Connector connector = new SelectChannelConnector(); - server.addConnector(connector); - server.start(); - try - { - Address address = new Address("localhost", connector.getLocalPort()); - - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - try - { - final CountDownLatch latch = new CountDownLatch(1); - String targetId = "1"; - final RHTTPClient client1 = new JettyClient(httpClient, address, server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, targetId) - { - @Override - protected void connectComplete(byte[] responseContent) throws IOException - { - // If the other client can disconnect this one, this method is called soon after it disconnected - latch.countDown(); - super.connectComplete(responseContent); - } - }; - client1.connect(); - try - { - final RHTTPClient client2 = new JettyClient(httpClient, address, server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, targetId); - // Disconnect client 2, this should not disconnect client1 - client2.disconnect(); - - // We want the await() to expire, it means it has not disconnected - assertFalse(latch.await(1000, TimeUnit.MILLISECONDS)); - } - finally - { - client1.disconnect(); - } - } - finally - { - httpClient.stop(); - } - } - finally - { - server.stop(); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/DuplicateClientTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/DuplicateClientTest.java deleted file mode 100644 index f8821aeab84..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/DuplicateClientTest.java +++ /dev/null @@ -1,84 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - - -/** - * @version $Revision$ $Date$ - */ -public class DuplicateClientTest extends TestCase -{ - public void testDuplicateClient() throws Exception - { - GatewayServer server = new GatewayServer(); - Connector connector = new SelectChannelConnector(); - server.addConnector(connector); - server.start(); - try - { - Address address = new Address("localhost", connector.getLocalPort()); - - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - try - { - String targetId = "1"; - final RHTTPClient client1 = new JettyClient(httpClient, address, server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, targetId); - client1.connect(); - try - { - final RHTTPClient client2 = new JettyClient(httpClient, address, server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, targetId); - try - { - client2.connect(); - fail(); - } - catch (IOException x) - { - } - } - finally - { - client1.disconnect(); - } - } - finally - { - httpClient.stop(); - } - } - finally - { - server.stop(); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ExternalRequestNotSuspendedTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ExternalRequestNotSuspendedTest.java deleted file mode 100644 index 631c357f28e..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ExternalRequestNotSuspendedTest.java +++ /dev/null @@ -1,186 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpExchange; -import org.eclipse.jetty.http.HttpMethods; -import org.eclipse.jetty.io.ByteArrayBuffer; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPListener; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.rhttp.gateway.ExternalRequest; -import org.eclipse.jetty.rhttp.gateway.Gateway; -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.rhttp.gateway.StandardGateway; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - - -/** - * @version $Revision$ $Date$ - */ -public class ExternalRequestNotSuspendedTest extends TestCase -{ - public void testExternalRequestNotSuspended() throws Exception - { - final CountDownLatch respondLatch = new CountDownLatch(1); - final CountDownLatch suspendLatch = new CountDownLatch(1); - final AtomicBoolean suspended = new AtomicBoolean(true); - GatewayServer server = new GatewayServer() - { - @Override - protected Gateway createGateway() - { - StandardGateway gateway = new StandardGateway() - { - @Override - public ExternalRequest newExternalRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException - { - return new SlowToSuspendExternalRequest(super.newExternalRequest(httpRequest, httpResponse), respondLatch, suspendLatch, suspended); - } - }; - return gateway; - } - }; - SelectChannelConnector connector = new SelectChannelConnector(); - server.addConnector(connector); - server.start(); - try - { - Address address = new Address("localhost", connector.getLocalPort()); - - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - try - { - String targetId = "1"; - final RHTTPClient client = new JettyClient(httpClient, address, server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, targetId); - final AtomicReference exception = new AtomicReference(); - client.addListener(new RHTTPListener() - { - public void onRequest(RHTTPRequest request) - { - try - { - RHTTPResponse response = new RHTTPResponse(request.getId(), 200, "OK", new HashMap(), request.getBody()); - client.deliver(response); - } - catch (Exception x) - { - exception.set(x); - } - } - }); - - client.connect(); - try - { - // Make a request to the gateway and check response - ContentExchange exchange = new ContentExchange(true); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(address); - exchange.setURI(server.getContext().getContextPath()+GatewayServer.DFT_EXT_PATH + "/" + URLEncoder.encode(targetId, "UTF-8")); - String requestContent = "body"; - exchange.setRequestContent(new ByteArrayBuffer(requestContent.getBytes("UTF-8"))); - httpClient.send(exchange); - - int status = exchange.waitForDone(); - assertEquals(HttpExchange.STATUS_COMPLETED, status); - assertEquals(HttpServletResponse.SC_OK, exchange.getResponseStatus()); - assertNull(exception.get()); - - suspendLatch.await(); - assertFalse(suspended.get()); - } - finally - { - client.disconnect(); - } - } - finally - { - httpClient.stop(); - } - } - finally - { - server.stop(); - } - } - - private class SlowToSuspendExternalRequest implements ExternalRequest - { - private final ExternalRequest delegate; - private final CountDownLatch respondLatch; - private final CountDownLatch suspendLatch; - private final AtomicBoolean suspended; - - private SlowToSuspendExternalRequest(ExternalRequest delegate, CountDownLatch respondLatch, CountDownLatch suspendLatch, AtomicBoolean suspended) - { - this.delegate = delegate; - this.respondLatch = respondLatch; - this.suspendLatch = suspendLatch; - this.suspended = suspended; - } - - public boolean suspend() - { - try - { - respondLatch.await(); - boolean result = delegate.suspend(); - suspended.set(result); - suspendLatch.countDown(); - return result; - } - catch (InterruptedException x) - { - throw new AssertionError(x); - } - } - - public void respond(RHTTPResponse response) throws IOException - { - delegate.respond(response); - respondLatch.countDown(); - } - - public RHTTPRequest getRequest() - { - return delegate.getRequest(); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ExternalTimeoutTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ExternalTimeoutTest.java deleted file mode 100644 index fba9334b6f7..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/ExternalTimeoutTest.java +++ /dev/null @@ -1,126 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.concurrent.atomic.AtomicReference; - -import javax.servlet.http.HttpServletResponse; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpExchange; -import org.eclipse.jetty.http.HttpMethods; -import org.eclipse.jetty.io.ByteArrayBuffer; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPListener; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.rhttp.gateway.StandardGateway; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - - -/** - * @version $Revision$ $Date$ - */ -public class ExternalTimeoutTest extends TestCase -{ - public void testExternalTimeout() throws Exception - { - GatewayServer server = new GatewayServer(); - SelectChannelConnector connector = new SelectChannelConnector(); - server.addConnector(connector); - final long externalTimeout = 5000L; - ((StandardGateway)server.getGateway()).setExternalTimeout(externalTimeout); - server.start(); - try - { - Address address = new Address("localhost", connector.getLocalPort()); - - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - try - { - String targetId = "1"; - final RHTTPClient client = new JettyClient(httpClient, address, server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, targetId); - final AtomicReference requestId = new AtomicReference(); - final AtomicReference exceptionRef = new AtomicReference(); - client.addListener(new RHTTPListener() - { - public void onRequest(RHTTPRequest request) - { - try - { - // Save the request id - requestId.set(request.getId()); - - // Wait until external timeout expires - Thread.sleep(externalTimeout + 1000L); - RHTTPResponse response = new RHTTPResponse(request.getId(), 200, "OK", new HashMap(), request.getBody()); - client.deliver(response); - } - catch (Exception x) - { - exceptionRef.set(x); - } - } - }); - - client.connect(); - try - { - // Make a request to the gateway and check response - ContentExchange exchange = new ContentExchange(true); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(address); - exchange.setURI(server.getContext().getContextPath()+GatewayServer.DFT_EXT_PATH + "/" + URLEncoder.encode(targetId, "UTF-8")); - String requestContent = "body"; - exchange.setRequestContent(new ByteArrayBuffer(requestContent.getBytes("UTF-8"))); - httpClient.send(exchange); - - int status = exchange.waitForDone(); - assertEquals(HttpExchange.STATUS_COMPLETED, status); - assertEquals(HttpServletResponse.SC_GATEWAY_TIMEOUT, exchange.getResponseStatus()); - assertNull(exceptionRef.get()); - - assertNull(server.getGateway().removeExternalRequest(requestId.get())); - } - finally - { - client.disconnect(); - } - } - finally - { - httpClient.stop(); - } - } - finally - { - server.stop(); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayEchoServer.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayEchoServer.java deleted file mode 100644 index 769eb3f0d0f..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayEchoServer.java +++ /dev/null @@ -1,109 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.util.HashMap; - -import javax.servlet.http.HttpServletRequest; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPListener; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.rhttp.gateway.TargetIdRetriever; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - - -/** - * @version $Revision$ $Date$ - */ -public class GatewayEchoServer -{ - private volatile GatewayServer server; - private volatile Address address; - private volatile String uri; - private volatile HttpClient httpClient; - private volatile RHTTPClient client; - - public void start() throws Exception - { - server = new GatewayServer(); - Connector connector = new SelectChannelConnector(); - server.addConnector(connector); - server.setTargetIdRetriever(new EchoTargetIdRetriever()); - server.start(); - server.dumpStdErr(); - address = new Address("localhost", connector.getLocalPort()); - uri = server.getContext().getContextPath()+GatewayServer.DFT_EXT_PATH; - - httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - - client = new JettyClient(httpClient, new Address("localhost", connector.getLocalPort()), server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, "echo"); - client.addListener(new EchoListener(client)); - client.connect(); - } - - public void stop() throws Exception - { - client.disconnect(); - httpClient.stop(); - server.stop(); - } - - public Address getAddress() - { - return address; - } - - public String getURI() - { - return uri; - } - - public static class EchoTargetIdRetriever implements TargetIdRetriever - { - public String retrieveTargetId(HttpServletRequest httpRequest) - { - return "echo"; - } - } - - private static class EchoListener implements RHTTPListener - { - private final RHTTPClient client; - - public EchoListener(RHTTPClient client) - { - this.client = client; - } - - public void onRequest(RHTTPRequest request) throws Exception - { - RHTTPResponse response = new RHTTPResponse(request.getId(), 200, "OK", new HashMap(), request.getBody()); - client.deliver(response); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayEchoTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayEchoTest.java deleted file mode 100644 index 103c1aa3515..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayEchoTest.java +++ /dev/null @@ -1,77 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import javax.servlet.http.HttpServletResponse; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpExchange; -import org.eclipse.jetty.http.HttpMethods; -import org.eclipse.jetty.io.ByteArrayBuffer; - -/** - * @version $Revision$ $Date$ - */ -public class GatewayEchoTest extends TestCase -{ - /** - * Tests that the basic functionality of the gateway works, - * by issuing a request and by replying with the same body. - * - * @throws Exception in case of test exceptions - */ - public void testEcho() throws Exception - { - GatewayEchoServer server = new GatewayEchoServer(); - server.start(); - try - { - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - try - { - // Make a request to the gateway and check response - ContentExchange exchange = new ContentExchange(true); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(server.getAddress()); - exchange.setURI(server.getURI() + "/"); - String requestBody = "body"; - exchange.setRequestContent(new ByteArrayBuffer(requestBody.getBytes("UTF-8"))); - httpClient.send(exchange); - int status = exchange.waitForDone(); - assertEquals(HttpExchange.STATUS_COMPLETED, status); - assertEquals(HttpServletResponse.SC_OK, exchange.getResponseStatus()); - String responseContent = exchange.getResponseContent(); - assertEquals(responseContent, requestBody); - } - finally - { - httpClient.stop(); - } - } - finally - { - server.stop(); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayLoadTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayLoadTest.java deleted file mode 100644 index c5526757c33..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayLoadTest.java +++ /dev/null @@ -1,202 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import javax.servlet.http.HttpServletResponse; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.http.HttpMethods; -import org.eclipse.jetty.io.ByteArrayBuffer; - -/** - * @version $Revision$ $Date$ - */ -public class GatewayLoadTest extends TestCase -{ - private final ConcurrentMap latencies = new ConcurrentHashMap(); - private final AtomicLong responses = new AtomicLong(0L); - private final AtomicLong failures = new AtomicLong(0L); - private final AtomicLong minLatency = new AtomicLong(Long.MAX_VALUE); - private final AtomicLong maxLatency = new AtomicLong(0L); - private final AtomicLong totLatency = new AtomicLong(0L); - - public void testEcho() throws Exception - { - GatewayEchoServer server = new GatewayEchoServer(); - server.start(); - - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - - String uri = server.getURI() + "/"; - - char[] chars = new char[1024]; - Arrays.fill(chars, 'x'); - String requestBody = new String(chars); - - int count = 1000; - CountDownLatch latch = new CountDownLatch(count); - for (int i = 0; i < count; ++i) - { - GatewayLoadTestExchange exchange = new GatewayLoadTestExchange(latch); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(server.getAddress()); - exchange.setURI(uri + i); - exchange.setRequestContent(new ByteArrayBuffer(requestBody.getBytes("UTF-8"))); - exchange.setStartNanos(System.nanoTime()); - httpClient.send(exchange); - Thread.sleep(5); - } - latch.await(); - printLatencies(count); - assertEquals(count, responses.get() + failures.get()); - } - - private void updateLatencies(long start, long end) - { - long latency = end - start; - - // Update the latencies using a non-blocking algorithm - long oldMinLatency = minLatency.get(); - while (latency < oldMinLatency) - { - if (minLatency.compareAndSet(oldMinLatency, latency)) break; - oldMinLatency = minLatency.get(); - } - long oldMaxLatency = maxLatency.get(); - while (latency > oldMaxLatency) - { - if (maxLatency.compareAndSet(oldMaxLatency, latency)) break; - oldMaxLatency = maxLatency.get(); - } - totLatency.addAndGet(latency); - - latencies.putIfAbsent(latency, new AtomicLong(0L)); - latencies.get(latency).incrementAndGet(); - } - - public void printLatencies(long expectedCount) - { - if (latencies.size() > 1) - { - long maxLatencyBucketFrequency = 0L; - long[] latencyBucketFrequencies = new long[20]; - long latencyRange = maxLatency.get() - minLatency.get(); - for (Iterator> entries = latencies.entrySet().iterator(); entries.hasNext();) - { - Map.Entry entry = entries.next(); - long latency = entry.getKey(); - Long bucketIndex = (latency - minLatency.get()) * latencyBucketFrequencies.length / latencyRange; - int index = bucketIndex.intValue() == latencyBucketFrequencies.length ? latencyBucketFrequencies.length - 1 : bucketIndex.intValue(); - long value = entry.getValue().get(); - latencyBucketFrequencies[index] += value; - if (latencyBucketFrequencies[index] > maxLatencyBucketFrequency) maxLatencyBucketFrequency = latencyBucketFrequencies[index]; - entries.remove(); - } - - System.out.println("Messages - Latency Distribution Curve (X axis: Frequency, Y axis: Latency):"); - for (int i = 0; i < latencyBucketFrequencies.length; i++) - { - long latencyBucketFrequency = latencyBucketFrequencies[i]; - int value = Math.round(latencyBucketFrequency * (float) latencyBucketFrequencies.length / maxLatencyBucketFrequency); - if (value == latencyBucketFrequencies.length) value = value - 1; - for (int j = 0; j < value; ++j) System.out.print(" "); - System.out.print("@"); - for (int j = value + 1; j < latencyBucketFrequencies.length; ++j) System.out.print(" "); - System.out.print(" _ "); - System.out.print(TimeUnit.NANOSECONDS.toMillis((latencyRange * (i + 1) / latencyBucketFrequencies.length) + minLatency.get())); - System.out.print(" (" + latencyBucketFrequency + ")"); - System.out.println(" ms"); - } - } - - long responseCount = responses.get(); - System.out.print("Messages success/failed/expected = "); - System.out.print(responseCount); - System.out.print("/"); - System.out.print(failures.get()); - System.out.print("/"); - System.out.print(expectedCount); - System.out.print(" - Latency min/ave/max = "); - System.out.print(TimeUnit.NANOSECONDS.toMillis(minLatency.get()) + "/"); - System.out.print(responseCount == 0 ? "-/" : TimeUnit.NANOSECONDS.toMillis(totLatency.get() / responseCount) + "/"); - System.out.println(TimeUnit.NANOSECONDS.toMillis(maxLatency.get()) + " ms"); - } - - private class GatewayLoadTestExchange extends ContentExchange - { - private final CountDownLatch latch; - private volatile long start; - - private GatewayLoadTestExchange(CountDownLatch latch) - { - super(true); - this.latch = latch; - } - - @Override - protected void onResponseComplete() throws IOException - { - if (getResponseStatus() == HttpServletResponse.SC_OK) - { - long end = System.nanoTime(); - responses.incrementAndGet(); - updateLatencies(start, end); - } - else - { - failures.incrementAndGet(); - } - latch.countDown(); - } - - @Override - protected void onException(Throwable throwable) - { - failures.incrementAndGet(); - latch.countDown(); - } - - @Override - protected void onExpire() - { - failures.incrementAndGet(); - latch.countDown(); - } - - public void setStartNanos(long value) - { - start = value; - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayTimeoutTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayTimeoutTest.java deleted file mode 100644 index 504e4f4207b..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/GatewayTimeoutTest.java +++ /dev/null @@ -1,130 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.concurrent.atomic.AtomicReference; - -import javax.servlet.http.HttpServletResponse; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpExchange; -import org.eclipse.jetty.http.HttpMethods; -import org.eclipse.jetty.io.ByteArrayBuffer; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.client.RHTTPListener; -import org.eclipse.jetty.rhttp.client.RHTTPRequest; -import org.eclipse.jetty.rhttp.client.RHTTPResponse; -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.rhttp.gateway.StandardGateway; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - - -/** - * @version $Revision$ $Date$ - */ -public class GatewayTimeoutTest extends TestCase -{ - /** - * Tests a forwarded request that lasts longer than the gateway timeout. - * The gateway client will perform 2 long polls before the forwarded request's response is returned. - * - * @throws Exception in case of test exceptions - */ - public void testGatewayTimeout() throws Exception - { - GatewayServer server = new GatewayServer(); - Connector connector = new SelectChannelConnector(); - server.addConnector(connector); - final long gatewayTimeout = 5000L; - ((StandardGateway)server.getGateway()).setGatewayTimeout(gatewayTimeout); - final long externalTimeout = gatewayTimeout * 2; - ((StandardGateway)server.getGateway()).setExternalTimeout(externalTimeout); - server.start(); - try - { - Address address = new Address("localhost", connector.getLocalPort()); - - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - try - { - String targetId = "1"; - final RHTTPClient client = new JettyClient(httpClient, address, server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, targetId); - final AtomicReference exceptionRef = new AtomicReference(); - client.addListener(new RHTTPListener() - { - public void onRequest(RHTTPRequest request) - { - try - { - // Wait until gateway timeout expires - Thread.sleep(gatewayTimeout + 1000L); - RHTTPResponse response = new RHTTPResponse(request.getId(), 200, "OK", new HashMap(), request.getBody()); - client.deliver(response); - } - catch (Exception x) - { - exceptionRef.set(x); - } - } - }); - client.connect(); - try - { - // Make a request to the gateway and check response - ContentExchange exchange = new ContentExchange(true); - exchange.setMethod(HttpMethods.POST); - exchange.setAddress(address); - exchange.setURI(server.getContext().getContextPath()+GatewayServer.DFT_EXT_PATH + "/" + URLEncoder.encode(targetId, "UTF-8")); - String requestContent = "body"; - exchange.setRequestContent(new ByteArrayBuffer(requestContent.getBytes("UTF-8"))); - httpClient.send(exchange); - - int status = exchange.waitForDone(); - assertEquals(HttpExchange.STATUS_COMPLETED, status); - assertEquals(HttpServletResponse.SC_OK, exchange.getResponseStatus()); - assertNull(exceptionRef.get()); - String responseContent = exchange.getResponseContent(); - assertEquals(responseContent, requestContent); - } - finally - { - client.disconnect(); - } - } - finally - { - httpClient.stop(); - } - } - finally - { - server.stop(); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/HandshakeClientTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/HandshakeClientTest.java deleted file mode 100644 index b2e4ca80948..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/HandshakeClientTest.java +++ /dev/null @@ -1,75 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import junit.framework.TestCase; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.rhttp.client.JettyClient; -import org.eclipse.jetty.rhttp.client.RHTTPClient; -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.rhttp.gateway.StandardGateway; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - - -/** - * @version $Revision$ $Date$ - */ -public class HandshakeClientTest extends TestCase -{ - public void testConnectReturnsImmediately() throws Exception - { - GatewayServer server = new GatewayServer(); - SelectChannelConnector connector = new SelectChannelConnector(); - server.addConnector(connector); - long gwt=5000L; - ((StandardGateway)server.getGateway()).setGatewayTimeout(gwt); - server.start(); - try - { - HttpClient httpClient = new HttpClient(); - httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); - httpClient.start(); - try - { - RHTTPClient client = new JettyClient(httpClient, new Address("localhost", connector.getLocalPort()), server.getContext().getContextPath()+GatewayServer.DFT_CONNECT_PATH, "test1"); - long start = System.currentTimeMillis(); - client.connect(); - try - { - long end = System.currentTimeMillis(); - assertTrue(end - start < gwt / 2); - } - finally - { - client.disconnect(); - } - } - finally - { - httpClient.stop(); - } - } - finally - { - server.stop(); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/HostTargetIdRetrieverTest.java b/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/HostTargetIdRetrieverTest.java deleted file mode 100644 index 8da0206139a..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/java/org/eclipse/jetty/rhttp/gateway/HostTargetIdRetrieverTest.java +++ /dev/null @@ -1,107 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.gateway; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -import javax.servlet.http.HttpServletRequest; - -import org.eclipse.jetty.rhttp.gateway.HostTargetIdRetriever; - -import junit.framework.TestCase; - -/** - * @version $Revision$ $Date$ - */ -public class HostTargetIdRetrieverTest extends TestCase -{ - public void testHostTargetIdRetrieverNoSuffix() - { - String host = "test"; - Class klass = HttpServletRequest.class; - HttpServletRequest request = (HttpServletRequest)Proxy.newProxyInstance(klass.getClassLoader(), new Class[]{klass}, new Request(host)); - - HostTargetIdRetriever retriever = new HostTargetIdRetriever(null); - String result = retriever.retrieveTargetId(request); - - assertEquals(host, result); - } - - public void testHostTargetIdRetrieverWithSuffix() - { - String suffix = ".rhttp.example.com"; - String host = "test"; - Class klass = HttpServletRequest.class; - HttpServletRequest request = (HttpServletRequest)Proxy.newProxyInstance(klass.getClassLoader(), new Class[]{klass}, new Request(host + suffix)); - - HostTargetIdRetriever retriever = new HostTargetIdRetriever(suffix); - String result = retriever.retrieveTargetId(request); - - assertEquals(host, result); - } - - public void testHostTargetIdRetrieverWithSuffixAndPort() - { - String suffix = ".rhttp.example.com"; - String host = "test"; - Class klass = HttpServletRequest.class; - HttpServletRequest request = (HttpServletRequest)Proxy.newProxyInstance(klass.getClassLoader(), new Class[]{klass}, new Request(host + suffix + ":8080")); - - HostTargetIdRetriever retriever = new HostTargetIdRetriever(suffix); - String result = retriever.retrieveTargetId(request); - - assertEquals(host, result); - } - - public void testHostTargetIdRetrieverNullHost() - { - Class klass = HttpServletRequest.class; - HttpServletRequest request = (HttpServletRequest)Proxy.newProxyInstance(klass.getClassLoader(), new Class[]{klass}, new Request(null)); - - HostTargetIdRetriever retriever = new HostTargetIdRetriever(".rhttp.example.com"); - String result = retriever.retrieveTargetId(request); - - assertNull(result); - } - - private static class Request implements InvocationHandler - { - private final String host; - - private Request(String host) - { - this.host = host; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable - { - if ("getHeader".equals(method.getName())) - { - if (args.length == 1 && "Host".equals(args[0])) - { - return host; - } - } - return null; - } - } - -} diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/test/resources/log4j.properties b/jetty-rhttp/jetty-rhttp-gateway/src/test/resources/log4j.properties deleted file mode 100644 index 8e6eddb704b..00000000000 --- a/jetty-rhttp/jetty-rhttp-gateway/src/test/resources/log4j.properties +++ /dev/null @@ -1,13 +0,0 @@ -# LOG4J levels: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -# -log4j.rootLogger=ALL,CONSOLE - -log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender -#log4j.appender.CONSOLE.threshold=INFO -log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout -#log4j.appender.CONSOLE.layout.ConversionPattern=%d %t [%5p][%c{1}] %m%n -log4j.appender.CONSOLE.layout.ConversionPattern=%d [%5p][%c] %m%n - -# Level tuning -log4j.logger.org.eclipse.jetty=INFO -log4j.logger.org.mortbay.jetty.rhttp=INFO diff --git a/jetty-rhttp/jetty-rhttp-loadtest/pom.xml b/jetty-rhttp/jetty-rhttp-loadtest/pom.xml deleted file mode 100644 index bd36d4ebdec..00000000000 --- a/jetty-rhttp/jetty-rhttp-loadtest/pom.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - org.eclipse.jetty.rhttp - jetty-rhttp-project - 9.0.0-SNAPSHOT - - - 4.0.0 - reverse-http-loadtest - jar - Jetty :: Reverse HTTP :: Load Test - - - - loader - - true - - - - - org.codehaus.mojo - exec-maven-plugin - - org.eclipse.jetty.rhttp.loadtest.Loader - runtime - - - - - - - server - - - - org.codehaus.mojo - exec-maven-plugin - - org.eclipse.jetty.rhttp.loadtest.Server - runtime - - - - - - - - - - org.eclipse.jetty - reverse-http-gateway - ${project.version} - - - - diff --git a/jetty-rhttp/jetty-rhttp-loadtest/src/main/java/org/eclipse/jetty/rhttp/loadtest/Loader.java b/jetty-rhttp/jetty-rhttp-loadtest/src/main/java/org/eclipse/jetty/rhttp/loadtest/Loader.java deleted file mode 100644 index 50dbd283d6c..00000000000 --- a/jetty-rhttp/jetty-rhttp-loadtest/src/main/java/org/eclipse/jetty/rhttp/loadtest/Loader.java +++ /dev/null @@ -1,429 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.loadtest; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import org.eclipse.jetty.client.Address; -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.io.ByteArrayBuffer; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.mortbay.jetty.rhttp.client.RHTTPClient; -import org.mortbay.jetty.rhttp.client.JettyClient; -import org.mortbay.jetty.rhttp.client.RHTTPListener; -import org.mortbay.jetty.rhttp.client.RHTTPRequest; -import org.mortbay.jetty.rhttp.client.RHTTPResponse; - -/** - * @version $Revision$ $Date$ - */ -public class Loader -{ - private final List clients = new ArrayList(); - private final AtomicLong start = new AtomicLong(); - private final AtomicLong end = new AtomicLong(); - private final AtomicLong responses = new AtomicLong(); - private final AtomicLong failures = new AtomicLong(); - private final AtomicLong minLatency = new AtomicLong(); - private final AtomicLong maxLatency = new AtomicLong(); - private final AtomicLong totLatency = new AtomicLong(); - private final ConcurrentMap latencies = new ConcurrentHashMap(); - private final String nodeName; - - public static void main(String[] args) throws Exception - { - String nodeName = ""; - if (args.length > 0) - nodeName = args[0]; - - Loader loader = new Loader(nodeName); - loader.run(); - } - - public Loader(String nodeName) - { - this.nodeName = nodeName; - } - - private void run() throws Exception - { - HttpClient httpClient = new HttpClient(); - httpClient.setMaxConnectionsPerAddress(40000); - QueuedThreadPool threadPool = new QueuedThreadPool(); - threadPool.setMaxThreads(500); - threadPool.setDaemon(true); - httpClient.setThreadPool(threadPool); - httpClient.setIdleTimeout(5000); - httpClient.start(); - - Random random = new Random(); - - BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); - - System.err.print("server [localhost]: "); - String value = console.readLine().trim(); - if (value.length() == 0) - value = "localhost"; - String host = value; - - System.err.print("port [8080]: "); - value = console.readLine().trim(); - if (value.length() == 0) - value = "8080"; - int port = Integer.parseInt(value); - - System.err.print("context []: "); - value = console.readLine().trim(); - if (value.length() == 0) - value = ""; - String context = value; - - System.err.print("external path [/]: "); - value = console.readLine().trim(); - if (value.length() == 0) - value = "/"; - String externalPath = value; - - System.err.print("gateway path [/__gateway]: "); - value = console.readLine().trim(); - if (value.length() == 0) - value = "/__gateway"; - String gatewayPath = value; - - int clients = 100; - int batchCount = 1000; - int batchSize = 5; - long batchPause = 5; - int requestSize = 50; - - while (true) - { - System.err.println("-----"); - - System.err.print("clients [" + clients + "]: "); - value = console.readLine(); - if (value == null) - break; - value = value.trim(); - if (value.length() == 0) - value = "" + clients; - clients = Integer.parseInt(value); - - System.err.println("Waiting for clients to be ready..."); - - Address gatewayAddress = new Address(host, port); - String gatewayURI = context + gatewayPath; - - // Create or remove the necessary clients - int currentClients = this.clients.size(); - if (currentClients < clients) - { - for (int i = 0; i < clients - currentClients; ++i) - { - final RHTTPClient client = new JettyClient(httpClient, gatewayAddress, gatewayURI, nodeName + (currentClients + i)); - client.addListener(new EchoListener(client)); - client.connect(); - this.clients.add(client); - - // Give some time to the server to accept connections and - // reply to handshakes and connects - if (i % 10 == 0) - { - Thread.sleep(100); - } - } - } - else if (currentClients > clients) - { - for (int i = 0; i < currentClients - clients; ++i) - { - RHTTPClient client = this.clients.remove(currentClients - i - 1); - client.disconnect(); - } - } - - System.err.println("Clients ready"); - - currentClients = this.clients.size(); - if (currentClients > 0) - { - System.err.print("batch count [" + batchCount + "]: "); - value = console.readLine().trim(); - if (value.length() == 0) - value = "" + batchCount; - batchCount = Integer.parseInt(value); - - System.err.print("batch size [" + batchSize + "]: "); - value = console.readLine().trim(); - if (value.length() == 0) - value = "" + batchSize; - batchSize = Integer.parseInt(value); - - System.err.print("batch pause [" + batchPause + "]: "); - value = console.readLine().trim(); - if (value.length() == 0) - value = "" + batchPause; - batchPause = Long.parseLong(value); - - System.err.print("request size [" + requestSize + "]: "); - value = console.readLine().trim(); - if (value.length() == 0) - value = "" + requestSize; - requestSize = Integer.parseInt(value); - String requestBody = ""; - for (int i = 0; i < requestSize; i++) - requestBody += "x"; - - String externalURL = "http://" + host + ":" + port + context + externalPath; - if (!externalURL.endsWith("/")) - externalURL += "/"; - - reset(); - - long start = System.nanoTime(); - long expected = 0; - for (int i = 0; i < batchCount; ++i) - { - for (int j = 0; j < batchSize; ++j) - { - int clientIndex = random.nextInt(this.clients.size()); - RHTTPClient client = this.clients.get(clientIndex); - String targetId = client.getTargetId(); - String url = externalURL + targetId; - - ExternalExchange exchange = new ExternalExchange(); - exchange.setMethod("GET"); - exchange.setURL(url); - exchange.setRequestContent(new ByteArrayBuffer(requestBody, "UTF-8")); - exchange.send(httpClient); - ++expected; - } - - if (batchPause > 0) - Thread.sleep(batchPause); - } - long end = System.nanoTime(); - long elapsedNanos = end - start; - if (elapsedNanos > 0) - { - System.err.print("Messages - Elapsed | Rate = "); - System.err.print(TimeUnit.NANOSECONDS.toMillis(elapsedNanos)); - System.err.print(" ms | "); - System.err.print(expected * 1000 * 1000 * 1000 / elapsedNanos); - System.err.println(" requests/s "); - } - - waitForResponses(expected); - printReport(expected); - } - } - } - - private void reset() - { - start.set(0L); - end.set(0L); - responses.set(0L); - failures.set(0L); - minLatency.set(Long.MAX_VALUE); - maxLatency.set(0L); - totLatency.set(0L); - } - - private void updateLatencies(long start, long end) - { - long latency = end - start; - - // Update the latencies using a non-blocking algorithm - long oldMinLatency = minLatency.get(); - while (latency < oldMinLatency) - { - if (minLatency.compareAndSet(oldMinLatency, latency)) break; - oldMinLatency = minLatency.get(); - } - long oldMaxLatency = maxLatency.get(); - while (latency > oldMaxLatency) - { - if (maxLatency.compareAndSet(oldMaxLatency, latency)) break; - oldMaxLatency = maxLatency.get(); - } - totLatency.addAndGet(latency); - - latencies.putIfAbsent(latency, new AtomicLong(0L)); - latencies.get(latency).incrementAndGet(); - } - - private boolean waitForResponses(long expected) throws InterruptedException - { - long arrived = responses.get() + failures.get(); - long lastArrived = 0; - int maxRetries = 20; - int retries = maxRetries; - while (arrived < expected) - { - System.err.println("Waiting for responses to arrive " + arrived + "/" + expected); - Thread.sleep(500); - if (lastArrived == arrived) - { - --retries; - if (retries == 0) break; - } - else - { - lastArrived = arrived; - retries = maxRetries; - } - arrived = responses.get() + failures.get(); - } - if (arrived < expected) - { - System.err.println("Interrupting wait for responses " + arrived + "/" + expected); - return false; - } - else - { - System.err.println("All responses arrived " + arrived + "/" + expected); - return true; - } - } - - public void printReport(long expectedCount) - { - long responseCount = responses.get() + failures.get(); - System.err.print("Messages - Success/Failures/Expected = "); - System.err.print(responses.get()); - System.err.print("/"); - System.err.print(failures.get()); - System.err.print("/"); - System.err.println(expectedCount); - - long elapsedNanos = end.get() - start.get(); - if (elapsedNanos > 0) - { - System.err.print("Messages - Elapsed | Rate = "); - System.err.print(TimeUnit.NANOSECONDS.toMillis(elapsedNanos)); - System.err.print(" ms | "); - System.err.print(responseCount * 1000 * 1000 * 1000 / elapsedNanos); - System.err.println(" responses/s "); - } - - if (latencies.size() > 1) - { - long maxLatencyBucketFrequency = 0L; - long[] latencyBucketFrequencies = new long[20]; - long latencyRange = maxLatency.get() - minLatency.get(); - for (Iterator> entries = latencies.entrySet().iterator(); entries.hasNext();) - { - Map.Entry entry = entries.next(); - long latency = entry.getKey(); - Long bucketIndex = (latency - minLatency.get()) * latencyBucketFrequencies.length / latencyRange; - int index = bucketIndex.intValue() == latencyBucketFrequencies.length ? latencyBucketFrequencies.length - 1 : bucketIndex.intValue(); - long value = entry.getValue().get(); - latencyBucketFrequencies[index] += value; - if (latencyBucketFrequencies[index] > maxLatencyBucketFrequency) maxLatencyBucketFrequency = latencyBucketFrequencies[index]; - entries.remove(); - } - - System.err.println("Messages - Latency Distribution Curve (X axis: Frequency, Y axis: Latency):"); - for (int i = 0; i < latencyBucketFrequencies.length; i++) - { - long latencyBucketFrequency = latencyBucketFrequencies[i]; - int value = Math.round(latencyBucketFrequency * (float) latencyBucketFrequencies.length / maxLatencyBucketFrequency); - if (value == latencyBucketFrequencies.length) value = value - 1; - for (int j = 0; j < value; ++j) System.err.print(" "); - System.err.print("@"); - for (int j = value + 1; j < latencyBucketFrequencies.length; ++j) System.err.print(" "); - System.err.print(" _ "); - System.err.print(TimeUnit.NANOSECONDS.toMillis((latencyRange * (i + 1) / latencyBucketFrequencies.length) + minLatency.get())); - System.err.println(" ms (" + latencyBucketFrequency + ")"); - } - } - - System.err.print("Messages - Latency Min/Ave/Max = "); - System.err.print(TimeUnit.NANOSECONDS.toMillis(minLatency.get()) + "/"); - System.err.print(responseCount == 0 ? "-/" : TimeUnit.NANOSECONDS.toMillis(totLatency.get() / responseCount) + "/"); - System.err.println(TimeUnit.NANOSECONDS.toMillis(maxLatency.get()) + " ms"); - } - - private class ExternalExchange extends ContentExchange - { - private volatile long sendTime; - - private ExternalExchange() - { - super(true); - } - - private void send(HttpClient httpClient) throws IOException - { - this.sendTime = System.nanoTime(); - httpClient.send(this); - } - - @Override - protected void onResponseComplete() throws IOException - { - if (getResponseStatus() == 200) - responses.incrementAndGet(); - else - failures.incrementAndGet(); - - long arrivalTime = System.nanoTime(); - if (start.get() == 0L) - start.set(arrivalTime); - end.set(arrivalTime); - updateLatencies(sendTime, arrivalTime); - } - - @Override - protected void onException(Throwable x) - { - failures.incrementAndGet(); - } - } - - private static class EchoListener implements RHTTPListener - { - private final RHTTPClient client; - - public EchoListener(RHTTPClient client) - { - this.client = client; - } - - public void onRequest(RHTTPRequest request) throws Exception - { - RHTTPResponse response = new RHTTPResponse(request.getId(), 200, "OK", new HashMap(), request.getBody()); - client.deliver(response); - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-loadtest/src/main/java/org/eclipse/jetty/rhttp/loadtest/Server.java b/jetty-rhttp/jetty-rhttp-loadtest/src/main/java/org/eclipse/jetty/rhttp/loadtest/Server.java deleted file mode 100644 index 57016cf649e..00000000000 --- a/jetty-rhttp/jetty-rhttp-loadtest/src/main/java/org/eclipse/jetty/rhttp/loadtest/Server.java +++ /dev/null @@ -1,69 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.rhttp.loadtest; - -import org.eclipse.jetty.rhttp.gateway.GatewayServer; -import org.eclipse.jetty.rhttp.gateway.StandardTargetIdRetriever; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.nio.SelectChannelConnector; - -/** - * @version $Revision$ $Date$ - */ -public class Server -{ - public static void main(String[] args) throws Exception - { - int port = 8080; - if (args.length > 0) - port = Integer.parseInt(args[0]); - - GatewayServer server = new GatewayServer(); - Connector connector = new SelectChannelConnector(); - connector.setLowResourceMaxIdleTime(connector.getMaxIdleTime()); - connector.setPort(port); - server.addConnector(connector); - server.setTargetIdRetriever(new StandardTargetIdRetriever()); - server.start(); - server.getServer().dumpStdErr(); - Runtime.getRuntime().addShutdownHook(new Shutdown(server)); - } - - private static class Shutdown extends Thread - { - private final GatewayServer server; - - public Shutdown(GatewayServer server) - { - this.server = server; - } - - @Override - public void run() - { - try - { - server.stop(); - } - catch (Exception ignored) - { - } - } - } -} diff --git a/jetty-rhttp/jetty-rhttp-loadtest/src/main/resources/log4j.properties b/jetty-rhttp/jetty-rhttp-loadtest/src/main/resources/log4j.properties deleted file mode 100644 index 8e6eddb704b..00000000000 --- a/jetty-rhttp/jetty-rhttp-loadtest/src/main/resources/log4j.properties +++ /dev/null @@ -1,13 +0,0 @@ -# LOG4J levels: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -# -log4j.rootLogger=ALL,CONSOLE - -log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender -#log4j.appender.CONSOLE.threshold=INFO -log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout -#log4j.appender.CONSOLE.layout.ConversionPattern=%d %t [%5p][%c{1}] %m%n -log4j.appender.CONSOLE.layout.ConversionPattern=%d [%5p][%c] %m%n - -# Level tuning -log4j.logger.org.eclipse.jetty=INFO -log4j.logger.org.mortbay.jetty.rhttp=INFO diff --git a/jetty-rhttp/pom.xml b/jetty-rhttp/pom.xml deleted file mode 100644 index 0284a0fba0f..00000000000 --- a/jetty-rhttp/pom.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - org.eclipse.jetty - jetty-project - 9.0.0-SNAPSHOT - - - 4.0.0 - org.eclipse.jetty.rhttp - jetty-rhttp-project - pom - Jetty :: Reverse HTTP - - - - - - reverse-http-client - reverse-http-connector - reverse-http-gateway - reverse-http-loadtest - - - - - - org.sonatype.maven.plugin - emma-maven-plugin - - - process-classes - - instrument - - - - - - maven-surefire-plugin - - ${project.build.directory}/generated-classes/emma/classes - - - emma.coverage.out.file - ${project.build.directory}/coverage.ec - - - - - - org.sonatype.maven.plugin - emma4it-maven-plugin - - - report - post-integration-test - - report - - - - - ${project.build.sourceDirectory} - - - - - - - - - - - - - javax.servlet - servlet-api - - - org.eclipse.jetty - jetty-server - ${project.version} - - - org.eclipse.jetty - jetty-client - ${project.version} - - - org.eclipse.jetty - jetty-io - ${project.version} - - - org.eclipse.jetty - jetty-util - ${project.version} - - - org.eclipse.jetty.toolchain - jetty-test-helper - test - - - - -