52n-wps-server-gcube/src/main/java/org/n52/wps/server/request/ExecuteRequest.java

920 lines
32 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (C) 2007 - 2016 52°North Initiative for Geospatial Open Source
* Software GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* If the program is linked with libraries which are licensed under one of
* the following licenses, the combination of the program with the linked
* library is not considered a "derivative work" of the program:
*
* • Apache License, version 2.0
* • Apache Software License, version 1.0
* • GNU Lesser General Public License, version 3
* • Mozilla Public License, versions 1.0, 1.1 and 2.0
* • Common Development and Distribution License (CDDL), version 1.0
*
* Therefore the distribution of the program linked with libraries licensed
* under the aforementioned licenses, is permitted by the copyright holders
* if the distribution is compliant with both the GNU General Public
* License version 2 and the aforementioned licenses.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*/
package org.n52.wps.server.request;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilderFactory;
import net.opengis.ows.x11.BoundingBoxType;
import net.opengis.ows.x11.ExceptionType;
import net.opengis.wps.x100.ComplexDataType;
import net.opengis.wps.x100.DataInputsType;
import net.opengis.wps.x100.DocumentOutputDefinitionType;
import net.opengis.wps.x100.ExecuteDocument;
import net.opengis.wps.x100.ExecuteDocument.Execute;
import net.opengis.wps.x100.InputDescriptionType;
import net.opengis.wps.x100.InputReferenceType;
import net.opengis.wps.x100.InputType;
import net.opengis.wps.x100.LiteralDataType;
import net.opengis.wps.x100.OutputDefinitionType;
import net.opengis.wps.x100.OutputDescriptionType;
import net.opengis.wps.x100.ProcessDescriptionType;
import net.opengis.wps.x100.ResponseDocumentType;
import net.opengis.wps.x100.ResponseFormType;
import net.opengis.wps.x100.StatusType;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.apache.commons.io.IOUtils;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.n52.wps.commons.context.ExecutionContext;
import org.n52.wps.commons.context.ExecutionContextFactory;
import org.n52.wps.io.data.IComplexData;
import org.n52.wps.io.data.IData;
import org.n52.wps.server.AbstractTransactionalAlgorithm;
import org.n52.wps.server.ExceptionReport;
import org.n52.wps.server.IAlgorithm;
import org.n52.wps.server.RepositoryManager;
import org.n52.wps.server.database.DatabaseFactory;
import org.n52.wps.server.observerpattern.IObserver;
import org.n52.wps.server.observerpattern.ISubject;
import org.n52.wps.server.response.ExecuteResponse;
import org.n52.wps.server.response.ExecuteResponseBuilder;
import org.n52.wps.server.response.Response;
import org.n52.wps.util.XMLBeansHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
/**
* Handles an ExecuteRequest
*/
public class ExecuteRequest extends Request implements IObserver {
private static Logger LOGGER = LoggerFactory.getLogger(ExecuteRequest.class);
private ExecuteDocument execDom;
private Map<String, IData> returnResults;
private ExecuteResponseBuilder execRespType;
/**
* Creates an ExecuteRequest based on a Document (HTTP_POST)
*
* @param doc
* The clients submission
* @throws ExceptionReport
*/
public ExecuteRequest(Document doc) throws ExceptionReport {
super(doc);
try {
XmlOptions option = new XmlOptions();
option.setLoadTrimTextBuffer();
this.execDom = ExecuteDocument.Factory.parse(doc, option);
if (this.execDom == null) {
LOGGER.error("ExecuteDocument is null");
throw new ExceptionReport("Error while parsing post data",
ExceptionReport.MISSING_PARAMETER_VALUE);
}
} catch (XmlException e) {
throw new ExceptionReport("Error while parsing post data",
ExceptionReport.MISSING_PARAMETER_VALUE, e);
}
// validate the client input
validate();
// create an initial response
execRespType = new ExecuteResponseBuilder(this);
storeRequest(execDom);
}
/*
* Creates an ExecuteRequest based on a Map (HTTP_GET). NOTE: Parameters are
* treated as non case sensitive. @param ciMap The client input @throws
* ExceptionReport
*/
public ExecuteRequest(CaseInsensitiveMap ciMap) throws ExceptionReport {
super(ciMap);
initForGET(ciMap);
// validate the client input
validate();
// create an initial response
execRespType = new ExecuteResponseBuilder(this);
storeRequest(ciMap);
}
public void getKVPDataInputs(){
}
/**
* @param ciMap
*/
private void initForGET(CaseInsensitiveMap ciMap) throws ExceptionReport {
String version = getMapValue("version", ciMap, true);
if (!version.equals(Request.SUPPORTED_VERSION)) {
throw new ExceptionReport("request version is not supported: "
+ version, ExceptionReport.VERSION_NEGOTIATION_FAILED);
}
this.execDom = ExecuteDocument.Factory.newInstance();
Execute execute = execDom.addNewExecute();
String processID = getMapValue("Identifier", true);
if (!RepositoryManager.getInstance().containsAlgorithm(processID)) {
throw new ExceptionReport("Process does not exist",
ExceptionReport.INVALID_PARAMETER_VALUE);
}
execute.addNewIdentifier().setStringValue(processID);
DataInputsType dataInputs = execute.addNewDataInputs();
String dataInputString = getMapValue("DataInputs", true);
dataInputString = dataInputString.replace("&amp;","&");
String[] inputs = dataInputString.split(";");
// Handle data inputs
for (String inputString : inputs) {
int position = inputString.indexOf("=");
if (position == -1) {
throw new ExceptionReport("No \"=\" supplied for attribute: "
+ inputString, ExceptionReport.MISSING_PARAMETER_VALUE);
}
//get name
String key = inputString.substring(0, position);
String value = null;
if (key.length() + 1 < inputString.length()) {
// BS int valueDelimiter = inputString.indexOf("@");
int valueDelimiter = inputString.indexOf("@");
if (valueDelimiter != -1 && position + 1 < valueDelimiter) {
value = inputString.substring(position + 1, valueDelimiter);
} else {
value = inputString.substring(position + 1);
}
}
ProcessDescriptionType description = RepositoryManager.getInstance().getProcessDescription(processID);
if (description == null) {
throw new ExceptionReport("Data Identifier not supported: "
+ key, ExceptionReport.MISSING_PARAMETER_VALUE);
}
InputDescriptionType inputDesc = XMLBeansHelper.findInputByID(key,
description.getDataInputs());
if (inputDesc == null) {
throw new ExceptionReport("Data Identifier not supported: "
+ key, ExceptionReport.MISSING_PARAMETER_VALUE);
}
InputType input = dataInputs.addNewInput();
input.addNewIdentifier().setStringValue(key);
// prepare attributes
String encodingAttribute = null;
String mimeTypeAttribute = null;
String schemaAttribute = null;
String hrefAttribute = null;
String uom = null;
String dataType = null;
String[] inputItemstemp = inputString.split("@");
String[] inputItems = null;
if (inputItemstemp.length == 2) {
inputItems = inputItemstemp[1].split("@");
} else {
inputItems = inputString.split("@");
}
if (inputItemstemp.length > 1) {
for (int i = 0; i < inputItems.length; i++) {
int attributePos = inputItems[i].indexOf("=");
if (attributePos == -1
|| attributePos + 1 >= inputItems[i].length()) {
continue;
}
String attributeName = inputItems[i].substring(0,
attributePos);
String attributeValue = inputItems[i]
.substring(attributePos + 1);
//attribute is input name
if(attributeName.equals(key)){
continue;
}
try {
attributeValue = URLDecoder.decode(attributeValue, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new ExceptionReport("Something went wrong while trying to decode value of " + attributeName, ExceptionReport.NO_APPLICABLE_CODE, e);
}
if (attributeName.equalsIgnoreCase("encoding")) {
encodingAttribute = attributeValue;
} else if (attributeName.equalsIgnoreCase("mimeType")) {
mimeTypeAttribute = attributeValue;
} else if (attributeName.equalsIgnoreCase("schema")) {
schemaAttribute = attributeValue;
} else if (attributeName.equalsIgnoreCase("href") | attributeName.equalsIgnoreCase("xlink:href")) {
hrefAttribute = attributeValue;
} else if (attributeName.equalsIgnoreCase("uom")) {
uom = attributeValue;
} else if (attributeName.equalsIgnoreCase("datatype")) {
dataType = attributeValue;
} else {
throw new ExceptionReport(
"Attribute is not supported: " + attributeName,
ExceptionReport.INVALID_PARAMETER_VALUE);
}
}
}
if (inputDesc.isSetComplexData()) {
// TODO: check for different attributes
// handling ComplexReference
if (!(hrefAttribute == null) && !hrefAttribute.equals("")) {
InputReferenceType reference = input.addNewReference();
reference.setHref(hrefAttribute);
if (schemaAttribute != null) {
reference.setSchema(schemaAttribute);
}
if (mimeTypeAttribute != null) {
reference.setMimeType(mimeTypeAttribute);
}
if (encodingAttribute != null) {
reference.setEncoding(encodingAttribute);
}
}
// Handling ComplexData
else {
ComplexDataType data = input.addNewData().addNewComplexData();
InputStream stream = new ByteArrayInputStream(value.getBytes());
try {
data.set(XmlObject.Factory.parse(stream));
} catch (Exception e) {
LOGGER.warn("Could not parse value: " + value + " as XMLObject. Trying to create text node.");
try {
Node textNode = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createTextNode(value);
data.set(XmlObject.Factory.parse(textNode));
} catch (Exception e1) {
throw new ExceptionReport("Exception while trying to parse value: " + value,
ExceptionReport.NO_APPLICABLE_CODE, e1);
}
}
if (schemaAttribute != null) {
data.setSchema(schemaAttribute);
}
if (mimeTypeAttribute != null) {
data.setMimeType(mimeTypeAttribute);
}
if (encodingAttribute != null) {
data.setEncoding(encodingAttribute);
}
}
} else if (inputDesc.isSetLiteralData()) {
LiteralDataType data = input.addNewData().addNewLiteralData();
if (value == null) {
throw new ExceptionReport("No value provided for literal: "
+ inputDesc.getIdentifier().getStringValue(),
ExceptionReport.MISSING_PARAMETER_VALUE);
}
data.setStringValue(value);
if(uom != null){
data.setUom(uom);
}
if(dataType != null){
data.setDataType(dataType);
}
} else if (inputDesc.isSetBoundingBoxData()) {
BoundingBoxType data = input.addNewData().addNewBoundingBoxData();
String[] values = value.split(",");
if(values.length<4){
throw new ExceptionReport("Invalid Number of BBOX Values: "
+ inputDesc.getIdentifier().getStringValue(),
ExceptionReport.MISSING_PARAMETER_VALUE);
}
List<String> lowerCorner = new ArrayList<String>();
lowerCorner.add(values[0]);
lowerCorner.add(values[1]);
data.setLowerCorner(lowerCorner);
List<String> upperCorner = new ArrayList<String>();
upperCorner.add(values[2]);
upperCorner.add(values[3]);
data.setUpperCorner(upperCorner);
if(values.length>4){
data.setCrs(values[4]);
}
if(values.length>5){
data.setDimensions(BigInteger.valueOf(Long.valueOf(values[5])));
}
}
}
// retrieve status
boolean status = false;
String statusString = getMapValue("status", false);
if (statusString != null) {
status = Boolean.parseBoolean(statusString);
}
boolean store = false;
String storeString = getMapValue("storeExecuteResponse", false);
if (storeString != null) {
store = Boolean.parseBoolean(storeString);
}
// Handle ResponseDocument option
String responseDocument = getMapValue("ResponseDocument", false);
if (responseDocument != null) {
String[] outputs = responseDocument.split(";");
ResponseDocumentType responseDoc = execute.addNewResponseForm()
.addNewResponseDocument();
responseDoc.setStatus(status);
responseDoc.setStoreExecuteResponse(store);
for (String outputID : outputs) {
String[] outputDataparameters = outputID.split("@");
String outputDataInput = "";
if (outputDataparameters.length > 0) {
outputDataInput = outputDataparameters[0];
} else {
outputDataInput = outputID;
}
outputDataInput = outputDataInput.replace("=", "");
ProcessDescriptionType description = RepositoryManager.getInstance().getProcessDescription(processID);
OutputDescriptionType outputDesc = XMLBeansHelper
.findOutputByID(outputDataInput, description.getProcessOutputs()
.getOutputArray());
if (outputDesc == null) {
throw new ExceptionReport(
"Data output Identifier not supported: "
+ outputDataInput,
ExceptionReport.MISSING_PARAMETER_VALUE);
}
DocumentOutputDefinitionType output = responseDoc
.addNewOutput();
output.addNewIdentifier().setStringValue(outputDataInput);
for (int i = 1; i < outputDataparameters.length; i++) {
int attributePos = outputDataparameters[i].indexOf("=");
if (attributePos == -1
|| attributePos + 1 >= outputDataparameters[i]
.length()) {
continue;
}
String attributeName = outputDataparameters[i].substring(0,
attributePos);
String attributeValue = outputDataparameters[i]
.substring(attributePos + 1);
try{
attributeValue = URLDecoder.decode(attributeValue, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new ExceptionReport("Something went wrong while trying to decode value of " + attributeName, ExceptionReport.NO_APPLICABLE_CODE, e);
}
if (attributeName.equalsIgnoreCase("mimeType")) {
output.setMimeType(attributeValue);
} else if (attributeName.equalsIgnoreCase("schema")) {
output.setSchema(attributeValue);
} else if (attributeName.equalsIgnoreCase("encoding")) {
output.setEncoding(attributeValue);
}
}
}
}
String rawData = getMapValue("RawDataOutput", false);
if (rawData != null) {
String[] rawDataparameters = rawData.split("@");
String rawDataInput = "";
if (rawDataparameters.length > 0) {
rawDataInput = rawDataparameters[0];
} else {
rawDataInput = rawData;
}
ProcessDescriptionType description = RepositoryManager.getInstance().getProcessDescription(processID);
OutputDescriptionType outputDesc = XMLBeansHelper.findOutputByID(
rawDataInput,
description.getProcessOutputs().getOutputArray());
if (outputDesc == null) {
throw new ExceptionReport(
"Data output Identifier not supported: " + rawData,
ExceptionReport.MISSING_PARAMETER_VALUE);
}
ResponseFormType responseForm = execute.addNewResponseForm();
OutputDefinitionType output = responseForm.addNewRawDataOutput();
output.addNewIdentifier().setStringValue(
outputDesc.getIdentifier().getStringValue());
if (rawDataparameters.length > 0) {
for (int i = 0; i < rawDataparameters.length; i++) {
int attributePos = rawDataparameters[i].indexOf("=");
if (attributePos == -1
|| attributePos + 1 >= rawDataparameters[i]
.length()) {
continue;
}
String attributeName = rawDataparameters[i].substring(0,
attributePos);
String attributeValue = rawDataparameters[i]
.substring(attributePos + 1);
try{
attributeValue = URLDecoder.decode(attributeValue, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new ExceptionReport("Something went wrong while trying to decode value of " + attributeName, ExceptionReport.NO_APPLICABLE_CODE, e);
}
if (attributeName.equalsIgnoreCase("mimeType")) {
output.setMimeType(attributeValue);
} else if (attributeName.equalsIgnoreCase("schema")) {
output.setSchema(attributeValue);
} else if (attributeName.equalsIgnoreCase("encoding")) {
output.setEncoding(attributeValue);
} else {
throw new ExceptionReport(
"Attribute is not supported: " + attributeName,
ExceptionReport.INVALID_PARAMETER_VALUE);
}
}
}
}
}
/**
* Validates the client request
*
* @return True if the input is valid, False otherwise
*/
public boolean validate() throws ExceptionReport {
// Identifier must be specified.
/*
* Only for HTTP_GET: String identifier = getMapValue("identifier");
*
* try{ // Specifies if all complex valued output(s) of this process
* should be stored by process // as web-accessible resources store =
* getMapValue("store").equals("true");
* // Specifies if Execute operation response shall be returned quickly
* with status information status =
* getMapValue("status").equals("true"); }catch(ExceptionReport e){ //
* if parameters "store" or "status" are not included, they default to
* false; }
* // just testing if the number of arguments is even... String[]
* diArray = getMapValue("DataInputs").split(","); if(diArray.length % 2 !=
* 0) { throw new ExceptionReport("Incorrect number of arguments for
* parameter dataInputs, please only a even number of parameter values",
* ExceptionReport.INVALID_PARAMETER_VALUE); }
*
*/
if (!execDom.getExecute().getVersion().equals(SUPPORTED_VERSION)) {
throw new ExceptionReport("Specified version is not supported.",
ExceptionReport.INVALID_PARAMETER_VALUE, "version="
+ getExecute().getVersion());
}
//Fix for bug https://bugzilla.52north.org/show_bug.cgi?id=906
String identifier = getAlgorithmIdentifier();
if(identifier == null){
throw new ExceptionReport(
"No process identifier supplied.",
ExceptionReport.MISSING_PARAMETER_VALUE, "identifier");
}
// check if the algorithm is in our repository
if (!RepositoryManager.getInstance().containsAlgorithm(
identifier)) {
throw new ExceptionReport(
"Specified process identifier does not exist",
ExceptionReport.INVALID_PARAMETER_VALUE,
"identifier=" + identifier);
}
// validate if the process can be executed
ProcessDescriptionType desc = RepositoryManager.getInstance().getProcessDescription(getAlgorithmIdentifier());
// We need a description of the inputs for the algorithm
if (desc == null) {
LOGGER.warn("desc == null");
return false;
}
// Get the inputdescriptions of the algorithm
if(desc.getDataInputs()!=null){
InputDescriptionType[] inputDescs = desc.getDataInputs().getInputArray();
//prevent NullPointerException for zero input values in execute request (if only default values are used)
InputType[] inputs;
if(getExecute().getDataInputs()==null)
inputs=new InputType[0];
else
inputs = getExecute().getDataInputs().getInputArray();
// For each input supplied by the client
for (InputType input : inputs) {
boolean identifierMatched = false;
// Try to match the input with one of the descriptions
for (InputDescriptionType inputDesc : inputDescs) {
// If found, then process:
if (inputDesc.getIdentifier().getStringValue().equals(
input.getIdentifier().getStringValue())) {
identifierMatched = true;
// If it is a literal value,
if (input.getData() != null
&& input.getData().getLiteralData() != null) {
// then check if the desription is also of type literal
if (inputDesc.getLiteralData() == null) {
throw new ExceptionReport(
"Inputtype LiteralData is not supported",
ExceptionReport.INVALID_PARAMETER_VALUE);
}
// literalValue.getDataType ist optional
if (input.getData().getLiteralData().getDataType() != null) {
if (inputDesc.getLiteralData() != null)
if (inputDesc.getLiteralData().getDataType() != null)
if (inputDesc.getLiteralData()
.getDataType().getReference() != null)
if (!input
.getData()
.getLiteralData()
.getDataType()
.equals(
inputDesc
.getLiteralData()
.getDataType()
.getReference())) {
throw new ExceptionReport(
"Specified dataType is not supported "
+ input
.getData()
.getLiteralData()
.getDataType()
+ " for input "
+ input
.getIdentifier()
.getStringValue(),
ExceptionReport.INVALID_PARAMETER_VALUE);
}
}
}
// Excluded, because ProcessDescription validation should be
// done on startup!
// else if (input.getComplexValue() != null) {
// if(ParserFactory.getInstance().getParser(input.getComplexValue().getSchema())
// == null) {
// LOGGER.warn("Request validation message: schema attribute
// null, so the simple one will be used!");
// }
// }
// else if (input.getComplexValueReference() != null) {
// // we found a complexvalue input, try to get the parser.
// if(ParserFactory.getInstance().getParser(input.getComplexValueReference().getSchema())
// == null) {
// LOGGER.warn("Request validation message: schema attribute
// null, so the simple one will be used!");
// }
// }
break;
}
}
// if the identifier did not match one of the descriptions, it is
// invalid
if (!identifierMatched) {
throw new ExceptionReport("Input Identifier is not valid: "
+ input.getIdentifier().getStringValue(),
ExceptionReport.INVALID_PARAMETER_VALUE,
"input identifier");
}
}
}
return true;
}
/**
* Actually serves the Request.
*
* @throws ExceptionReport
*/
public Response call() throws ExceptionReport {
IAlgorithm algorithm = null;
Map<String, List<IData>> inputMap = null;
try {
ExecutionContext context;
if (getExecute().isSetResponseForm()) {
context = getExecute().getResponseForm().isSetRawDataOutput() ?
new ExecutionContext(getExecute().getResponseForm().getRawDataOutput()) :
new ExecutionContext(Arrays.asList(getExecute().getResponseForm().getResponseDocument().getOutputArray()));
}
else {
context = new ExecutionContext();
}
// register so that any function that calls ExecuteContextFactory.getContext() gets the instance registered with this thread
ExecutionContextFactory.registerContext(context);
LOGGER.debug("started with execution");
updateStatusStarted();
// parse the input
InputType[] inputs = new InputType[0];
if( getExecute().getDataInputs()!=null){
inputs = getExecute().getDataInputs().getInputArray();
}
InputHandler parser = new InputHandler.Builder(inputs, getAlgorithmIdentifier()).build();
// we got so far:
// get the algorithm, and run it with the clients input
/*
* IAlgorithm algorithm =
* RepositoryManager.getInstance().getAlgorithm(getAlgorithmIdentifier());
* returnResults = algorithm.run((Map)parser.getParsedInputLayers(),
* (Map)parser.getParsedInputParameters());
*/
algorithm = RepositoryManager.getInstance().getAlgorithm(getAlgorithmIdentifier());
if(algorithm instanceof ISubject){
ISubject subject = (ISubject) algorithm;
subject.addObserver(this);
}
if(algorithm instanceof AbstractTransactionalAlgorithm){
returnResults = ((AbstractTransactionalAlgorithm)algorithm).run(execDom);
} else {
inputMap = parser.getParsedInputData();
returnResults = algorithm.run(inputMap);
}
List<String> errorList = algorithm.getErrors();
if (errorList != null && !errorList.isEmpty()) {
String errorMessage = errorList.get(0);
LOGGER.error("Error reported while handling ExecuteRequest for " + getAlgorithmIdentifier() + ": " + errorMessage);
updateStatusError(errorMessage);
} else {
updateStatusSuccess();
}
} catch(Throwable e) {
String errorMessage = null;
if (algorithm != null && algorithm.getErrors() != null && !algorithm.getErrors().isEmpty()) {
errorMessage = algorithm.getErrors().get(0);
}
if (errorMessage == null) {
errorMessage = e.toString();
}
if (errorMessage == null) {
errorMessage = "UNKNOWN ERROR";
}
LOGGER.error("Exception/Error while executing ExecuteRequest for " + getAlgorithmIdentifier() + ": " + errorMessage);
updateStatusError(errorMessage);
if (e instanceof Error) {
// This is required when catching Error
throw (Error)e;
}
if (e instanceof ExceptionReport) {
throw (ExceptionReport)e;
} else {
throw new ExceptionReport("Error while executing the embedded process for: " + getAlgorithmIdentifier(), ExceptionReport.NO_APPLICABLE_CODE, e);
}
} finally {
// you ***MUST*** call this or else you will have a PermGen ClassLoader memory leak due to ThreadLocal use
ExecutionContextFactory.unregisterContext();
if (algorithm instanceof ISubject) {
((ISubject)algorithm).removeObserver(this);
}
if (inputMap != null) {
for(List<IData> l : inputMap.values()) {
for (IData d : l) {
if (d instanceof IComplexData) {
((IComplexData)d).dispose();
}
}
}
}
if (returnResults != null) {
for (IData d : returnResults.values()) {
if (d instanceof IComplexData) {
((IComplexData)d).dispose();
}
}
}
}
ExecuteResponse response = new ExecuteResponse(this);
return response;
}
/**
* Gets the identifier of the algorithm the client requested
*
* @return An identifier
*/
public String getAlgorithmIdentifier() {
//Fix for bug https://bugzilla.52north.org/show_bug.cgi?id=906
if(getExecute().getIdentifier() != null){
return getExecute().getIdentifier().getStringValue();
}
return null;
}
/**
* Gets the Execute that is associated with this Request
*
* @return The Execute
*/
public Execute getExecute() {
return execDom.getExecute();
}
public Map<String, IData> getAttachedResult() {
return returnResults;
}
public boolean isStoreResponse() {
if (execDom.getExecute().getResponseForm() == null) {
return false;
}
if (execDom.getExecute().getResponseForm().getRawDataOutput() != null) {
return false;
}
return execDom.getExecute().getResponseForm().getResponseDocument()
.getStoreExecuteResponse();
}
public boolean isQuickStatus() {
if (execDom.getExecute().getResponseForm() == null) {
return false;
}
if (execDom.getExecute().getResponseForm().getRawDataOutput() != null) {
return false;
}
return execDom.getExecute().getResponseForm().getResponseDocument()
.getStatus();
}
public ExecuteResponseBuilder getExecuteResponseBuilder() {
return this.execRespType;
}
public boolean isRawData() {
if (execDom.getExecute().getResponseForm() == null) {
return false;
}
if (execDom.getExecute().getResponseForm().getRawDataOutput() != null) {
return true;
} else {
return false;
}
}
public void update(ISubject subject) {
Object state = subject.getState();
LOGGER.info("Update received from Subject, state changed to : " + state);
StatusType status = StatusType.Factory.newInstance();
int percentage = 0;
if (state instanceof Integer) {
percentage = (Integer) state;
status.addNewProcessStarted().setPercentCompleted(percentage);
}else if(state instanceof String){
status.addNewProcessStarted().setStringValue((String)state);
}
updateStatus(status);
}
public void updateStatusAccepted() {
StatusType status = StatusType.Factory.newInstance();
status.setProcessAccepted("Process Accepted");
updateStatus(status);
}
public void updateStatusStarted() {
StatusType status = StatusType.Factory.newInstance();
status.addNewProcessStarted().setPercentCompleted(0);
updateStatus(status);
}
public void updateStatusSuccess() {
StatusType status = StatusType.Factory.newInstance();
status.setProcessSucceeded("Process successful");
updateStatus(status);
}
public void updateStatusError(String errorMessage) {
StatusType status = StatusType.Factory.newInstance();
net.opengis.ows.x11.ExceptionReportDocument.ExceptionReport excRep = status
.addNewProcessFailed().addNewExceptionReport();
excRep.setVersion("1.0.0");
ExceptionType excType = excRep.addNewException();
excType.addNewExceptionText().setStringValue(errorMessage);
excType.setExceptionCode(ExceptionReport.NO_APPLICABLE_CODE);
updateStatus(status);
}
private void updateStatus(StatusType status) {
getExecuteResponseBuilder().setStatus(status);
try {
getExecuteResponseBuilder().update();
if (isStoreResponse()) {
ExecuteResponse executeResponse = new ExecuteResponse(this);
InputStream is = null;
try {
is = executeResponse.getAsStream();
DatabaseFactory.getDatabase().storeResponse(
getUniqueId().toString(), is);
} finally {
IOUtils.closeQuietly(is);
}
}
} catch (ExceptionReport e) {
LOGGER.error("Update of process status failed.", e);
throw new RuntimeException(e);
}
}
private void storeRequest(ExecuteDocument executeDocument) {
InputStream is = null;
try {
is = executeDocument.newInputStream();
DatabaseFactory.getDatabase().insertRequest(
getUniqueId().toString(), is, true);
} catch (Exception e) {
LOGGER.error("Exception storing ExecuteRequest", e);
} finally {
IOUtils.closeQuietly(is);
}
}
private void storeRequest(CaseInsensitiveMap map) {
BufferedWriter w = null;
ByteArrayOutputStream os = null;
ByteArrayInputStream is = null;
try {
os = new ByteArrayOutputStream();
w = new BufferedWriter(new OutputStreamWriter(os));
for (Object key : map.keySet()) {
Object value = map.get(key);
String valueString = "";
if(value instanceof String[]){
valueString = ((String[])value)[0];
}else{
valueString = value.toString();
}
w.append(key.toString()).append('=').append(valueString);
w.newLine();
}
w.flush();
is = new ByteArrayInputStream(os.toByteArray());
DatabaseFactory.getDatabase().insertRequest(
getUniqueId().toString(), is, false);
} catch (Exception e) {
LOGGER.error("Exception storing ExecuteRequest", e);
} finally {
IOUtils.closeQuietly(w);
IOUtils.closeQuietly(os);
IOUtils.closeQuietly(is);
}
}
}