blob: a7b048aae515b5ca355eac8718e6005b75f3a8d2 [file] [log] [blame]
/*
* Copyright (c) 2020 Kentyou.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kentyou - initial API and implementation
*/
package org.eclipse.sensinact.gateway.sthbnd.http.smpl;
import org.eclipse.sensinact.gateway.generic.Task.CommandType;
import org.eclipse.sensinact.gateway.protocol.http.client.ConnectionConfiguration;
import org.eclipse.sensinact.gateway.sthbnd.http.HttpPacket;
import org.eclipse.sensinact.gateway.sthbnd.http.annotation.HttpChildTaskConfiguration;
import org.eclipse.sensinact.gateway.sthbnd.http.annotation.HttpTaskConfiguration;
import org.eclipse.sensinact.gateway.sthbnd.http.annotation.KeyValuePair;
import org.eclipse.sensinact.gateway.sthbnd.http.task.HttpTask;
import org.eclipse.sensinact.gateway.util.ReflectUtils;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class SimpleTaskConfigurator implements HttpTaskBuilder {
public static final String VALUE_PATTERN = "\\$\\(([^\\)\\@]+)\\)";
public static final String CONTEXT_PATTERN = "\\@context\\[([^\\]\\$]+)\\]";
private static KeyValuePair[] join(KeyValuePair[] pa, KeyValuePair[] pb) {
int paLength = pa == null ? 0 : pa.length;
int pbLength = pb == null ? 0 : pb.length;
int length = paLength + pbLength;
KeyValuePair[] joined = new KeyValuePair[length];
int index = 0;
if (paLength > 0) {
for (; index < paLength; index++) {
joined[index] = pa[index];
}
}
if (pbLength > 0) {
for (; index < length; index++) {
joined[index] = pb[index - paLength];
}
}
return joined;
}
protected SimpleHttpProtocolStackEndpoint endpoint;
private Pattern valuePattern;
private Pattern contextPattern;
private String acceptType = null;
private String contentType = null;
private String httpMethod = null;
private String scheme = null;
private String host = null;
private String port = null;
private String path = null;
private String profile = null;
private String clientCertificate = null;
private String serverCertificate = null;
private boolean direct = false;
private CommandType command = null;
private Map<String, List<String>> query = null;
private Map<String, List<String>> headers = null;
private Class<? extends HttpPacket> packetType = null;
private HttpTaskConfigurator contentBuilder = null;
private HttpTaskConfigurator urlBuilder = null;
/**
* @param mediator
* @param profile
* @param command
* @param urlBuilder
* @param annotation
*/
public SimpleTaskConfigurator(SimpleHttpProtocolStackEndpoint endpoint, String profile, CommandType command, HttpTaskConfigurator urlBuilder, HttpTaskConfiguration annotation) {
this(endpoint, profile, command, urlBuilder, annotation, null);
}
/**
* @param mediator
* @param profile
* @param command
* @param urlBuilder
* @param parent
* @param annotation
*/
public SimpleTaskConfigurator(SimpleHttpProtocolStackEndpoint endpoint, String profile, CommandType command, HttpTaskConfigurator urlBuilder, HttpTaskConfiguration parent, HttpChildTaskConfiguration annotation) {
this.endpoint = endpoint;
this.valuePattern = Pattern.compile(VALUE_PATTERN);
this.contextPattern = Pattern.compile(CONTEXT_PATTERN);
this.acceptType = annotation != null && !HttpChildTaskConfiguration.DEFAULT_ACCEPT_TYPE.equals(annotation.acceptType()) ? annotation.acceptType() : parent.acceptType();
this.contentType = annotation != null && !HttpChildTaskConfiguration.DEFAULT_CONTENT_TYPE.equals(annotation.contentType()) ? annotation.contentType() : parent.contentType();
this.httpMethod = annotation != null && !HttpChildTaskConfiguration.DEFAULT_HTTP_METHOD.equals(annotation.httpMethod()) ? annotation.httpMethod() : parent.httpMethod();
this.scheme = annotation != null && !HttpChildTaskConfiguration.DEFAULT_SCHEME.equals(annotation.scheme()) ? annotation.scheme() : parent.scheme();
this.host = annotation != null && !HttpChildTaskConfiguration.DEFAULT_HOST.equals(annotation.host()) ? annotation.host() : parent.host();
this.port = annotation != null && !HttpChildTaskConfiguration.DEFAULT_PORT.equals(annotation.port()) ? annotation.port() : parent.port();
this.path = annotation != null && !HttpChildTaskConfiguration.DEFAULT_PATH.equals(annotation.path()) ? annotation.path() : parent.path();
this.clientCertificate = annotation != null && !HttpTaskConfiguration.DEFAULT_CLIENT_SSL_CERTIFICATE.equals(annotation.clientSSLCertificate()) ?annotation.clientSSLCertificate():parent.clientSSLCertificate();
this.serverCertificate = annotation != null && !HttpTaskConfiguration.DEFAULT_SERVER_SSL_CERTIFICATE.equals(annotation.serverSSLCertificate()) ?annotation.serverSSLCertificate():parent.serverSSLCertificate();
this.profile = profile;
this.urlBuilder = urlBuilder;
this.command = command;
this.direct = annotation != null ? annotation.direct() : parent.direct();
this.packetType = annotation != null && HttpPacket.class != annotation.packet() ? annotation.packet() : parent.packet();
this.query = new HashMap<String, List<String>>();
KeyValuePair[] queryParameters = join(annotation == null ? null : annotation.query(), parent.query());
int index = 0;
int length = queryParameters == null ? 0 : queryParameters.length;
for (; index < length; index++) {
String key = queryParameters[index].key();
String value = queryParameters[index].value();
List<String> values = query.get(key);
if (values == null) {
values = new ArrayList<String>();
query.put(key, values);
}
values.add(value);
}
this.headers = new HashMap<String, List<String>>();
KeyValuePair[] headersParameters = join(annotation == null ? null : annotation.headers(), parent.headers());
index = 0;
length = headersParameters == null ? 0 : headersParameters.length;
for (; index < length; index++) {
String key = headersParameters[index].key();
String value = headersParameters[index].value();
List<String> values = headers.get(key);
if (values == null) {
values = new ArrayList<String>();
headers.put(key, values);
}
values.add(value);
}
Class<? extends HttpTaskConfigurator> taskContentConfigurationType = annotation != null && HttpTaskConfigurator.class != annotation.content()
? annotation.content() : parent.content();
if (taskContentConfigurationType != null && taskContentConfigurationType != HttpTaskConfigurator.class) {
try {
this.contentBuilder = ReflectUtils.getTheBestInstance(taskContentConfigurationType, new Object[] {this.endpoint.getMediator()});
} catch (Exception e) {
this.endpoint.getMediator().error(e);
}
}
}
/**
* @param key
* @param value
* @return
*/
private String resolve(HttpTask<?, ?> key, String value) {
String argument = value;
String resolved = null;
while (argument != null) {
Matcher valueMatcher = this.valuePattern.matcher(argument);
Matcher contextMatcher = this.contextPattern.matcher(argument);
int valueIndex = valueMatcher.find()?valueMatcher.start(1):-1;
int contextIndex = contextMatcher.find()?contextMatcher.start(1):-1;
if (valueIndex > contextIndex) {
String val = (String) this.endpoint.getMediator().getProperty(valueMatcher.group(1));
StringBuilder builder = new StringBuilder().append(argument.substring(0, valueMatcher.start(1) - 2)).append(val).append(argument.substring(valueMatcher.end(1) + 1, argument.length()));
argument = builder.toString();
} else if (contextIndex > valueIndex) {
String val = this.endpoint.getMediator().resolve(key, contextMatcher.group(1));
StringBuilder builder = new StringBuilder().append(argument.substring(0, contextMatcher.start(1) - 9)).append(val).append(argument.substring(contextMatcher.end(1) + 1, argument.length()));
argument = builder.toString();
} else {
resolved = argument;
break;
}
}
return resolved;
}
/**
* @inheritDoc
* @see Executable#
* execute(java.lang.Object)
*/
public <T extends HttpTask<?, ?>> void configure(T task) throws Exception {
String portStr = this.resolve(task, this.port);
int port;
try {
port = Integer.parseInt(portStr);
} catch (NumberFormatException e) {
port = 80;
}
String uri = new URL(this.resolve(task, scheme), this.resolve(task, host), port, this.resolve(task, path)).toExternalForm();
StringBuilder queryBuilder = new StringBuilder();
Iterator<Map.Entry<String, List<String>>> iterator = query.entrySet().iterator();
Map.Entry<String, List<String>> entry = null;
int position = -1;
for (; iterator.hasNext(); ) {
entry = iterator.next();
List<String> values = entry.getValue();
if (values == null || values.isEmpty()) {
continue;
}
queryBuilder.append(++position == 0 ? "?" : "");
int index = 0;
int length = values == null ? 0 : values.size();
for (; index < length; index++) {
queryBuilder.append((position > 0 || index > 0) ? "&" : "");
queryBuilder.append(this.resolve(task, entry.getKey()));
queryBuilder.append("=");
queryBuilder.append(this.resolve(task, values.get(index)));
}
}
String queryRequest = queryBuilder.toString();
if (queryRequest.length() > 1) {
uri = new StringBuilder().append(uri).append(queryRequest).toString();
}
task.setUri(uri);
if (this.urlBuilder != null) {
this.urlBuilder.configure(task);
}
task.setClientSSLCertificate(HttpTaskConfiguration.NO_CERTIFICATE.equals(clientCertificate)?null:clientCertificate);
task.setServerSSLCertificate(HttpTaskConfiguration.NO_CERTIFICATE.equals(serverCertificate)?ConnectionConfiguration.TRUST_ALL:serverCertificate);
task.setDirect(direct);
iterator = headers.entrySet().iterator();
entry = null;
position = -1;
for (; iterator.hasNext(); ) {
entry = iterator.next();
List<String> values = entry.getValue();
if (values == null || values.isEmpty()) {
continue;
}
int index = 0;
int length = values == null ? 0 : values.size();
for (; index < length; index++) {
task.addHeader(this.resolve(task, entry.getKey()), this.resolve(task, values.get(index)));
}
}
if(this.packetType!=HttpPacket.class) {
task.setPacketType(this.packetType);
}
task.setAccept(this.resolve(task, acceptType));
task.setContentType(this.resolve(task, contentType));
task.setHttpMethod(this.resolve(task, httpMethod));
if (contentBuilder != null) {
contentBuilder.configure(task);
}
}
/**
* Returns the {@link CommandType} of the task to be
* configured
*
* @return the {@link CommandType} of the task to be
* configured
*/
public CommandType handled() {
return this.command;
}
}