blob: 7a0d5d6385c2d941e8e409bd83d7f4d1599c7f61 [file] [log] [blame]
package net.sf.taverna.t2.activities.rest;
import static net.sf.taverna.t2.activities.rest.RESTActivity.hasMessageBodyInputPort;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.JsonNode;
import net.sf.taverna.t2.activities.rest.RESTActivity.DATA_FORMAT;
import net.sf.taverna.t2.activities.rest.RESTActivity.HTTP_METHOD;
import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean;
import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty;
/**
* Beans of this class store configuration information for REST activities.
* Configuration is comprised of the HTTP method to use, URL signature, and MIME
* types for Accept and Content-Type HTTP request headers. Additional value is
* used to record the format of outgoing data - binary or string. <br/>
* <br/>
* Also, derived attribute "activityInputs" is generated by identifying all
* "input ports" in the provided URL signature. <br/>
* <br/>
* Complete request URL (obtained by substituting values into the placeholders
* of the URL signature) is not stored, as it represents an instantiation of the
* activity invocation. The same applies for the input message body sent along
* with POST / PUT requests.
*
* @author Sergejs Aleksejevs
*/
@SuppressWarnings("serial")
@ConfigurationBean(uri = RESTActivity.URI + "#Config")
public class RESTActivityConfigurationBean implements Serializable {
private static final List<String> knownHeaders = Arrays.asList("Accept",
"Content-Type", "Expect");
private RESTActivity.DATA_FORMAT outgoingDataFormat;
private boolean showRedirectionOutputPort;
private boolean showActualUrlPort;
private boolean showResponseHeadersPort;
// whether to perform URL escaping of passed parameters, true by default
private boolean escapeParameters = true;
// only need to store the configuration of inputs, as all of them are
// dynamic;
// only inputs that constitute components of URL signature are to be stored
// in this map all outputs are currently fixed, so no need to keep
// configuration of those
private Map<String, Class<?>> activityInputs;
private HTTPRequest request;
/**
* @return An instance of the {@link RESTActivityConfigurationBean}
* pre-configured with default settings for all parameters.
*/
public static RESTActivityConfigurationBean getDefaultInstance() {
// TODO - set sensible default values here
RESTActivityConfigurationBean defaultBean = new RESTActivityConfigurationBean();
defaultBean.setRequest(new HTTPRequest());
defaultBean.setHttpMethod(RESTActivity.HTTP_METHOD.GET);
defaultBean.setAcceptsHeaderValue("application/xml");
defaultBean.setContentTypeForUpdates("application/xml");
defaultBean.setUrlSignature("http://www.uniprot.org/uniprot/{id}.xml");
defaultBean.setOutgoingDataFormat(RESTActivity.DATA_FORMAT.String);
// not ticked by default to allow to post to Twitter
defaultBean.setSendHTTPExpectRequestHeader(false);
// not showing the Redirection output port by default to make processor
// look simpler
defaultBean.setShowRedirectionOutputPort(false);
defaultBean.setShowActualUrlPort(false);
defaultBean.setShowResponseHeadersPort(false);
defaultBean.setEscapeParameters(true);
defaultBean.setOtherHTTPHeaders(new ArrayList<ArrayList<String>>());
return (defaultBean);
}
public RESTActivityConfigurationBean() {
}
public RESTActivityConfigurationBean(JsonNode json) {
JsonNode requestNode = json.get("request");
HTTPRequest request = new HTTPRequest();
if (requestNode.has("httpMethod")) {
request.setMethod(HTTP_METHOD.valueOf(requestNode.get("httpMethod")
.textValue()));
} else {
request.setMethod(HTTP_METHOD.GET);
}
request.setAbsoluteURITemplate(requestNode.get("absoluteURITemplate")
.textValue());
setRequest(request);
setAcceptsHeaderValue("application/xml");
setContentTypeForUpdates("application/xml");
setSendHTTPExpectRequestHeader(false);
if (requestNode.has("headers")) {
for (JsonNode headerNode : requestNode.get("headers")) {
String headerName = headerNode.get("header").textValue();
String headerValue = headerNode.get("value").textValue();
if ("Expect".equals(headerName)) {
request.setHeader(headerName, true);
} else {
request.setHeader(headerName, headerValue);
}
}
}
if (json.has("outgoingDataFormat")) {
setOutgoingDataFormat(DATA_FORMAT.valueOf(json.get(
"outgoingDataFormat").textValue()));
} else {
setOutgoingDataFormat(DATA_FORMAT.String);
}
if (json.has("showRedirectionOutputPort")) {
setShowRedirectionOutputPort(json.get("showRedirectionOutputPort")
.booleanValue());
} else {
setShowRedirectionOutputPort(false);
}
if (json.has("showActualURLPort")) {
setShowActualUrlPort(json.get("showActualURLPort").booleanValue());
} else {
setShowActualUrlPort(false);
}
if (json.has("showResponseHeadersPort")) {
setShowResponseHeadersPort(json.get("showResponseHeadersPort")
.booleanValue());
} else {
setShowResponseHeadersPort(false);
}
if (json.has("escapeParameters")) {
setEscapeParameters(json.get("escapeParameters").booleanValue());
} else {
setEscapeParameters(true);
}
}
/**
* Tests validity of the configuration held in this bean. <br/>
* <br/>
* Performed tests are as follows: <br/>
* * <code>httpMethod</code> is known to be valid - it's an enum; <br/>
* * <code>urlSignature</code> - uses
* {@link URISignatureHandler#isValid(String)} to test validity; <br/>
* * <code>acceptsHeaderValue</code> and <code>contentTypeForUpdates</code>
* must not be empty. <br/>
* <br/>
* <code>contentTypeForUpdates</code> is only checked if the
* <code>httpMethod</code> is such that it is meant to use the Content-Type
* header (that is POST / PUT only).
*
* @return <code>true</code> if the configuration in the bean is valid;
* <code>false</code> otherwise.
*/
public boolean isValid() {
if (getUrlSignature() == null
|| !URISignatureHandler.isValid(getUrlSignature()))
return false;
return (hasMessageBodyInputPort(getHttpMethod())
&& getContentTypeForUpdates() != null
&& getContentTypeForUpdates().length() > 0 && outgoingDataFormat != null)
|| !hasMessageBodyInputPort(getHttpMethod());
}
public void setHttpMethod(RESTActivity.HTTP_METHOD httpMethod) {
request.setMethod(httpMethod);
}
public RESTActivity.HTTP_METHOD getHttpMethod() {
return request.getMethod();
}
public String getUrlSignature() {
return request.getAbsoluteURITemplate();
}
public void setUrlSignature(String urlSignature) {
request.setAbsoluteURITemplate(urlSignature);
}
public String getAcceptsHeaderValue() {
HTTPRequestHeader header = request.getHeader("Accept");
return header == null ? null : header.getFieldValue();
}
public void setAcceptsHeaderValue(String acceptsHeaderValue) {
request.setHeader("Accept", acceptsHeaderValue);
}
public String getContentTypeForUpdates() {
HTTPRequestHeader header = request.getHeader("Content-Type");
return header == null ? null : header.getFieldValue();
}
public void setContentTypeForUpdates(String contentTypeForUpdates) {
request.setHeader("Content-Type", contentTypeForUpdates);
}
public void setActivityInputs(Map<String, Class<?>> activityInputs) {
this.activityInputs = activityInputs;
}
public Map<String, Class<?>> getActivityInputs() {
return activityInputs;
}
public RESTActivity.DATA_FORMAT getOutgoingDataFormat() {
return outgoingDataFormat;
}
@ConfigurationProperty(name = "outgoingDataFormat", label = "Send data as", required = false)
public void setOutgoingDataFormat(
RESTActivity.DATA_FORMAT outgoingDataFormat) {
this.outgoingDataFormat = outgoingDataFormat;
}
public boolean getSendHTTPExpectRequestHeader() {
HTTPRequestHeader header = request.getHeader("Expect");
return header == null ? false : header.isUse100Continue();
}
public void setSendHTTPExpectRequestHeader(
boolean sendHTTPExpectRequestHeader) {
request.setHeader("Expect", sendHTTPExpectRequestHeader);
}
public boolean getShowRedirectionOutputPort() {
return showRedirectionOutputPort;
}
@ConfigurationProperty(name = "showRedirectionOutputPort", label = "Show 'Redirection' output port", required = false)
public void setShowRedirectionOutputPort(boolean showRedirectionOutputPort) {
this.showRedirectionOutputPort = showRedirectionOutputPort;
}
@ConfigurationProperty(name = "escapeParameters", label = "Escape URL parameter values", required = false)
public void setEscapeParameters(boolean escapeParameters) {
this.escapeParameters = Boolean.valueOf(escapeParameters);
}
public boolean getEscapeParameters() {
return escapeParameters;
}
public void setOtherHTTPHeaders(
ArrayList<ArrayList<String>> otherHTTPHeaders) {
for (ArrayList<String> otherHTTPHeader : otherHTTPHeaders)
request.setHeader(otherHTTPHeader.get(0), otherHTTPHeader.get(1));
}
public ArrayList<ArrayList<String>> getOtherHTTPHeaders() {
ArrayList<ArrayList<String>> otherHTTPHeaders = new ArrayList<>();
List<HTTPRequestHeader> headers = request.getHeaders();
for (HTTPRequestHeader header : headers)
if (!knownHeaders.contains(header.getFieldName())) {
ArrayList<String> nameValuePair = new ArrayList<>();
nameValuePair.add(header.getFieldName());
nameValuePair.add(header.getFieldValue());
otherHTTPHeaders.add(nameValuePair);
}
return otherHTTPHeaders;
}
/**
* @return the showActualUrlPort
*/
public boolean getShowActualUrlPort() {
return showActualUrlPort;
}
/**
* @param showActualUrlPort
* the showActualUrlPort to set
*/
public void setShowActualUrlPort(boolean showActualUrlPort) {
this.showActualUrlPort = showActualUrlPort;
}
/**
* @return the showResponseHeadersPort
*/
public boolean getShowResponseHeadersPort() {
return showResponseHeadersPort;
}
/**
* @param showResponseHeadersPort
* the showResponseHeadersPort to set
*/
public void setShowResponseHeadersPort(boolean showResponseHeadersPort) {
this.showResponseHeadersPort = showResponseHeadersPort;
}
public HTTPRequest getRequest() {
return request;
}
@ConfigurationProperty(name = "request", label = "HTTP Request")
public void setRequest(HTTPRequest request) {
this.request = request;
}
}