/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community 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.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003 - 2010 Peter Baumann / rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
package petascope.wcst.server;
import petascope.ConfigManager;
import net.opengis.ows.v_1_0_0.ExceptionReport;
import petascope.exceptions.PetascopeException;
import petascope.exceptions.RasdamanException;
import petascope.exceptions.WCPSException;
import petascope.exceptions.WCSTException;
import petascope.wcst.transaction.ServiceFirewall;
import petascope.wcst.transaction.executeAsyncTransaction;
import petascope.wcst.transaction.executeTransaction;
import wcst.transaction.schema.AcknowledgementType;
import wcst.transaction.schema.TransactionResponseType;
import wcst.transaction.schema.TransactionType;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import petascope.PetascopeXmlNamespaceMapper;
import petascope.core.DbMetadataSource;
import petascope.exceptions.WCSException;
import petascope.exceptions.ExceptionCode;
/**
* The Web Coverage Service, with the Transactional extension (WcstServer)
*
* @author Andrei Aiordachioaie
*/
public class WcstServer {
private static Logger log = LoggerFactory.getLogger(WcstServer.class);
private static Boolean finished;
private boolean synchronous = true;
private String responseHandler;
private DbMetadataSource meta;
/**
* Public minimal constructor
*/
public WcstServer(DbMetadataSource source) throws WCSException {
finished = false;
meta = source;
/* Check user settings */
String cfg = ConfigManager.WCST_DEFAULT_DATATYPE;
if (source.getDataTypes().contains(cfg) == false) {
throw new WCSException(ExceptionCode.InvalidPropertyValue, "The following setting is not a valid datatype: " + cfg);
}
cfg = ConfigManager.WCST_DEFAULT_INTERPOLATION;
if (source.getInterpolationTypes().contains(cfg) == false) {
throw new WCSException(ExceptionCode.InvalidPropertyValue, "The following setting is not a valid interpolation method: " + cfg);
}
cfg = ConfigManager.WCST_DEFAULT_NULL_RESISTANCE;
if (source.getNullResistances().contains(cfg) == false) {
throw new WCSException(ExceptionCode.InvalidPropertyValue, "The following setting is not a valid null resistance: " + cfg);
}
}
/**
* Web service operation
*/
public String Transaction(String stringXml) throws WCSTException, RasdamanException, WCPSException, PetascopeException {
// Actual contents of these two strings do not matter
String output = "Default output. ";
String errmsg = "No error. ";
finished = false;
try {
try {
// Check if Firewall allows the query
if (ServiceFirewall.reject(stringXml)) {
throw new WCSException(ExceptionCode.MaliciousQuery, "WCS-T Service Firewall "
+ "refused to run possibly malitious query.");
}
// read the input XML
log.debug("Reading the input XML file ... ");
JAXBContext context = JAXBContext.newInstance(
TransactionType.class.getPackage().getName());
Unmarshaller unmarshaller = context.createUnmarshaller();
Object xml = unmarshaller.unmarshal(new StringReader(stringXml));
if (xml instanceof JAXBElement) {
xml = ((JAXBElement) xml).getValue();
}
TransactionType input = (TransactionType) xml;
/**
* We can work in both asynchronous and synchronous mode.
*
* If we are in async mode, we generate an acknowledgement that
* we have received the Transaction request. Next, when we finish processing,
* we send the output (as a String) to the specified responseHandler.
*
* In synchronous mode, we just do the processing and output
* the result.
*/
if (input.getResponseHandler() == null) {
synchronous = true;
responseHandler = null;
} else {
synchronous = false;
responseHandler = input.getResponseHandler();
}
executeTransaction exec = new executeTransaction(input, meta);
/** Synchronous operation */
if (synchronous == true) {
TransactionResponseType response = null;
exec.get();
JAXBElement jaxbOutput =
new JAXBElement(
new QName("http://www.opengis.net/wcs/1.1/wcst",
"TransactionResponse", XMLConstants.DEFAULT_NS_PREFIX),
TransactionResponseType.class, response);
// Write the output xml to a string
log.debug("Marshalling with context: " + response.getClass().getPackage().getName());
final StringWriter writer = new StringWriter();
try {
context = JAXBContext.newInstance(response.getClass());
final XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
final Marshaller marshaller = context.createMarshaller();
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new PetascopeXmlNamespaceMapper());
marshaller.setProperty("jaxb.formatted.output", true);
marshaller.setProperty("jaxb.schemaLocation", "http://www.opengis.net/wcs/1.1/wcst http://schemas.opengis.net/wcst/ "
+ "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.0.0/owsExceptionReport.xsd");
marshaller.marshal(jaxbOutput, xmlStreamWriter);
} catch (final Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
output = writer.toString();
log.debug("Done! User has the TransactionResponse result !");
} else /** Asynchronous operation */
{
/* (1) Create acknowledgement that we received the request */
AcknowledgementType ack = new AcknowledgementType();
GregorianCalendar c = new GregorianCalendar();
c.setTime(new Date());
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
ack.setTimeStamp(date2);
ack.setOperationRequest(input);
ack.setRequestId(exec.generateRequestId());
JAXBElement jaxbOutput = new JAXBElement(new QName("", "Acknowledgement"),
TransactionResponseType.class, ack);
/* (2) Write the acknowledgement to a string */
JAXBContext jaxbCtx = JAXBContext.newInstance(
ack.getClass().getPackage().getName());
Marshaller marshaller = jaxbCtx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter strWriter = new StringWriter();
marshaller.marshal(jaxbOutput, strWriter);
output = strWriter.toString();
log.debug("Created the acknowledgement of the request !");
log.debug("Now starting to asynchronously execute the transaction...");
/* (3) Start asynchronous processing */
executeAsyncTransaction execAsync = new executeAsyncTransaction(exec,
responseHandler);
execAsync.start();
}
finished = true;
} catch (JAXBException e) {
throw new WCSException(ExceptionCode.XmlStructuresError, "Could not marshall/unmarshall XML structures.", e);
} catch (DatatypeConfigurationException e) {
throw new WCSException(ExceptionCode.XmlStructuresError, "Could not build request acknowledgement. ", e);
}
} catch (WCSException e) {
log.info("Caught WCST Exception");
ExceptionReport report = e.getReport();
try {
JAXBContext jaxbCtx = JAXBContext.newInstance(
report.getClass().getPackage().getName());
Marshaller marshaller = jaxbCtx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter strWriter = new StringWriter();
marshaller.marshal(report, strWriter);
output = strWriter.toString();
finished = true;
log.error("WCS-T Exception: " + e.getExceptionCode() + ", with message '"
+ e.getExceptionText() + "'");
log.debug("Done with the Error Report !");
} catch (JAXBException e2) {
errmsg = e2.getMessage();
log.error("Could not build XML error report. Stack trace: " + e2);
}
}
if (finished == false) {
output = errmsg;
}
return output;
}
}