diff options
Diffstat (limited to 'spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss')
9 files changed, 958 insertions, 0 deletions
diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/Constants.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/Constants.java new file mode 100644 index 000000000..c6ea9e88d --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/Constants.java @@ -0,0 +1,55 @@ +/* + * Created on 18.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class Constants +{ + // System properties + public static final String SP_INIT_PROPS_LOC_ = + "at.gv.egovernment.moa.spss.slinterface.PropertiesLocation"; + + // Init properties + public static final String IP_SL2MOA_STYLESHEET_ = "location.stylesheet.sl2moa"; + public static final String IP_MOA2SL_STYLESHEET_ = "location.stylesheet.moa2sl"; + public static final String IP_SL_SCHEMA_ = "location.schema.sl"; + public static final String IP_MOA_SCHEMA_ = "location.schema.moa"; + public static final String IP_SP_ENDPOINT_ = "service.endpoint.sp"; + + // Logging hierarchies + + public static final String LH_BASE_ = "slinterface"; + public static final String LH_LISTENERS_ = LH_BASE_ + ".listeners"; + public static final String LH_FILTERS_ = LH_BASE_ + ".filters"; + public static final String LH_SERVLETS_ = LH_BASE_ + ".servlets"; + + // Web service context parameters + + public static final String WSCP_INIT_PROPS_ = "initProperties"; + public static final String WSCP_SL2MOA_TRANSFORMER_ = "sl2MoaTransformer"; + public static final String WSCP_MOA2SL_TRANSFORMER_ = "moa2SlTransformer"; + public static final String WSCP_XMLPARSER_ = "xmlParser"; + + // Security-Layer constants + + public static final String SLC_NAME_HTTP_REQUEST_ = "http-security-layer-request"; + public static final String SLC_NAME_XML_REQUEST_ = "XMLRequest"; + public static final String SLC_NAME_DATA_URL_ = "DataURL"; + public static final String SLC_NAME_STYLESHEET_URL_ = "StylesheetURL"; + public static final String SLC_NAME_REDIRECT_URL_ = "RedirectURL"; + + // Namespace URIs + + public static final String NSURI_SL_11_ = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#"; + public static final String NSURI_SL_12_ = "http://www.buergerkarte.at/namespaces/securitylayer/20031231#"; + public static final String NSURI_MOA_12_ = "http://reference.e-government.gv.at/namespace/moa/20020822#"; + + // MOA invoker constants + + public static final String MI_SP_QNAME_ = "SignatureVerification"; +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/RequestWrapper.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/RequestWrapper.java new file mode 100644 index 000000000..a6652a56e --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/RequestWrapper.java @@ -0,0 +1,57 @@ +/* + * Created on 19.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.filters; + +import java.io.ByteArrayInputStream; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class RequestWrapper extends HttpServletRequestWrapper +{ + + private ServletInputStream inputStream_; + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Generates a request wrapper around a particular request. + * + * @param request The request to be wrapped. + * + * @param inputStream The new inputstream, which will be returned by method {@link #getInputStream}, and + * whose length will be returned by method {@link #getContentLength}. + */ + public RequestWrapper(HttpServletRequest request, ByteArrayInputStream inputStream) + { + super(request); + inputStream_ = new ServletInputStream(inputStream); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see #RequestWrapper(HttpServletRequest, ByteArrayInputStream) + */ + public javax.servlet.ServletInputStream getInputStream() + { + return inputStream_; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see #RequestWrapper(HttpServletRequest, ByteArrayInputStream) + */ + public int getContentLength() + { + return inputStream_.getContentLength(); + } + +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ResponseWrapper.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ResponseWrapper.java new file mode 100644 index 000000000..420723abb --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ResponseWrapper.java @@ -0,0 +1,44 @@ +/* + * Created on 18.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.filters; + +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class ResponseWrapper extends HttpServletResponseWrapper +{ + private ServletOutputStream outputStream_; + + /* ---------------------------------------------------------------------------------------------------- */ + + public ResponseWrapper(HttpServletResponse response) + { + super(response); + outputStream_ = new ServletOutputStream(); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public javax.servlet.ServletOutputStream getOutputStream() + { + return outputStream_; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Returns the wrapped response as a byte array. + * + * @return the response as a byte array. + */ + public byte[] toByteArray() + { + return outputStream_.toByteArray(); + } +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java new file mode 100644 index 000000000..4632c80f5 --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java @@ -0,0 +1,341 @@ +/* + * Created on 18.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.filters; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.CharArrayReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.fileupload.DiskFileUpload; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileUpload; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.log4j.Logger; +import org.apache.xerces.parsers.DOMParser; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +import at.gv.egovernment.moa.spss.slinterface.Constants; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class SL2MOAFilter implements Filter +{ + private static Logger logger_ = Logger.getLogger(Constants.LH_FILTERS_); + + private FilterConfig config_; + private SLRequest slRequest_; + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) + */ + public void init(FilterConfig config) throws ServletException + { + // Store filter configuration + config_ = config; + + slRequest_ = new SLRequest(); + + // Initialize stylesheet transform SL2MOA + ServletContext context = config_.getServletContext(); + Transformer sl2MoaTransformer = (Transformer) context.getAttribute(Constants.WSCP_SL2MOA_TRANSFORMER_); + if (sl2MoaTransformer == null) + { + initTransformer(context, Constants.IP_SL2MOA_STYLESHEET_); + } + + // Initialize stylesheet transform MOA2SL + Transformer moa2SlTransformer = (Transformer) context.getAttribute(Constants.WSCP_MOA2SL_TRANSFORMER_); + if (moa2SlTransformer == null) + { + initTransformer(context, Constants.IP_MOA2SL_STYLESHEET_); + } + + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /* + * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, + * javax.servlet.FilterChain) + */ + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + // Check if request is HTTP-POST + checkHttpPost((HttpServletRequest) request); + + // Get SL request from content of request + parseRequest((HttpServletRequest) request); + + // Schema validate SL request + CharArrayReader slXmlRequestCAR = new CharArrayReader(slRequest_.xmlRequest_.toCharArray()); + Document slXMLRequestDoc = parseSlXmlRequest(slXmlRequestCAR); + + // Transform SL request into a MOA SPSS request + Transformer sl2MoaTransformer = + (Transformer) config_.getServletContext().getAttribute(Constants.WSCP_SL2MOA_TRANSFORMER_); + DOMSource slXMLRequestDS = new DOMSource(slXMLRequestDoc); + ByteArrayOutputStream moaRequestBOS = new ByteArrayOutputStream(); + StreamResult moaRequestResult = new StreamResult(moaRequestBOS); + try + { + sl2MoaTransformer.transform(slXMLRequestDS, moaRequestResult); + } + catch (TransformerException e) + { + String message = "Transforming SL XML request into MOA XML request failed."; + logger_.error(message, e); + throw new ServletException(message, e); + } + logger_.debug("MOA XML Request:\n" + moaRequestBOS.toString()); + ByteArrayInputStream moaRequestIS = new ByteArrayInputStream(moaRequestBOS.toByteArray()); + + // Invoke MOA SPSS + RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest) request, moaRequestIS); + ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response); + chain.doFilter(requestWrapper, responseWrapper); + + // Prepare response to client + response.setContentType("text/xml"); + + // Transform MOA response into a SL response and send SL response back to client + Transformer moa2SlTransformer = + (Transformer) config_.getServletContext().getAttribute(Constants.WSCP_MOA2SL_TRANSFORMER_); + ServletOutputStream moaResponseSOS = (ServletOutputStream) responseWrapper.getOutputStream(); + ByteArrayInputStream moaResponseBIS = new ByteArrayInputStream(moaResponseSOS.toByteArray()); + StreamSource moaResponseSource = new StreamSource(moaResponseBIS); + StreamResult slResponseResult = new StreamResult(response.getOutputStream()); + try + { + moa2SlTransformer.transform(moaResponseSource, slResponseResult); + } + catch (TransformerException e) + { + String message = "Transforming MOA XML response into SL XML response failed."; + logger_.error(message, e); + throw new ServletException(message, e); + } + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see javax.servlet.Filter#destroy() + */ + public void destroy() + { + // Nothing to do here at the moment. + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private void initTransformer(ServletContext context, String initPropStylesheetLoc) throws ServletException + { + String stylesheetName = + (Constants.IP_SL2MOA_STYLESHEET_.equals(initPropStylesheetLoc)) + ? "sl2Moa" + : "moa2Sl"; + + String contextAttrName = + (Constants.IP_SL2MOA_STYLESHEET_.equals(initPropStylesheetLoc)) + ? Constants.WSCP_SL2MOA_TRANSFORMER_ + : Constants.WSCP_MOA2SL_TRANSFORMER_; + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Properties initProps = (Properties) context.getAttribute(Constants.WSCP_INIT_PROPS_); + String stylesheetLoc = initProps.getProperty(initPropStylesheetLoc); + InputStream stylesheetIS = context.getResourceAsStream(stylesheetLoc); + if (stylesheetIS == null) + { + String message = + "Cannot load " + stylesheetName + " stylesheet from location \"" + stylesheetLoc + "\"."; + logger_.error(message); + throw new ServletException(message); + } + Transformer transformer; + try + { + StreamSource stylesheetSS = new StreamSource(stylesheetIS); + transformer = transformerFactory.newTransformer(stylesheetSS); + } + catch (TransformerConfigurationException e) + { + String message = "Cannot create XSLT transformer with " + stylesheetName + " stylesheet."; + logger_.error(message, e); + throw new ServletException(message, e); + } + context.setAttribute(contextAttrName, transformer); + } + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Parses the http request. + */ + private void parseRequest(HttpServletRequest request) throws IOException + { + // Check if request URL ends with "http-security-layer-request" + // @TODO Don't know if this check is sufficient - spec says request URL must have this value as path + String requestURI = request.getRequestURI(); + if (!requestURI.endsWith(Constants.SLC_NAME_HTTP_REQUEST_)) + { + String message = "Request does not end with \"" + Constants.SLC_NAME_HTTP_REQUEST_ + "\"."; + logger_.error(message); + throw new IOException(message); + } + + if (FileUpload.isMultipartContent(request)) + { + // Request is encoded as mulitpart/form-data + List items; + try + { + DiskFileUpload upload = new DiskFileUpload(); + items = upload.parseRequest(request); + } + catch (FileUploadException e) + { + String message = "Cannot parse multipart/form-data request."; + logger_.error(message); + throw new IOException(message); + } + + Iterator itemsIt = items.iterator(); + while (itemsIt.hasNext()) + { + FileItem currItem = (FileItem) itemsIt.next(); + String currItemName = currItem.getFieldName(); + if (Constants.SLC_NAME_XML_REQUEST_.equals(currItemName)) + slRequest_.xmlRequest_ = currItem.getString(); + else if (Constants.SLC_NAME_DATA_URL_.equals(currItemName)) + slRequest_.dataUrl_ = currItem.getString(); + else if (Constants.SLC_NAME_STYLESHEET_URL_.equals(currItemName)) + slRequest_.stylesheetUrl_ = currItem.getString(); + else if (Constants.SLC_NAME_REDIRECT_URL_.equals(currItemName)) + slRequest_.redirectUrl_ = currItem.getString(); + else + continue; // @TODO Do not evaluate other params at the moment + } + } + else + { + // Request is encoded as application/x-www-form-urlencoded + Map paramsMap = request.getParameterMap(); + Iterator paramNames = paramsMap.keySet().iterator(); + while (paramNames.hasNext()) + { + String currName = (String) paramNames.next(); + String[] currValues = (String[]) paramsMap.get(currName); + if (Constants.SLC_NAME_XML_REQUEST_.equals(currName)) + slRequest_.xmlRequest_ = currValues[0]; + else if (Constants.SLC_NAME_DATA_URL_.equals(currName)) + slRequest_.dataUrl_ = currValues[0]; + else if (Constants.SLC_NAME_STYLESHEET_URL_.equals(currName)) + slRequest_.stylesheetUrl_ = currValues[0]; + else if (Constants.SLC_NAME_REDIRECT_URL_.equals(currName)) + slRequest_.redirectUrl_ = currValues[0]; + else + continue; // @TODO Do not evaluate other params at the moment + } + } + + if (slRequest_.xmlRequest_ == null || slRequest_.dataUrl_ == null || + slRequest_.stylesheetUrl_ != null || slRequest_.redirectUrl_ != null) + { + // @TODO Only combindation of XMLRequest and StylesheetURL allowed at the moment + String message = "Currently only (XMLRequest + DataURL) is supported."; + logger_.error(message); + throw new IOException(message); + } + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private Document parseSlXmlRequest(Reader slXmlRequest) throws ServletException + { + // Parse sl request + InputSource slXMLRequestIS = new InputSource(slXmlRequest); + Document slXmlRequestDoc = null; + try + { + DOMParser xmlParser = (DOMParser) config_.getServletContext().getAttribute(Constants.WSCP_XMLPARSER_); + xmlParser.parse(slXMLRequestIS); + slXmlRequestDoc = xmlParser.getDocument(); + } + catch (Exception e) + { + String message = "Parsing Security-Layer request failed."; + logger_.error(message, e); + throw new ServletException(message, e); + } + + // Check if namespace is correct + String namespaceURI = slXmlRequestDoc.getDocumentElement().getNamespaceURI(); + if (!Constants.NSURI_SL_11_.equals(namespaceURI) && !Constants.NSURI_SL_12_.equals(namespaceURI)) + { + String message = "XML request has invalid namespace: \"" + namespaceURI + "\"."; + logger_.error(message); + throw new ServletException(message); + } + + return slXmlRequestDoc; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private void checkHttpPost(HttpServletRequest request) throws ServletException + { + String method = request.getMethod(); + if (!"POST".equals(method)) + { + String message = "HTTP method \"" + method + "\" not supported. Must be \"POST\"."; + logger_.error(message); + throw new ServletException(message); + } + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Helper class, representing the fields of a Security-Layer request. + * + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ + class SLRequest + { + public String xmlRequest_; + public String dataUrl_; + public String stylesheetUrl_; + public String redirectUrl_; + } +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ServletInputStream.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ServletInputStream.java new file mode 100644 index 000000000..b0609c2f8 --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ServletInputStream.java @@ -0,0 +1,55 @@ +/* + * Created on 19.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.filters; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class ServletInputStream extends javax.servlet.ServletInputStream +{ + private ByteArrayInputStream inputStream_; + private int length_; + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Generates a new <code>ServletInputStram</code> from the specified stream. + * + * @param inputStream See above. + */ + public ServletInputStream(ByteArrayInputStream inputStream) + { + super(); + inputStream_ = inputStream; + length_ = inputStream_.available(); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Reads a single byte from the underlying <code>ByteArrayInputStream</code>. + * + * @see java.io.InputStream#read() + */ + public int read() throws IOException + { + return inputStream_.read(); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Gets the length of the content from this input stream. This equals to the number of bytes which where + * available at the time of creating this <code>ServletInputStream</code>. + */ + public int getContentLength() + { + return length_; + } +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ServletOutputStream.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ServletOutputStream.java new file mode 100644 index 000000000..b790ee55c --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/ServletOutputStream.java @@ -0,0 +1,50 @@ +/* + * Created on 18.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.filters; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class ServletOutputStream extends javax.servlet.ServletOutputStream +{ + private ByteArrayOutputStream outputStream_; + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Default constructor. + */ + public ServletOutputStream() + { + super(); + outputStream_ = new ByteArrayOutputStream(); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see java.io.OutputStream#write(int) + */ + public void write(int b) throws IOException + { + outputStream_.write(b); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Returns the content of this stream as a byte array. + * + * @return the content of this stream as a byte array. + */ + public byte[] toByteArray() + { + return outputStream_.toByteArray(); + } +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/listeners/ContextListener.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/listeners/ContextListener.java new file mode 100644 index 000000000..5b32a482b --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/listeners/ContextListener.java @@ -0,0 +1,153 @@ +/* + * Created on 18.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.listeners; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.log4j.Logger; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.parsers.XMLGrammarPreparser; +import org.apache.xerces.util.SymbolTable; +import org.apache.xerces.util.XMLGrammarPoolImpl; +import org.apache.xerces.xni.grammars.XMLGrammarDescription; +import org.apache.xerces.xni.grammars.XMLGrammarPool; +import org.apache.xerces.xni.parser.XMLInputSource; +import org.xml.sax.SAXException; + +import at.gv.egovernment.moa.spss.slinterface.Constants; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class ContextListener implements ServletContextListener +{ + private static final String SAX_NAMESPACES_FEATURE = "http://xml.org/sax/features/namespaces"; + private static final String SAX_VALIDATION_FEATURE = "http://xml.org/sax/features/validation"; + + private static final String XERCES_SCHEMA_VALIDATION_FEATURE = + "http://apache.org/xml/features/validation/schema"; + private static final String XERCES_NORMALIZED_VALUE_FEATURE = + "http://apache.org/xml/features/validation/schema/normalized-value"; + private static final String XERCES_INCLUDE_IGNORABLE_WHITESPACE_FEATURE = + "http://apache.org/xml/features/dom/include-ignorable-whitespace"; + private static final String XERCES_CREATE_ENTITY_REF_NODES_FEATURE = + "http://apache.org/xml/features/dom/create-entity-ref-nodes"; + + private static final int BIG_PRIME = 2039; + + private static Logger logger_ = Logger.getLogger(Constants.LH_LISTENERS_); + + /** + * Initializes the web application. + * + * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) + */ + public void contextInitialized(ServletContextEvent event) + { + logger_.debug("Context is being initialized."); + + ServletContext context = event.getServletContext(); + + String initPropsLoc = System.getProperty(Constants.SP_INIT_PROPS_LOC_); + if (initPropsLoc == null) + { + logger_.error("System property \"" + Constants.SP_INIT_PROPS_LOC_ + "\" not set."); + return; + } + + // Load init properties + try + { + InputStream initPropsIS = context.getResourceAsStream(initPropsLoc); + Properties initProps = new Properties(); + initProps.load(initPropsIS); + context.setAttribute(Constants.WSCP_INIT_PROPS_, initProps); + } + catch (IOException e) + { + logger_.error("Cannot load initialization properties from location \"" + initPropsLoc + "\".", e); + } + + // Initialize XML parser + SymbolTable symbolTable = new SymbolTable(BIG_PRIME); + XMLGrammarPool grammarPool = new XMLGrammarPoolImpl(); + + XMLGrammarPreparser preparser = new XMLGrammarPreparser(symbolTable); + preparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null); + preparser.setProperty(org.apache.xerces.impl.Constants.XERCES_PROPERTY_PREFIX + + org.apache.xerces.impl.Constants.XMLGRAMMAR_POOL_PROPERTY, grammarPool); + preparser.setFeature(SAX_NAMESPACES_FEATURE, true); + preparser.setFeature(SAX_VALIDATION_FEATURE, true); + + Properties initProps = (Properties) context.getAttribute(Constants.WSCP_INIT_PROPS_); + String slSchemaLoc = initProps.getProperty(Constants.IP_SL_SCHEMA_); + preparseSchema(context, preparser, slSchemaLoc); + String moaSchemaLoc = initProps.getProperty(Constants.IP_MOA_SCHEMA_); + preparseSchema(context, preparser, moaSchemaLoc); + + DOMParser xmlParser = new DOMParser(symbolTable, grammarPool); + try + { + xmlParser.setFeature(SAX_NAMESPACES_FEATURE, true); + xmlParser.setFeature(SAX_VALIDATION_FEATURE, true); + xmlParser.setFeature(XERCES_SCHEMA_VALIDATION_FEATURE, true); + xmlParser.setFeature(XERCES_NORMALIZED_VALUE_FEATURE, false); + xmlParser.setFeature(XERCES_INCLUDE_IGNORABLE_WHITESPACE_FEATURE, true); + xmlParser.setFeature(XERCES_CREATE_ENTITY_REF_NODES_FEATURE, false); + } + catch (SAXException e) + { + String message = "Initialization of XML parser failed."; + logger_.error(message, e); + } + context.setAttribute(Constants.WSCP_XMLPARSER_, xmlParser); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Does some clean up at finalization of the web application. + * + * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) + */ + public void contextDestroyed(ServletContextEvent event) + { + // Remove init properties from web service context + Properties initProps = (Properties) event.getServletContext().getAttribute(Constants.WSCP_INIT_PROPS_); + if (initProps != null) event.getServletContext().removeAttribute(Constants.WSCP_INIT_PROPS_); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private void preparseSchema(ServletContext context, XMLGrammarPreparser preparser, String schemaLoc) + { + InputStream schemaIS = context.getResourceAsStream(schemaLoc); + if (schemaIS == null) + { + String message = "Cannot load schema from location \"" + schemaLoc + "\"."; + logger_.error(message); + } + try + { + String schemaSystemId = context.getResource(schemaLoc).toExternalForm(); + preparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, + new XMLInputSource(null, schemaSystemId, null, schemaIS, null)); + } + catch (Exception e) + { + String message = "Parsing schema loaded from location \"" + schemaLoc + "\" failed."; + logger_.error(message, e); + } + } + + +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/moainvoker/MOAInvoker.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/moainvoker/MOAInvoker.java new file mode 100644 index 000000000..e89d255f0 --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/moainvoker/MOAInvoker.java @@ -0,0 +1,92 @@ +/* + * Created on 19.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.moainvoker; + +import java.io.IOException; +import java.io.OutputStream; +import java.rmi.RemoteException; +import java.util.Vector; + +import javax.xml.namespace.QName; +import javax.xml.rpc.Call; +import javax.xml.rpc.Service; +import javax.xml.rpc.ServiceException; +import javax.xml.rpc.ServiceFactory; + +import org.apache.axis.message.SOAPBodyElement; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; +import org.w3c.dom.Document; + +import at.gv.egovernment.moa.spss.slinterface.Constants; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class MOAInvoker +{ + /** + * Invokes MOA SP. + * + * @param request The XML request to be sent to MOA SP. + * + * @param endpoint The endpoint of the SOAP service where to send the XML request to. + * + * @return the XML response from the service. + * + * @throws Exception if getting the XML response from the SOAP response body fails. + * + * @throws RemoteException if MOA SP signals an error. + * + * @throws ServiceException if the SOAP client invoking MOA SP signals an error. + */ + public static Document invokeSP(Document request, String endpoint) + throws Exception, RemoteException, ServiceException + { + QName serviceQName = new QName(Constants.MI_SP_QNAME_); + return invoke(request, endpoint, serviceQName); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private static Document invoke(Document request, String endpoint, QName serviceQName) throws Exception + { + // Instantiate AXIS service + Service service = ServiceFactory.newInstance().createService(serviceQName); + + // Create and configure service call + Call call = service.createCall(); + call.setTargetEndpointAddress(endpoint); + + // Create SOAP body + SOAPBodyElement body = new SOAPBodyElement(request.getDocumentElement()); + SOAPBodyElement[] params = new SOAPBodyElement[] {body}; + + // Make call + Vector responses = (Vector) call.invoke(params); + + // Get response + SOAPBodyElement responseBody = (SOAPBodyElement) responses.get(0); + Document response = responseBody.getAsDocument(); + return response; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public static void serializeDocument(Document doc, OutputStream out) throws IOException + { + OutputFormat format = new OutputFormat(doc); + + format.setLineSeparator("\n"); + format.setIndenting(false); + format.setPreserveSpace(true); + format.setOmitXMLDeclaration(false); + format.setEncoding("UTF-8"); + + XMLSerializer serializer = new XMLSerializer(out, format); + serializer.serialize(doc); + } +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/servlets/MOAServlet.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/servlets/MOAServlet.java new file mode 100644 index 000000000..1ec18e5cb --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/servlets/MOAServlet.java @@ -0,0 +1,111 @@ +/* + * Created on 19.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.servlets; + +import java.io.IOException; +import java.rmi.RemoteException; +import java.util.Properties; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.rpc.ServiceException; + +import org.apache.log4j.Logger; +import org.apache.xerces.parsers.DOMParser; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import at.gv.egovernment.moa.spss.slinterface.Constants; +import at.gv.egovernment.moa.spss.slinterface.moainvoker.MOAInvoker; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class MOAServlet extends HttpServlet +{ + private static Logger logger_ = Logger.getLogger(Constants.LH_SERVLETS_); + + /** + * Default constructor. + */ + public MOAServlet() + { + super(); + } + + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException + { + // Get moa request form http request + Document moaXmlRequest = null; + DOMParser xmlParser = (DOMParser) this.getServletContext().getAttribute(Constants.WSCP_XMLPARSER_); + try + { + InputSource requestIS = new InputSource(request.getInputStream()); + xmlParser.parse(requestIS); + moaXmlRequest = xmlParser.getDocument(); + } + catch (IOException ioe) + { + String message = "Getting MOA XML request from http request input failed."; + logger_.error(message, ioe); + throw new ServletException(message, ioe); + } + catch (SAXException se) + { + String message = "Parsing MOA XML request got from http request failed."; + logger_.error(message, se); + throw new ServletException(message, se); + } + + // Send request to MOA SP + Properties initProps = (Properties) this.getServletContext().getAttribute(Constants.WSCP_INIT_PROPS_); + String endPoint = initProps.getProperty(Constants.IP_SP_ENDPOINT_); + if (endPoint == null) + { + String message = "No endpoint configured for MOA SP service."; + logger_.error(message); + throw new ServletException(message); + } + Document moaXMLResponseDoc = null; + try + { + moaXMLResponseDoc = MOAInvoker.invokeSP(moaXmlRequest, endPoint); + } + catch (Exception e) + { + String message; + if (e instanceof RemoteException) + { + message = "MOA SP service indicated an error at request execution."; + } + else if (e instanceof ServiceException) + { + message = "MOA SP client indicated an error at request execution."; + } + else + { + message = "Could not create DOM Document from MOA SP service response."; + } + logger_.error(message, e); + throw new ServletException(message, e); + } + + // Write moa response to http response + try + { + MOAInvoker.serializeDocument(moaXMLResponseDoc, response.getOutputStream()); + } + catch (IOException e) + { + String message = "Writing MOA SP XML response to http response failed."; + logger_.error(message, e); + throw new ServletException(message, e); + } + } +} |