Loading plugins/org.etsi.mts.tdl.execution.java.runtime/src/org/etsi/mts/tdl/execution/java/adapters/http/HttpSystemAdapter.java +71 −43 Original line number Diff line number Diff line Loading @@ -79,20 +79,23 @@ public class HttpSystemAdapter implements SystemAdapter { public HttpSystemAdapter(Validator validator, Reporter reporter) { this.validator = validator; this.reporter = reporter; this.endpoints.add(new HttpEndpoint(defaultSut, defaultGate, "https://example.com", 0)); this.endpoints.add(new HttpEndpoint("", defaultSut, defaultGate, "https://example.com", "/", 0)); } public void setBaseUri(String baseUri) { getEndpoint(defaultSut, defaultGate).address = baseUri; getEndpoint(null, defaultSut, defaultGate).address = baseUri; getEndpoint(null, defaultSut, defaultGate).baseUri = ""; } public void setEndpoint(String componentName, String gateName, String baseUri, int serverPort) { this.endpoints.add(new HttpEndpoint(componentName, gateName, baseUri, serverPort)); public void setEndpoint(String connectionName, String componentName, String gateName, String address, String baseUri, int serverPort) { this.endpoints.add(new HttpEndpoint(connectionName, componentName, gateName, address, baseUri, serverPort)); } private HttpEndpoint getEndpoint(String componentName, String gateName) { private HttpEndpoint getEndpoint(String connectionName, String componentName, String gateName) { if (connectionName == null) connectionName = ""; for (HttpEndpoint endpoint : this.endpoints) { if (endpoint.componentName.equals(componentName) && endpoint.gateName == gateName) if (endpoint.connectionName.equals(connectionName) && endpoint.componentName.equals(componentName) && endpoint.gateName == gateName) return endpoint; } return null; Loading @@ -111,19 +114,23 @@ public class HttpSystemAdapter implements SystemAdapter { } @Override public void configure(Connection[] connections) { public void configure(Connection[] connections, NamedElement component) { for (Connection connection : connections) { for (GateReference gate : connection.getEndPoints()) { if (gate.getComponentRole() != ComponentInstanceRole.Tester) continue; HttpEndpoint endpoint = this.getEndpoint(gate.getComponent().getName(), gate.getGate().getName()); if (endpoint == null || this.servers.containsKey(endpoint)) if (!gate.getComponent().equals(component)) continue; HttpEndpoint endpoint = this.getEndpoint(connection.getName(), gate.getComponent().getName(), gate.getGate().getName()); if (endpoint == null) continue; if (this.servers.containsKey(endpoint)) throw new RuntimeException("Invalid endpoint configuration (duplicates)."); int serverPort = endpoint.port; try { HttpServer server = HttpServer.create(new InetSocketAddress(serverPort), 0); server.createContext(serverBaseUri, request -> this.handleRequest(request, endpoint, connection)); server.createContext(endpoint.baseUri, request -> this.handleRequest(request, endpoint, connection)); server.setExecutor(null); server.start(); this.servers.put(endpoint, server); Loading Loading @@ -158,20 +165,20 @@ public class HttpSystemAdapter implements SystemAdapter { server.stop(5); } private void handleRequest(HttpExchange request, HttpEndpoint source, Connection connection) throws IOException { private void handleRequest(HttpExchange request, HttpEndpoint target, Connection connection) throws IOException { synchronized (unhandledInputs) { unhandledInputs.add(new HttpInput(null, request, source, connection)); unhandledInputs.add(new HttpInput(null, request, target, connection)); unhandledInputs.notifyAll(); } } private void handleResponse(HttpResponse<String> response, Throwable t, HttpEndpoint source, private void handleResponse(HttpResponse<String> response, Throwable t, HttpEndpoint target, Connection connection) { if (t != null) handleError(t); else { synchronized (unhandledInputs) { unhandledInputs.add(new HttpInput(response, null, source, connection)); unhandledInputs.add(new HttpInput(response, null, target, connection)); unhandledInputs.notifyAll(); } } Loading @@ -179,7 +186,7 @@ public class HttpSystemAdapter implements SystemAdapter { private void handleError(Throwable t) { t.printStackTrace(); reporter.runtimeError(t); reporter.runtimeError(null, t); throw new RuntimeException(t); } Loading Loading @@ -211,16 +218,18 @@ public class HttpSystemAdapter implements SystemAdapter { if (!(data instanceof HttpRequestData) && !(data instanceof HttpResponseData)) throw new RuntimeException("Request/response data in unsupported format"); GateReference sourceGate = null; GateReference target = null; for (GateReference gate : connection.getEndPoints()) if (!gate.getComponent().equals(source)) { target = gate; break; } else { sourceGate = gate; } HttpEndpoint targetEndpoint = this.getEndpoint(target.getComponent().getName(), target.getGate().getName()); HttpEndpoint targetEndpoint = this.getEndpoint(connection.getName(), target.getComponent().getName(), target.getGate().getName()); if (targetEndpoint == null) // Assume default targetEndpoint = this.getEndpoint(defaultSut, defaultGate); targetEndpoint = this.getEndpoint(null, defaultSut, defaultGate); boolean isRequest = data instanceof HttpRequestData; try { Loading Loading @@ -273,20 +282,22 @@ public class HttpSystemAdapter implements SystemAdapter { requestBuilder.uri(uri); // TODO logging reporter.comment("Outgoing (headers): " + httpData.method.toString() + " | " + uri); reporter.comment(source.getName(), "Outgoing (headers): " + httpData.method.toString() + " | " + uri); byte[] body = encodeBody(httpData.body); reporter.comment(source.getName(), "Outgoing (body): " + mapper.writeValueAsString(httpData.body)); requestBuilder.method(httpData.method.toString(), HttpRequest.BodyPublishers.ofByteArray(body)); if (httpData.headers != null) for (HttpHeader header : httpData.headers) requestBuilder.header(header.name, header.value); CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(requestBuilder.build(), HttpResponse.BodyHandlers.ofString(UTF_8)); HttpEndpoint endpoint = targetEndpoint; HttpEndpoint sourceEndpoint = this.getEndpoint(connection.getName(), sourceGate.getComponent().getName(), sourceGate.getGate().getName()); responseFuture .whenCompleteAsync((response, t) -> this.handleResponse(response, t, endpoint, connection)); .whenCompleteAsync((response, t) -> this.handleResponse(response, t, sourceEndpoint, connection)); } else { Loading @@ -306,6 +317,7 @@ public class HttpSystemAdapter implements SystemAdapter { Headers headers = unhandledExchange.getResponseHeaders(); this.applyDefaults(headers); if (httpData.headers != null) for (HttpHeader header : httpData.headers) headers.add(header.name, header.value); Loading @@ -327,7 +339,8 @@ public class HttpSystemAdapter implements SystemAdapter { int length = body.length; // TODO logging reporter.comment("Outgoing (headers): " + httpData.status + " | " + length); reporter.comment(source.getName(), "Outgoing (headers): " + httpData.status + " | length=" + length); reporter.comment(source.getName(), "Outgoing (body): " + mapper.writeValueAsString(httpData.body)); unhandledExchange.sendResponseHeaders(httpData.status, length); Loading @@ -351,7 +364,7 @@ public class HttpSystemAdapter implements SystemAdapter { do { for (HttpInput i : unhandledInputs) if (i.connection.equals(connection)) if (!i.source.componentName.equals(target.getName())) { if (i.target.componentName.equals(target.getName())) { input = i; break; } Loading @@ -371,10 +384,13 @@ public class HttpSystemAdapter implements SystemAdapter { String body = response.body(); // TODO logging reporter.comment("Incoming: " + response.statusCode() + " | " + body); reporter.comment(target.getName(), "Incoming: " + response.statusCode() + " | " + body); try { // This is not provided by HttpResponse expectedHttpData.statusMessage = null; HttpResponseData receivedHttpData = new HttpResponseData(); receivedHttpData.status = response.statusCode(); Map<String, List<String>> headers = response.headers().map(); Loading Loading @@ -411,14 +427,21 @@ public class HttpSystemAdapter implements SystemAdapter { HttpExchange exchange = input.exchange; if (input.body == null) try (InputStream is = exchange.getRequestBody()) { // TODO other encodings Charset cs = StandardCharsets.UTF_8; String body = new String(is.readAllBytes(), cs); input.body = new String(is.readAllBytes(), cs); // TODO logging reporter.comment("Incoming: " + exchange.getRequestMethod() + " | " + body); reporter.comment(target.getName(), "Incoming: " + exchange.getRequestMethod() + " | " + input.body); } catch (IOException e) { handleError(e); } try { HttpRequestData receivedHttpData = new HttpRequestData(); receivedHttpData.uri = exchange.getRequestURI().toString(); Loading @@ -434,14 +457,14 @@ public class HttpSystemAdapter implements SystemAdapter { boolean isReceived = false; if (expected != null) { if (expectedHttpData.body != null) { receivedHttpData.body = decodeBody(body, expectedHttpData.body.getClass()); receivedHttpData.body = decodeBody(input.body, expectedHttpData.body.getClass()); } if (this.validator.matches(expected, received)) { isReceived = true; } } else { receivedHttpData.body = body; receivedHttpData.body = input.body; isReceived = true; } Loading @@ -467,7 +490,6 @@ public class HttpSystemAdapter implements SystemAdapter { } protected byte[] encodeBody(Object body) throws IOException { reporter.comment("Outgoing (body): " + mapper.writeValueAsString(body)); return mapper.writeValueAsBytes(body); } Loading Loading @@ -575,30 +597,36 @@ public class HttpSystemAdapter implements SystemAdapter { class HttpInput { HttpResponse<String> response; HttpExchange exchange; HttpEndpoint source; HttpEndpoint target; Connection connection; public HttpInput(HttpResponse<String> response, HttpExchange exchange, HttpEndpoint source, String body; public HttpInput(HttpResponse<String> response, HttpExchange exchange, HttpEndpoint target, Connection connection) { this.response = response; this.exchange = exchange; this.source = source; this.target = target; this.connection = connection; } } class HttpEndpoint { String connectionName; String componentName; String gateName; String address; String baseUri; int port; public HttpEndpoint(String componentName, String gateName, String address, int port) { public HttpEndpoint(String connectionName, String componentName, String gateName, String address, String baseUri, int port) { super(); this.connectionName = connectionName; this.componentName = componentName; this.gateName = gateName; this.address = address; this.baseUri = baseUri; this.port = port; } } Loading Loading
plugins/org.etsi.mts.tdl.execution.java.runtime/src/org/etsi/mts/tdl/execution/java/adapters/http/HttpSystemAdapter.java +71 −43 Original line number Diff line number Diff line Loading @@ -79,20 +79,23 @@ public class HttpSystemAdapter implements SystemAdapter { public HttpSystemAdapter(Validator validator, Reporter reporter) { this.validator = validator; this.reporter = reporter; this.endpoints.add(new HttpEndpoint(defaultSut, defaultGate, "https://example.com", 0)); this.endpoints.add(new HttpEndpoint("", defaultSut, defaultGate, "https://example.com", "/", 0)); } public void setBaseUri(String baseUri) { getEndpoint(defaultSut, defaultGate).address = baseUri; getEndpoint(null, defaultSut, defaultGate).address = baseUri; getEndpoint(null, defaultSut, defaultGate).baseUri = ""; } public void setEndpoint(String componentName, String gateName, String baseUri, int serverPort) { this.endpoints.add(new HttpEndpoint(componentName, gateName, baseUri, serverPort)); public void setEndpoint(String connectionName, String componentName, String gateName, String address, String baseUri, int serverPort) { this.endpoints.add(new HttpEndpoint(connectionName, componentName, gateName, address, baseUri, serverPort)); } private HttpEndpoint getEndpoint(String componentName, String gateName) { private HttpEndpoint getEndpoint(String connectionName, String componentName, String gateName) { if (connectionName == null) connectionName = ""; for (HttpEndpoint endpoint : this.endpoints) { if (endpoint.componentName.equals(componentName) && endpoint.gateName == gateName) if (endpoint.connectionName.equals(connectionName) && endpoint.componentName.equals(componentName) && endpoint.gateName == gateName) return endpoint; } return null; Loading @@ -111,19 +114,23 @@ public class HttpSystemAdapter implements SystemAdapter { } @Override public void configure(Connection[] connections) { public void configure(Connection[] connections, NamedElement component) { for (Connection connection : connections) { for (GateReference gate : connection.getEndPoints()) { if (gate.getComponentRole() != ComponentInstanceRole.Tester) continue; HttpEndpoint endpoint = this.getEndpoint(gate.getComponent().getName(), gate.getGate().getName()); if (endpoint == null || this.servers.containsKey(endpoint)) if (!gate.getComponent().equals(component)) continue; HttpEndpoint endpoint = this.getEndpoint(connection.getName(), gate.getComponent().getName(), gate.getGate().getName()); if (endpoint == null) continue; if (this.servers.containsKey(endpoint)) throw new RuntimeException("Invalid endpoint configuration (duplicates)."); int serverPort = endpoint.port; try { HttpServer server = HttpServer.create(new InetSocketAddress(serverPort), 0); server.createContext(serverBaseUri, request -> this.handleRequest(request, endpoint, connection)); server.createContext(endpoint.baseUri, request -> this.handleRequest(request, endpoint, connection)); server.setExecutor(null); server.start(); this.servers.put(endpoint, server); Loading Loading @@ -158,20 +165,20 @@ public class HttpSystemAdapter implements SystemAdapter { server.stop(5); } private void handleRequest(HttpExchange request, HttpEndpoint source, Connection connection) throws IOException { private void handleRequest(HttpExchange request, HttpEndpoint target, Connection connection) throws IOException { synchronized (unhandledInputs) { unhandledInputs.add(new HttpInput(null, request, source, connection)); unhandledInputs.add(new HttpInput(null, request, target, connection)); unhandledInputs.notifyAll(); } } private void handleResponse(HttpResponse<String> response, Throwable t, HttpEndpoint source, private void handleResponse(HttpResponse<String> response, Throwable t, HttpEndpoint target, Connection connection) { if (t != null) handleError(t); else { synchronized (unhandledInputs) { unhandledInputs.add(new HttpInput(response, null, source, connection)); unhandledInputs.add(new HttpInput(response, null, target, connection)); unhandledInputs.notifyAll(); } } Loading @@ -179,7 +186,7 @@ public class HttpSystemAdapter implements SystemAdapter { private void handleError(Throwable t) { t.printStackTrace(); reporter.runtimeError(t); reporter.runtimeError(null, t); throw new RuntimeException(t); } Loading Loading @@ -211,16 +218,18 @@ public class HttpSystemAdapter implements SystemAdapter { if (!(data instanceof HttpRequestData) && !(data instanceof HttpResponseData)) throw new RuntimeException("Request/response data in unsupported format"); GateReference sourceGate = null; GateReference target = null; for (GateReference gate : connection.getEndPoints()) if (!gate.getComponent().equals(source)) { target = gate; break; } else { sourceGate = gate; } HttpEndpoint targetEndpoint = this.getEndpoint(target.getComponent().getName(), target.getGate().getName()); HttpEndpoint targetEndpoint = this.getEndpoint(connection.getName(), target.getComponent().getName(), target.getGate().getName()); if (targetEndpoint == null) // Assume default targetEndpoint = this.getEndpoint(defaultSut, defaultGate); targetEndpoint = this.getEndpoint(null, defaultSut, defaultGate); boolean isRequest = data instanceof HttpRequestData; try { Loading Loading @@ -273,20 +282,22 @@ public class HttpSystemAdapter implements SystemAdapter { requestBuilder.uri(uri); // TODO logging reporter.comment("Outgoing (headers): " + httpData.method.toString() + " | " + uri); reporter.comment(source.getName(), "Outgoing (headers): " + httpData.method.toString() + " | " + uri); byte[] body = encodeBody(httpData.body); reporter.comment(source.getName(), "Outgoing (body): " + mapper.writeValueAsString(httpData.body)); requestBuilder.method(httpData.method.toString(), HttpRequest.BodyPublishers.ofByteArray(body)); if (httpData.headers != null) for (HttpHeader header : httpData.headers) requestBuilder.header(header.name, header.value); CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(requestBuilder.build(), HttpResponse.BodyHandlers.ofString(UTF_8)); HttpEndpoint endpoint = targetEndpoint; HttpEndpoint sourceEndpoint = this.getEndpoint(connection.getName(), sourceGate.getComponent().getName(), sourceGate.getGate().getName()); responseFuture .whenCompleteAsync((response, t) -> this.handleResponse(response, t, endpoint, connection)); .whenCompleteAsync((response, t) -> this.handleResponse(response, t, sourceEndpoint, connection)); } else { Loading @@ -306,6 +317,7 @@ public class HttpSystemAdapter implements SystemAdapter { Headers headers = unhandledExchange.getResponseHeaders(); this.applyDefaults(headers); if (httpData.headers != null) for (HttpHeader header : httpData.headers) headers.add(header.name, header.value); Loading @@ -327,7 +339,8 @@ public class HttpSystemAdapter implements SystemAdapter { int length = body.length; // TODO logging reporter.comment("Outgoing (headers): " + httpData.status + " | " + length); reporter.comment(source.getName(), "Outgoing (headers): " + httpData.status + " | length=" + length); reporter.comment(source.getName(), "Outgoing (body): " + mapper.writeValueAsString(httpData.body)); unhandledExchange.sendResponseHeaders(httpData.status, length); Loading @@ -351,7 +364,7 @@ public class HttpSystemAdapter implements SystemAdapter { do { for (HttpInput i : unhandledInputs) if (i.connection.equals(connection)) if (!i.source.componentName.equals(target.getName())) { if (i.target.componentName.equals(target.getName())) { input = i; break; } Loading @@ -371,10 +384,13 @@ public class HttpSystemAdapter implements SystemAdapter { String body = response.body(); // TODO logging reporter.comment("Incoming: " + response.statusCode() + " | " + body); reporter.comment(target.getName(), "Incoming: " + response.statusCode() + " | " + body); try { // This is not provided by HttpResponse expectedHttpData.statusMessage = null; HttpResponseData receivedHttpData = new HttpResponseData(); receivedHttpData.status = response.statusCode(); Map<String, List<String>> headers = response.headers().map(); Loading Loading @@ -411,14 +427,21 @@ public class HttpSystemAdapter implements SystemAdapter { HttpExchange exchange = input.exchange; if (input.body == null) try (InputStream is = exchange.getRequestBody()) { // TODO other encodings Charset cs = StandardCharsets.UTF_8; String body = new String(is.readAllBytes(), cs); input.body = new String(is.readAllBytes(), cs); // TODO logging reporter.comment("Incoming: " + exchange.getRequestMethod() + " | " + body); reporter.comment(target.getName(), "Incoming: " + exchange.getRequestMethod() + " | " + input.body); } catch (IOException e) { handleError(e); } try { HttpRequestData receivedHttpData = new HttpRequestData(); receivedHttpData.uri = exchange.getRequestURI().toString(); Loading @@ -434,14 +457,14 @@ public class HttpSystemAdapter implements SystemAdapter { boolean isReceived = false; if (expected != null) { if (expectedHttpData.body != null) { receivedHttpData.body = decodeBody(body, expectedHttpData.body.getClass()); receivedHttpData.body = decodeBody(input.body, expectedHttpData.body.getClass()); } if (this.validator.matches(expected, received)) { isReceived = true; } } else { receivedHttpData.body = body; receivedHttpData.body = input.body; isReceived = true; } Loading @@ -467,7 +490,6 @@ public class HttpSystemAdapter implements SystemAdapter { } protected byte[] encodeBody(Object body) throws IOException { reporter.comment("Outgoing (body): " + mapper.writeValueAsString(body)); return mapper.writeValueAsBytes(body); } Loading Loading @@ -575,30 +597,36 @@ public class HttpSystemAdapter implements SystemAdapter { class HttpInput { HttpResponse<String> response; HttpExchange exchange; HttpEndpoint source; HttpEndpoint target; Connection connection; public HttpInput(HttpResponse<String> response, HttpExchange exchange, HttpEndpoint source, String body; public HttpInput(HttpResponse<String> response, HttpExchange exchange, HttpEndpoint target, Connection connection) { this.response = response; this.exchange = exchange; this.source = source; this.target = target; this.connection = connection; } } class HttpEndpoint { String connectionName; String componentName; String gateName; String address; String baseUri; int port; public HttpEndpoint(String componentName, String gateName, String address, int port) { public HttpEndpoint(String connectionName, String componentName, String gateName, String address, String baseUri, int port) { super(); this.connectionName = connectionName; this.componentName = componentName; this.gateName = gateName; this.address = address; this.baseUri = baseUri; this.port = port; } } Loading