package org.uncertweb.ps.handler.soap; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import org.apache.log4j.Logger; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import org.uncertweb.ps.ClientException; import org.uncertweb.ps.ServiceException; import org.uncertweb.ps.data.ProcessOutputs; import org.uncertweb.ps.data.Request; import org.uncertweb.ps.data.Response; import org.uncertweb.ps.handler.RequestParseException; import org.uncertweb.ps.handler.ResponseGenerateException; import org.uncertweb.ps.process.AbstractProcess; import org.uncertweb.ps.process.ProcessException; import org.uncertweb.ps.process.ProcessRepository; import org.uncertweb.util.Stopwatch; import org.uncertweb.xml.Namespaces; import org.uncertweb.xml.SoapBody; import org.uncertweb.xml.SoapEnvelope; import org.uncertweb.xml.SoapFault; import org.uncertweb.xml.SoapFault.Code; public class SOAPHandler { private final Logger logger = Logger.getLogger(SOAPHandler.class); public void handleRequest(InputStream inputStream, OutputStream outputStream) { // response envelope + body SoapEnvelope responseEnvelope = new SoapEnvelope(); SoapBody responseBody = new SoapBody(); responseEnvelope.addContent(responseBody); try { // build request document logger.debug("Parsing request document..."); Stopwatch stopwatch = new Stopwatch(); DocumentBuilder builder = new DocumentBuilder(); Document reqSoapDocument = builder.build(inputStream); logger.debug("Parsed document in " + stopwatch.getElapsedTime() + "."); // validate ValidationResult validationResult = builder.getValidationResult(); if (!validationResult.isValid()) { throw new ClientException("Request document failed schema validation.", validationResult.getPrettierResult()); } // parse request List<?> bodyChildren = reqSoapDocument.getRootElement().getChild("Body", Namespaces.SOAPENV).getChildren(); Element requestElement = (Element)bodyChildren.get(0); Request request = XMLRequestParser.parse(requestElement); // find process AbstractProcess process = ProcessRepository.getInstance().getProcess(request.getProcessIdentifier()); // run process ProcessOutputs outputs = process.run(request.getInputs()); // build response Response response = new Response(process.getIdentifier(), outputs); // generate response element Element responseElement = XMLResponseGenerator.generate(response, request.getRequestedOutputs()); responseBody.addContent(responseElement); // TODO: remove post validation /* try { // create validator and set handler ValidationErrorHandler respHandler = new ValidationErrorHandler(); builder.setErrorHandler(respHandler); // validate and return result builder.build(new StringReader(new XMLOutputter().outputString(new Document(responseEnvelope)))); ValidationResult respValResult = respHandler.getResult(); if (!respValResult.isValid()) { LOGGER.error("Generated an invalid response document (" + respValResult.getPrettierResult() + ")."); //throw new ServiceException("Generated an invalid response document.", respValResult.getPrettierResult()); } } catch (IOException e) { LOGGER.error("Couldn't validate response document", e); //throw new ServiceException("Couldn't validate response document.", e.getClass().getSimpleName() + ": " + e.getMessage()); } catch (JDOMException e) { LOGGER.error("Couldn't validate response document", e); //throw new ServiceException("Couldn't validate response document.", e.getClass().getSimpleName() + ": " + e.getMessage()); }*/ } catch (Exception e) { handleException(e, responseBody); } // output try { XMLOutputter outputter = new XMLOutputter(Format.getCompactFormat()); outputter.output(new Document(responseEnvelope), outputStream); } catch (Throwable t) { // TODO: panic, soapmessage or transformer could be null as well! } finally { try { outputStream.close(); } catch (IOException e) { // not much else we can do here } } } private void handleException(Exception e, SoapBody responseBody) { if (e instanceof IOException) { logger.error("Couldn't read request from stream.", e); responseBody.removeContent(); responseBody.addContent(new SoapFault(Code.Server, "Couldn't read request.")); } else if (e instanceof ClientException) { logger.error("Client exception.", e); responseBody.removeContent(); responseBody.addContent(new SoapFault(Code.Client, e.getMessage(), ((ClientException)e).getDetail())); } else if (e instanceof ServiceException) { logger.error("Service exception.", e); responseBody.removeContent(); responseBody.addContent(new SoapFault(Code.Server, e.getMessage(), ((ServiceException)e).getDetail())); } else if (e instanceof ProcessException) { logger.error("Failed to execute process.", e); responseBody.removeContent(); String message = "Failed to execute process"; if (e.getMessage() != null) { message += ": " + e.getMessage(); } else { message += "."; } SoapFault fault = new SoapFault(Code.Server, message); if (e.getCause() != null) { fault.setDetail(e.getCause().getMessage()); } responseBody.addContent(fault); } else if (e instanceof JDOMException) { logger.error("Problem reading/generating request/response.", e); responseBody.removeContent(); responseBody.addContent(new SoapFault(Code.Server, "Problem reading/generating request/response.")); } else if (e instanceof RequestParseException) { logger.error("Couldn't parse request.", e); responseBody.removeContent(); responseBody.addContent(new SoapFault(Code.Server, "Couldn't parse request.")); } else if (e instanceof ResponseGenerateException) { logger.error("Couldn't generate response.", e); responseBody.removeContent(); responseBody.addContent(new SoapFault(Code.Server, "Couldn't generate response.")); } else if (e instanceof RuntimeException) { logger.error("Failed to handle request.", e); responseBody.removeContent(); String message = "Failed to handle request."; if (e.getMessage() != null) { message += ": " + e.getMessage(); } else { message += "."; } responseBody.addContent(new SoapFault(Code.Server, message)); } } }