Commit 7567ff5d authored by Martti Käärik's avatar Martti Käärik
Browse files

HTTP adapter support for parameters and basic configuration.

parent d040d826
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,7 @@ public class HttpRequestParameter {
	public HttpParameterLocation location;
	public HttpParameterLocation location;
	public String name;
	public String name;
	public String value;
	public String value;
	public HttpRequestParameter() {}
	public HttpRequestParameter(String name, String value, HttpParameterLocation location) {
	public HttpRequestParameter(String name, String value, HttpParameterLocation location) {
		this.name = name;
		this.name = name;
		this.value = value;
		this.value = value;
+76 −16
Original line number Original line Diff line number Diff line
@@ -3,6 +3,8 @@ package org.etsi.mts.tdl.execution.java.adapters.http;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.charset.StandardCharsets.UTF_8;


import java.net.URI;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse;
@@ -12,6 +14,7 @@ import java.util.Map;
import java.util.Queue;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.regex.Pattern;


import org.etsi.mts.tdl.execution.java.rt.core.PojoData;
import org.etsi.mts.tdl.execution.java.rt.core.PojoData;
import org.etsi.mts.tdl.execution.java.tri.Argument;
import org.etsi.mts.tdl.execution.java.tri.Argument;
@@ -21,12 +24,14 @@ import org.etsi.mts.tdl.execution.java.tri.Procedure;
import org.etsi.mts.tdl.execution.java.tri.Reporter;
import org.etsi.mts.tdl.execution.java.tri.Reporter;
import org.etsi.mts.tdl.execution.java.tri.SystemAdapter;
import org.etsi.mts.tdl.execution.java.tri.SystemAdapter;
import org.etsi.mts.tdl.execution.java.tri.Validator;
import org.etsi.mts.tdl.execution.java.tri.Validator;
import org.openapitools.jackson.nullable.JsonNullableModule;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;


public class HttpSystemAdapter implements SystemAdapter {
public class HttpSystemAdapter implements SystemAdapter {


@@ -37,7 +42,9 @@ public class HttpSystemAdapter implements SystemAdapter {
	private HttpClient client;
	private HttpClient client;
	private ObjectMapper mapper;
	private ObjectMapper mapper;


	private String baseUri = BASE_URI;

	private String baseUri = "https://example.com";
	private List<HttpHeader> defaultHeaders = new ArrayList<HttpHeader>();


	private Connection[] connections;
	private Connection[] connections;


@@ -48,8 +55,26 @@ public class HttpSystemAdapter implements SystemAdapter {
		this.reporter = reporter;
		this.reporter = reporter;
	}
	}
	
	
	public void setBaseUri(String baseUri) {
		this.baseUri = baseUri;
	}
	
	/**
	 * Set headers that are applied to all requests, such as authentication.
	 * The default implementation adds by default:
	 * <ul>
	 * <li>Content-Type: application/json</li>
	 * <li>Accept: application/json</li>
	 * </ul>   
	 */
	public void setDefaultHeaders(List<HttpHeader> defaultHeaders) {
		this.defaultHeaders = defaultHeaders;
	}

	@Override
	@Override
	public void configure(Connection[] connections) {
	public void configure(Connection[] connections) {
		if (connections.length > 1)
			System.err.println("TODO: multiple connections not supported");


		// TODO multiple connections
		// TODO multiple connections
		this.connections = connections;
		this.connections = connections;
@@ -67,9 +92,11 @@ public class HttpSystemAdapter implements SystemAdapter {
		mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
		mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
		/*
		/*
		 * TODO optional modules 
		 * TODO optional modules 
		 * mapper.registerModule(new JavaTimeModule());
		 * 
		 * mapper.registerModule(new JsonNullableModule());
		 */
		 */
		mapper.registerModule(new JavaTimeModule());
		mapper.registerModule(new JsonNullableModule());
		
	}
	}


	private void handleResponse(HttpResponse<String> response, Throwable t) {
	private void handleResponse(HttpResponse<String> response, Throwable t) {
@@ -91,8 +118,9 @@ public class HttpSystemAdapter implements SystemAdapter {
	private void applyDefaults(HttpRequest.Builder requestBuilder) {
	private void applyDefaults(HttpRequest.Builder requestBuilder) {
		requestBuilder.header("Content-Type", "application/json");
		requestBuilder.header("Content-Type", "application/json");
		requestBuilder.header("Accept", "application/json");
		requestBuilder.header("Accept", "application/json");
		// TODO configuration (e.g. auth)
		for (HttpHeader h: defaultHeaders) {
//		requestBuilder.header("Cookie", "usertoken=" + AUTH);
			requestBuilder.header(h.name, h.value);
		}
	}
	}


	@Override
	@Override
@@ -102,13 +130,47 @@ public class HttpSystemAdapter implements SystemAdapter {
		HttpRequest.Builder requestBuilder = HttpRequest.newBuilder();
		HttpRequest.Builder requestBuilder = HttpRequest.newBuilder();
		applyDefaults(requestBuilder);
		applyDefaults(requestBuilder);


		// TODO parameters
		// Parameters
		String query = null;
		for (HttpRequestParameter p : httpData.parameters) {
			if (p.value == null)
				continue;
			switch (p.location) {
			case path: {
				httpData.uri = httpData.uri.replaceAll(Pattern.quote("{" + p.name + "}"), p.value);
				break;
			}
			case quey: {
				String queryParameter = p.name + "=" + URLEncoder.encode(p.value, UTF_8);
				if (query == null)
					query = queryParameter;
				else
					query += "&" + queryParameter;
				break;
			}
			case cookie: {
				System.err.println("TODO: cookie parameters not handled");
				break;
			}
			}
		}
		URI uri = URI.create(baseUri + httpData.uri);
		try {
			if (query != null) {
				if (uri.getQuery() != null)
					query = uri.getQuery() + "&" + query;
				uri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(),
						URLEncoder.encode(query, UTF_8), uri.getFragment());
			}
		} catch (URISyntaxException e) {
			handleError(e);
		}


		try {
		try {
			requestBuilder.uri(URI.create(baseUri + httpData.uri));
			requestBuilder.uri(uri);


			//XXX
			// TODO logging
			reporter.comment("Outgoing: " + mapper.writeValueAsString(httpData.body));
			reporter.comment("Outgoing: " + httpData.method.toString() + " | " + uri + " | " + mapper.writeValueAsString(httpData.body));


			byte[] body = mapper.writeValueAsBytes(httpData.body);
			byte[] body = mapper.writeValueAsBytes(httpData.body);
			requestBuilder.method(httpData.method.toString(), HttpRequest.BodyPublishers.ofByteArray(body));
			requestBuilder.method(httpData.method.toString(), HttpRequest.BodyPublishers.ofByteArray(body));
@@ -138,7 +200,7 @@ public class HttpSystemAdapter implements SystemAdapter {
			}
			}


			// TODO logging
			// TODO logging
			reporter.comment("Incoming: " + response.body());
			reporter.comment("Incoming: " + response.statusCode() + " | " + response.body());


			try {
			try {


@@ -190,6 +252,4 @@ public class HttpSystemAdapter implements SystemAdapter {
	public void replyCall(Procedure operation, Data returnValue, Data exception, Connection connection) {
	public void replyCall(Procedure operation, Data returnValue, Data exception, Connection connection) {
		throw new UnsupportedOperationException("Procedure-based communication is not supported by this adapter.");
		throw new UnsupportedOperationException("Procedure-based communication is not supported by this adapter.");
	}
	}

	private static String BASE_URI = "<todo>";
}
}
 No newline at end of file