aboutsummaryrefslogtreecommitdiff
path: root/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java')
-rw-r--r--spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java464
1 files changed, 464 insertions, 0 deletions
diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java
new file mode 100644
index 000000000..6bf2317b4
--- /dev/null
+++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2003 Federal Chancellery Austria
+ * MOA-SPSS has been developed in a cooperation between BRZ, the Federal
+ * Chancellery Austria - ICT staff unit, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+
+
+package at.gv.egovernment.moa.spss.server.service;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.attachments.AttachmentPart;
+import org.apache.axis.handlers.BasicHandler;
+import org.apache.axis.transport.http.HTTPConstants;
+import org.apache.axis.utils.Messages;
+import org.apache.axis.utils.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import at.gv.egovernment.moa.logging.LogMsg;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.logging.LoggingContext;
+import at.gv.egovernment.moa.logging.LoggingContextManager;
+import at.gv.egovernment.moa.spss.MOASystemException;
+import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider;
+import at.gv.egovernment.moa.spss.server.transaction.TransactionContext;
+import at.gv.egovernment.moa.spss.server.transaction.TransactionContextManager;
+import at.gv.egovernment.moa.spss.server.transaction.TransactionIDGenerator;
+import at.gv.egovernment.moa.spss.util.MessageProvider;
+import at.gv.egovernment.moa.util.DOMUtils;
+
+/**
+ * An handler that is invoked on each web service request and performs some
+ * central message handling.
+ *
+ * Mainly sets up the <code>TransactionContext</code> for the current
+ * transaction (i.e. web service request).
+ *
+ * @author Patrick Peck
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class AxisHandler extends BasicHandler {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2520698947819506866L;
+
+/** The resource names of the messages to load. */
+ private static final String MOA_SPSS_WSDL_RESOURCE_ = "/resources/wsdl/MOA-SPSS-1.3.wsdl";
+
+ /** The property name for accessing the HTTP request. */
+ private static final String REQUEST_PROPERTY = HTTPConstants.MC_HTTP_SERVLETREQUEST;
+
+ /** The property name for accessing the X509 client certificate chain. */
+ private static final String X509_CERTIFICATE_PROPERTY = "javax.servlet.request.X509Certificate";
+
+ /** The property name for accessing the SOAP action header. */
+ private static final String SOAP_ACTION_HEADER = "soapaction";
+
+ /** URI of the SOAP XML namespace. */
+ public static final String SOAP_NS_URI = "http://schemas.xmlsoap.org/soap/envelope/";
+
+ /** Prefix used for the SOAP XML namespace */
+ public static final String SOAP_PREFIX = "soapenv";
+
+ /** Simple string contains the front part of the enveloping SOAP wrapping */
+ private static final String SOAP_PART_PRE = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body>";
+
+ /** Simple string contains the post part of the enveloping SOAP wrapping */
+ private static final String SOAP_PART_POST = "</soapenv:Body></soapenv:Envelope>";
+
+ /**
+ * Handle an invocation of this handler.
+ *
+ * @param msgContext Information about this request/response.
+ * @throws AxisFault An error occurred during processing of the request.
+ * @see org.apache.axis.Handler#invoke(MessageContext)
+ */
+ public void invoke(MessageContext msgContext) throws AxisFault {
+ if (!msgContext.getPastPivot()) {
+ handleRequest(msgContext);
+ } else {
+ handleResponse(msgContext);
+ }
+ }
+
+ /**
+ * This method is called by <code>invoke</code> to handle incoming requests.
+ *
+ * @param msgContext The context as provided to <code>invoke</code>.
+ * @throws AxisFault An error occurred during processing of the request.
+ */
+ private void handleRequest(MessageContext msgContext) throws AxisFault {
+ try {
+ Logger.trace("---- Entering Axishandler");
+ // generate a unique transaction id and build the TransactionContext
+ // for this request
+ HttpServletRequest request =
+ (HttpServletRequest) msgContext.getProperty(REQUEST_PROPERTY);
+
+ X509Certificate[] clientCert =
+ (X509Certificate[]) request.getAttribute(X509_CERTIFICATE_PROPERTY);
+
+ //Configure Axis
+// AxisProperties.setProperty(AxisEngine.PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION,"false");
+// AxisProperties.setProperty(AxisEngine.PROP_DOMULTIREFS,"false");
+// AxisProperties.setProperty(AxisEngine.PROP_SEND_XSI,"true");
+ //msgContext.setProperty(org.apache.axis.SOAPPart.ALLOW_FORM_OPTIMIZATION, Boolean.FALSE);
+ //msgContext.setProperty(org.apache.axis. AxisEngine.PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION,"false");
+
+ Message soapMessage = msgContext.getCurrentMessage();
+
+ ConfigurationProvider configuration =
+ ConfigurationProvider.getInstance();
+
+ Element xmlRequest = null;
+ //log.info(soapMessage.getSOAPPartAsString());
+ Element soapPart = DOMUtils.parseDocument(new ByteArrayInputStream(soapMessage.getSOAPPartAsBytes()), false, null, null).getDocumentElement();
+ if (soapPart!=null) {
+ //TODO: check if DOM Version is intolerant when white spaces are between tags (preceding normalization would be necessary)
+ NodeList soapBodies = soapPart.getElementsByTagNameNS(SOAP_NS_URI, "Body");
+ if (soapBodies!=null && soapBodies.getLength()>0) {
+ xmlRequest = DOMUtils.getElementFromNodeList(soapBodies.item(0).getChildNodes());
+ }
+ //oder TODO: Evaluierung ob XPATH schneller
+ /*
+ HashMap nSMap = new HashMap();
+ nSMap.put((String)SOAP_PREFIX, SOAP_NS_URI);
+ Element soapBody = (Element) XPathUtils.selectSingleNode(soapPart, nSMap, "/"+SOAP_PREFIX+":Envelope/"+SOAP_PREFIX+":Body");
+ if (soapBody!=null) {
+ xmlRequest = DOMUtils.getElementFromNodeList(soapBody.getChildNodes());
+ }
+ */
+ }
+
+ TransactionContext context =
+ new TransactionContext(
+ TransactionIDGenerator.nextID(),
+ clientCert,
+ configuration,
+ xmlRequest,
+ null);
+
+ String soapAction = (String) request.getHeader(SOAP_ACTION_HEADER);
+ if ("\"\"".equals(soapAction)) {
+ // if http soap action header is empty
+ soapAction = msgContext.getTargetService();
+ }
+ context.setRequestName(soapAction);
+
+ Logger.trace(">>> Get AttachmentCount");
+ int attachmentCount = soapMessage.getAttachmentsImpl().getAttachmentCount();
+ Logger.trace("<<< Finished Get AttachmentCount");
+ if (attachmentCount>0) {
+
+ // add SOAP attachments to transaction context
+ Iterator iterator = soapMessage.getAttachments();
+ while (iterator.hasNext()) {
+ AttachmentPart attachment = (AttachmentPart)iterator.next();
+ String id = attachment.getContentId();
+ String type = attachment.getContentType();
+
+ //Now get the InputStream (note: we could also get the content with Object content = attachment.getContent();)
+ InputStream is = null;
+ javax.activation.DataHandler datahandler = attachment.getDataHandler();
+
+ int TYPE = 2;
+ switch (TYPE) {
+ case 1:
+ {
+ org.apache.axis.attachments.ManagedMemoryDataSource mmds = (org.apache.axis.attachments.ManagedMemoryDataSource)datahandler.getDataSource();
+ context.addAttachment(id, type, mmds);
+ break;
+ }
+ case 2:
+ {
+ is = datahandler.getDataSource().getInputStream();
+ context.addAttachment(id, type, is, datahandler.getDataSource().getName());
+ break;
+ }
+ }
+ debug("handler.06", new Object[] {id, type});
+ }
+ }
+
+ setUpContexts(context);
+
+ // log some information about the request
+ info(
+ "handler.00",
+ new Object[] {
+ context.getTransactionID(),
+ msgContext.getTargetService()});
+ info("handler.01", new Object[] { request.getRemoteAddr()});
+ if (clientCert != null) {
+ info(
+ "handler.02",
+ new Object[] {
+ clientCert[0].getSubjectDN(),
+ clientCert[0].getSerialNumber(),
+ clientCert[0].getIssuerDN()});
+
+ } else {
+ info("handler.03", null);
+ }
+ if (Logger.isTraceEnabled()) {
+// OutputFormat format = new OutputFormat((Document) xmlRequest.getOwnerDocument());
+// format.setLineSeparator("\n");
+// format.setIndenting(false);
+// format.setPreserveSpace(true);
+// format.setOmitXMLDeclaration(false);
+// format.setEncoding("UTF-8");
+// ByteArrayOutputStream baos = new ByteArrayOutputStream();
+// XMLSerializer conSerializer = new XMLSerializer(baos, format);
+// conSerializer.serialize(xmlRequest);
+// Logger.debug(new LogMsg("Request:" + baos.toString()));
+
+
+ String msg = soapMessage.getSOAPPartAsString();
+ Logger.trace(new LogMsg(msg));
+ }
+ } catch (MOASystemException e) {
+ MOASystemException se = new MOASystemException("2900", null, e);
+ AxisFault fault = AxisFault.makeFault(se);
+ fault.setFaultDetail(new Element[] { se.toErrorResponse()});
+ throw fault;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ Logger.info(new LogMsg(t.getStackTrace()));
+ MOASystemException e = new MOASystemException("2900", null, t);
+ AxisFault fault = AxisFault.makeFault(e);
+ fault.setFaultDetail(new Element[] { e.toErrorResponse()});
+ throw fault;
+ }
+ Logger.trace("---- Leaving Axishandler");
+ }
+
+ /**
+ * This method is called by <code>invoke</code> to handle outgoing
+ * responses.
+ *
+ * @param msgContext The context as provided to <code>invoke</code>.
+ * @throws AxisFault An error occurred during processing of the response.
+ */
+ private void handleResponse(MessageContext msgContext) throws AxisFault {
+ String xmlResponseString = null;
+ String soapResponseString = null;
+
+ TransactionContext context = TransactionContextManager.getInstance().getTransactionContext();
+ Element xmlResponse = context.getResponse();
+
+ if (xmlResponse!=null) {
+ try {
+ xmlResponseString = DOMUtils.serializeNode(xmlResponse, true);
+ /*
+ Soll die Antwort nur \n enthalten, so gibt es 2 Möglichkeiten:
+ 1.) höhere Xalan Version und
+ xmlResponseString = DOMUtils.serializeNode(xmlResponse, true, "\n");
+ 2.)
+ OutputFormat serializerFormat = new OutputFormat((Document) xmlResponse.getOwnerDocument());
+ serializerFormat.setLineSeparator("\n");
+ serializerFormat.setIndenting(false);
+ serializerFormat.setPreserveSpace(true);
+ serializerFormat.setOmitXMLDeclaration(true);
+ serializerFormat.setEncoding("UTF-8");
+ ByteArrayOutputStream serializedBytes = new ByteArrayOutputStream();
+ XMLSerializer serializer = new XMLSerializer(serializedBytes, serializerFormat);
+ serializer.serialize(xmlResponse);
+ serializedBytes.close();
+ xmlResponseString = serializedBytes.toString("UTF-8");
+ */
+ if (Logger.isTraceEnabled()) {
+ Logger.trace(new LogMsg(xmlResponseString));
+ }
+ soapResponseString = SOAP_PART_PRE + xmlResponseString + SOAP_PART_POST;
+ //override axis response-message
+ msgContext.setResponseMessage(new Message(soapResponseString));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ Logger.info(new LogMsg(t.getStackTrace()));
+ MOASystemException e = new MOASystemException("2900", null, t);
+ AxisFault fault = AxisFault.makeFault(e);
+ fault.setFaultDetail(new Element[] { e.toErrorResponse()});
+ throw fault;
+ }
+
+ } else {
+ //Fallback: if functions do not set the resulting response in the transaction, the original one from axis will be used
+ soapResponseString = msgContext.getCurrentMessage().getSOAPPartAsString();
+ }
+
+ info("handler.04", null);
+ if (Logger.isDebugEnabled()) {
+ Logger.debug(new LogMsg(soapResponseString));
+ }
+ tearDownContexts();
+ }
+
+ /**
+ * Called, when the processing of the web service fails.
+ *
+ * @param msgContext Information about the current request.
+ * @see org.apache.axis.Handler#onFault(org.apache.axis.MessageContext)
+ */
+ public void onFault(MessageContext msgContext) {
+ info("handler.05", null);
+ tearDownContexts();
+ }
+
+ /**
+ * Set up the thread-local contexts (<code>TransactionContext</code> and
+ * <code>LoggingContext</code>).
+ *
+ * @param context The <code>TransactionContext</code> to set for the current
+ * request.
+ */
+ private void setUpContexts(TransactionContext context) {
+ // set the transaction context in the TransactionContextManager
+ TransactionContextManager tcm = TransactionContextManager.getInstance();
+ tcm.setTransactionContext(context);
+
+ // set the logging context in the LoggingContextManager
+ LoggingContextManager lcm = LoggingContextManager.getInstance();
+ LoggingContext lc = new LoggingContext(context.getTransactionID());
+ lcm.setLoggingContext(lc);
+ }
+
+ /**
+ * Tear down the thread-local contexts.
+ */
+ private void tearDownContexts() {
+ TransactionContextManager tcm = TransactionContextManager.getInstance();
+
+ //delete temporary files
+ TransactionContext context = tcm.getTransactionContext();
+ context.cleanAttachmentCache();
+
+ // unset the transaction context
+ tcm.setTransactionContext(null);
+
+ // unset the logging context
+ LoggingContextManager lcm = LoggingContextManager.getInstance();
+ lcm.setLoggingContext(null);
+ }
+
+ /**
+ * Generate the WSDL into the <code>msgContext</code>.
+ *
+ * The code of this method is more or less copied from the
+ * <code>org.apache.axis.handlers.soap.SOAPService</code> class contained in
+ * the 1.1 release of Axis to allow for a missing <code>wsdlFile</code> (so
+ * that a resource by the same name is searched for in the classpath). The
+ * implementation of this method should be obsolete if Axis 1.1 or higher is
+ * used.
+ *
+ * @param msgContext The <code>MessageContext</code> that will contain the
+ * WSDL description of the current web service.
+ * @throws AxisFault An error occurred producing the WSDL.
+ */
+ public void generateWSDL(MessageContext msgContext) throws AxisFault {
+ InputStream instream = null;
+
+ try {
+ String filename = MOA_SPSS_WSDL_RESOURCE_;
+ File file = new File(filename);
+ if (file.exists()) {
+ //if this resolves to a file, load it
+ instream = new FileInputStream(filename);
+ } else {
+ //else load a named resource in our classloader.
+ instream = this.getClass().getResourceAsStream(filename);
+ if (instream == null) {
+ String errorText = Messages.getMessage("wsdlFileMissing", filename);
+ throw new AxisFault(errorText);
+ }
+ }
+ Document doc = XMLUtils.newDocument(instream);
+ msgContext.setProperty("WSDL", doc);
+ } catch (Exception e) {
+ throw AxisFault.makeFault(e);
+ } finally {
+ if (instream != null) {
+ try {
+ instream.close();
+ } catch (IOException e) {
+ // ok to do nothing here
+ }
+ }
+ }
+ }
+
+ /**
+ * Utility function to issue an info message to the log.
+ *
+ * @param messageId The ID of the message to log.
+ * @param parameters Additional message parameters.
+ */
+ private static void info(String messageId, Object[] parameters) {
+ MessageProvider msg = MessageProvider.getInstance();
+
+ Logger.info(new LogMsg(msg.getMessage(messageId, parameters)));
+ }
+
+ /**
+ * Utility function to issue an debug message to the log.
+ *
+ * @param messageId The ID of the message to log.
+ * @param parameters Additional message parameters.
+ */
+ private static void debug(String messageId, Object[] parameters) {
+ MessageProvider msg = MessageProvider.getInstance();
+
+ Logger.debug(new LogMsg(msg.getMessage(messageId, parameters)));
+ }
+
+
+
+// private byte[] toByteArray(AttachmentPart attachment) throws SOAPException, IOException
+// {
+// ByteArrayOutputStream outputStream = new ByteArrayOutputStream(attachment.getSize());
+// InputStream inputStream = (InputStream) attachment.getContent();
+// int currentByte = -1;
+// while ((currentByte = inputStream.read()) != -1)
+// outputStream.write(currentByte);
+//
+// inputStream.close();
+// outputStream.close();
+//
+// return outputStream.toByteArray();
+//
+//}
+
+} \ No newline at end of file