From 1c900609d64445040e8c5bdbfa01ae1a0f563f43 Mon Sep 17 00:00:00 2001 From: gregor Date: Wed, 28 Feb 2007 13:17:57 +0000 Subject: Initial commit git-svn-id: https://joinup.ec.europa.eu/svn/moa-idspss/trunk@806 d688527b-c9ab-4aba-bd8d-4036d912da1d --- .../moa/ss/erechtclient/ERechtClientException.java | 111 ++++++ .../moa/ss/erechtclient/init/Constants.java | 104 +++++ .../moa/ss/erechtclient/init/ContextListener.java | 187 +++++++++ .../ss/erechtclient/init/InitPropertiesBean.java | 33 ++ .../erechtclient/init/XMLParserErrorHandler.java | 65 ++++ .../erechtclient/moainvoker/DOMErrorHandler.java | 55 +++ .../moa/ss/erechtclient/moainvoker/MOAInvoker.java | 157 ++++++++ .../ss/erechtclient/moainvoker/RequestBuilder.java | 190 +++++++++ .../moa/ss/erechtclient/servlets/Dispatcher.java | 428 +++++++++++++++++++++ .../moa/ss/erechtclient/util/DOMUtils.java | 169 ++++++++ .../moa/ss/erechtclient/util/Utils.java | 106 +++++ .../moa/ss/erechtclient/util/XPathUtils.java | 162 ++++++++ 12 files changed, 1767 insertions(+) create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/ERechtClientException.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/Constants.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/ContextListener.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/InitPropertiesBean.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/XMLParserErrorHandler.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/DOMErrorHandler.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/MOAInvoker.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/RequestBuilder.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/servlets/Dispatcher.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/DOMUtils.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/Utils.java create mode 100644 erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/XPathUtils.java (limited to 'erecht.client.ss/src/at/gv/egovernment/moa/ss') diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/ERechtClientException.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/ERechtClientException.java new file mode 100644 index 000000000..1650e1641 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/ERechtClientException.java @@ -0,0 +1,111 @@ +package at.gv.egovernment.moa.ss.erechtclient; + +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Writer; + +import javax.servlet.ServletOutputStream; + +/** + * Base class of MOA specific exceptions. + * + * This class has the ability to wrap other exceptions which may be seen + * as the root cause for this exception. + * + * @author Gregor Karlinger + * @version $Id$ + */ +public class ERechtClientException extends Exception { + + /** The wrapped Throwable. */ + private Throwable wrapped_; + + /** + * Create a MOAException. + * + * @param message The message contained in the created ERechtClientException. + */ + public ERechtClientException(String message) + { + super(message); + } + + /** + * Create a MOAException. + * + * @param message The message contained in the created ERechtClientException. + * + * @param wrapped The exception wrapped by the created ERechtClientException. + */ + public ERechtClientException(String message, Throwable wrapped) + { + super(message, wrapped); + this.wrapped_ = wrapped; + } + + /** + * Print a stack trace of this exception to System.err. + * + * @see java.lang.Throwable#printStackTrace() + */ + public void printStackTrace() + { + printStackTrace(System.err); + } + + /** + * Print a stack trace of this exception, including the wrapped exception. + * + * @param s The stream to write the stack trace to. + * + * @see java.lang.Throwable#printStackTrace(java.io.PrintStream) + */ + public void printStackTrace(PrintStream s) + { + super.printStackTrace(s); + if (wrapped_ != null) + { + s.print("Caused by: "); + wrapped_.printStackTrace(s); + } + } + + /** + * Print a stack trace of this exception, including the wrapped exception. + * + * @param s The stream to write the stacktrace to. + * + * @see java.lang.Throwable#printStackTrace(java.io.PrintWriter) + */ + public void printStackTrace(PrintWriter s) { + super.printStackTrace(s); + if (wrapped_ != null) + { + s.print("Caused by: "); + wrapped_.printStackTrace(s); + } + } + + /** + * Print a stack trace of this exception, including the wrapped exception. + * + * @param s The stream to write the stacktrace to. + * + * @see java.lang.Throwable#printStackTrace(java.io.PrintWriter) + */ + public String getStackTracePrint() + { + ByteArrayOutputStream bAOS = new ByteArrayOutputStream(); + PrintWriter s = new PrintWriter(bAOS); + super.printStackTrace(s); + if (wrapped_ != null) + { + s.print("Caused by: "); + wrapped_.printStackTrace(s); + } + s.flush(); + return bAOS.toString(); + } +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/Constants.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/Constants.java new file mode 100644 index 000000000..a9cfdac62 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/Constants.java @@ -0,0 +1,104 @@ +/* + * Created on 18.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.ss.erechtclient.init; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class Constants +{ + // System properties + public static final String INIT_PROPS_LOC_ = + "at.gv.egovernment.moa.ss.erechtclient.PropertiesLocation"; + + // Init properties + + // TODO Revisit if constants can be removed + public static final String IP_WEBAPP_HOST_PORT_ = "location.webAppHostPort"; + public static final String IP_WEBAPP_HOST_PORT_FROM_MOA_SS_ = "location.webAppHostPortFromMOASS"; + + public static final String IP_MOA_SCHEMA_ = "location.schema.moa"; + public static final String IP_SS_REQUEST_TEMPLATE_ = "location.ss.requestTemplate"; + + public static final String IP_TEMP_DIR_ = "location.tempdir"; + public static final String IP_SS_STYLESHEET_ = "location.ss.stylesheet"; + + public static final String IP_SS_ENDPOINT_ = "service.ss.endpoint"; + public static final String IP_SS_KEYID_ = "service.ss.keyIdentifier"; + + // Logging hierarchies + + public static final String LH_BASE_ = "erechtclient"; + public static final String LH_INIT_ = LH_BASE_ + ".init"; + public static final String LH_XMLPARSER_ = LH_BASE_ + ".xmlparser"; + public static final String LH_SERVLETS_ = LH_BASE_ + ".servlets"; + public static final String LH_BEANS_ = LH_BASE_ + ".beans"; + public static final String LH_MOAINVOKER_ = LH_BASE_ + ".moainvoker"; + + // Web service context parameters + + public static final String WSCP_INIT_PROPS_ = "initProperties"; + public static final String WSCP_INITPROPS_BEAN_ = "initPropertiesBean"; + public static final String WSCP_XMLPARSER_ = "xmlParser"; + + // Session parameters + + public static final String SCP_XMLBGBL_FNAME_ = "xMLBGBl"; + public static final String SCP_STYLESHEET_FNAME_ = "stylesheet"; + public static final String SCP_IMAGE_NAMES_LIST_ = "imageNames"; + public static final String SCP_IMAGES_LIST_ = "images"; + public static final String SCP_SIGNATURE_URL_ = "signatureURL"; + + // Reqeust context parameters + + public static final String RCP_ERROR_THROWABLE_ = "throwable"; + + // Namespace URIs + + public static final String NSURI_MOA_13_ = "http://reference.e-government.gv.at/namespace/moa/20020822#"; + public static final String NSURI_NAMESPACES_ = "http://www.w3.org/2000/xmlns/"; + public static final String NSURI_XML_ = "http://www.w3.org/XML/1998/namespace"; + public static final String NSURI_DSIG_ = "http://www.w3.org/2000/09/xmldsig#"; + public static final String NSURI_XMLBGBL_ = "http://www.bka.gv.at"; + + // Namespace prefixes + + public static final String NSPRE_MOA_13_ = "moa"; + public static final String NSPRE_DSIG_ = "dsig"; + public static final String NSPRE_XMLBGBL_ = "bka"; + + // Local XML element's names + + public static final String XML_LN_XMLBGBL_ROOT_ = "erechtdok"; + public static final String XML_LN_XMLBGBL_IMG_ = "binary"; + public static final String XML_LN_XMLBGBL_IMG_SRC_ = "src"; + public static final String XML_LN_XMLBGBL_IMG_REF_ = "ref"; + + // MOA invoker constants + + public static final String MI_SS_QNAME_ = "SignatureCreation"; + + // Default values + + public static final String DV_WEBAPP_HOST_PATH_ = "http://localhost:8080"; + + // HTML form parameter names + + public static final String FPN_UPLOAD_XML_XMLBGBL_ = "xMLBGBl"; + public static final String FPN_UPLOAD_STYLESHEET_ = "stylesheet"; + public static final String FPN_UPLOAD_IMG_IMG_ = "image."; + + // JSP page names + + public static final String JSPPN_ERROR_ = "pages/Error.jsp"; + public static final String JSPPN_UPLOAD_XML_ = "pages/UploadXML.jsp"; + public static final String JSPPN_UPLOAD_IMG_ = "pages/UploadImages.jsp"; + public static final String JSPPN_DOWNLOAD_SIG_ = "pages/DownloadSignature.jsp"; + + // Servlet url names + public static final String SRVN_UPLOAD_XML_ = "/UploadXML"; + public static final String SRVN_UPLOAD_IMG_ = "/UploadImages"; +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/ContextListener.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/ContextListener.java new file mode 100644 index 000000000..6cc5988ac --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/ContextListener.java @@ -0,0 +1,187 @@ +/* + * (c) Siemens Business Services GmbH + */ +package at.gv.egovernment.moa.ss.erechtclient.init; + +import java.io.FileInputStream; +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; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@siemens.com) + */ +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"; + protected static final String XERCES_DEFER_NODE_EXPANSION_ = + "http://apache.org/xml/features/dom/defer-node-expansion"; + protected static final String XERCES_AUGMENT_PSI_ = + "http://apache.org/xml/features/validation/schema/augment-psvi"; + + private static final int BIG_PRIME = 2039; + + private static Logger logger_ = Logger.getLogger(Constants.LH_INIT_); + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * 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.INIT_PROPS_LOC_); + if (initPropsLoc == null) + { + logger_.fatal("System property \"" + Constants.INIT_PROPS_LOC_ + "\" not set."); + logger_.fatal("Web application initialization failed."); + return; + } + + // Load init properties + try + { + logger_.debug("Init properties location \"" + initPropsLoc + "\" will be used."); + + // Try to interpret init properties location as relative to the web application root + InputStream initPropsIS = context.getResourceAsStream(initPropsLoc); + + if (initPropsIS == null) + { + // If this does not work, try to interpret init properties location as an absolute file system path + initPropsIS = new FileInputStream(initPropsLoc); + } + + Properties initProps = new Properties(); + initProps.load(initPropsIS); + context.setAttribute(Constants.WSCP_INIT_PROPS_, initProps); + + // Prepare application bean knowing about init properties + InitPropertiesBean initPropsBean = new InitPropertiesBean(initProps); + context.setAttribute(Constants.WSCP_INITPROPS_BEAN_, initPropsBean); + } + catch (IOException e) + { + logger_.fatal("Cannot load initialization properties from location \"" + initPropsLoc + "\".", e); + logger_.fatal("Web application initialization failed."); + return; + } + + // 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); + + // Schema for MOA 1.3 + // TODO Maybe remove this? + Properties initProps = (Properties) context.getAttribute(Constants.WSCP_INIT_PROPS_); + String moaSchemaLoc = initProps.getProperty(Constants.IP_MOA_SCHEMA_); + if (!preparseSchema(context, preparser, moaSchemaLoc)) + { + logger_.fatal("Web application initialization failed."); + return; + } + + // TODO parser is not threadsafe + 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); + xmlParser.setFeature(XERCES_DEFER_NODE_EXPANSION_, true); + xmlParser.setFeature(XERCES_AUGMENT_PSI_, false); + xmlParser.setErrorHandler(new XMLParserErrorHandler(false, true, true)); + } + catch (SAXException e) + { + String message = "Initialization of XML parser failed."; + logger_.fatal(message, e); + logger_.fatal("Web application initialization failed."); + return; + } + context.setAttribute(Constants.WSCP_XMLPARSER_, xmlParser); + + String message = "Web application initialization succeeded."; + logger_.info(message); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * 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 boolean preparseSchema(ServletContext context, XMLGrammarPreparser preparser, String schemaLoc) + { + InputStream schemaIS = context.getResourceAsStream(schemaLoc); + if (schemaIS == null) + { + String message = "Cannot load schema from location \"" + schemaLoc + "\"."; + logger_.fatal(message); + return false; + } + 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_.fatal(message, e); + return false; + } + return true; + } +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/InitPropertiesBean.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/InitPropertiesBean.java new file mode 100644 index 000000000..7b7e1eb11 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/InitPropertiesBean.java @@ -0,0 +1,33 @@ +package at.gv.egovernment.moa.ss.erechtclient.init; + +import java.util.Properties; + +import org.apache.log4j.Logger; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@siemens.com) + */ +public class InitPropertiesBean +{ + private Properties initProps_; + + private static Logger logger_ = Logger.getLogger(Constants.LH_BEANS_); + + public InitPropertiesBean(Properties props) + { + initProps_ = props; + } + + public String getWebAppHostPort() + { + String webAppHostPort = initProps_.getProperty(Constants.IP_WEBAPP_HOST_PORT_); + logger_.debug("MOA SS E-Recht Client web application host/port: " + webAppHostPort); + if (webAppHostPort == null || webAppHostPort.trim().length() == 0) + { + String defaultWebAppHostPath = Constants.DV_WEBAPP_HOST_PATH_; + logger_.info("MOA SS E-Recht Client web application host/port property not available, using default (" + defaultWebAppHostPath + ")"); + return defaultWebAppHostPath; + } + else return webAppHostPort; + } +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/XMLParserErrorHandler.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/XMLParserErrorHandler.java new file mode 100644 index 000000000..a954d35d9 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/init/XMLParserErrorHandler.java @@ -0,0 +1,65 @@ +/* + * Created on 02.12.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.ss.erechtclient.init; + +import org.apache.log4j.Logger; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import at.gv.egovernment.moa.ss.erechtclient.init.Constants; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class XMLParserErrorHandler implements ErrorHandler +{ + private static Logger logger_ = Logger.getLogger(Constants.LH_XMLPARSER_); + + private boolean reportWarning_, reportError_, reportFatal_; + + /* ---------------------------------------------------------------------------------------------------- */ + + public XMLParserErrorHandler(boolean reportWarning, boolean reportError, boolean reportFatal) + { + reportWarning_ = reportWarning; + reportError_ = reportError; + reportFatal_ = reportFatal; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException) + */ + public void warning(SAXParseException exception) throws SAXException + { + logger_.warn("XML parser reported a warning.", exception); + if (reportWarning_) throw exception; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException) + */ + public void error(SAXParseException exception) throws SAXException + { + logger_.error("XML parser reported an error.", exception); + if (reportError_) throw exception; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException) + */ + public void fatalError(SAXParseException exception) throws SAXException + { + logger_.error("XML parser reported a fatal error.", exception); + if (reportFatal_) throw exception; + } +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/DOMErrorHandler.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/DOMErrorHandler.java new file mode 100644 index 000000000..47b389c31 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/DOMErrorHandler.java @@ -0,0 +1,55 @@ +package at.gv.egovernment.moa.ss.erechtclient.moainvoker; + +import java.util.Iterator; +import java.util.LinkedList; + +import org.apache.log4j.Logger; +import org.w3c.dom.DOMError; + +import at.gv.egovernment.moa.ss.erechtclient.init.Constants; + +public class DOMErrorHandler implements org.w3c.dom.DOMErrorHandler +{ + private LinkedList errors_; + + private static Logger logger_ = Logger.getLogger(Constants.LH_MOAINVOKER_); + + public DOMErrorHandler() + { + errors_ = new LinkedList(); + } + public boolean handleError(DOMError error) + { + if (error.getSeverity() == DOMError.SEVERITY_WARNING) + { + logger_.warn("A warning occured while parsing: " + error.getMessage()); + return true; + } + else + { + logger_.error("A (fatal) error occured while parsing: " + error.getMessage()); + errors_.add(error.getMessage()); + return false; + } + } + + public int getErrorCount() + { + return errors_.size(); + } + + public String getErrorSummaryMsg() + { + if (errors_.size() <= 0) return null; + + StringBuffer errorSummaryMsg = new StringBuffer(); + errorSummaryMsg.append("The following errors have been reported during parsing:\n"); + for (int i = 0; i < errors_.size(); i++) + { + errorSummaryMsg.append("Error no. " + i + ":\n"); + errorSummaryMsg.append(errors_.get(i) + "\n"); + } + return errorSummaryMsg.toString(); + } + +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/MOAInvoker.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/MOAInvoker.java new file mode 100644 index 000000000..65cb55c04 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/MOAInvoker.java @@ -0,0 +1,157 @@ +/* + * Created on 19.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.ss.erechtclient.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.log4j.Logger; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.xni.parser.XMLInputSource; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; +import org.w3c.dom.DOMConfiguration; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.ss.erechtclient.ERechtClientException; +import at.gv.egovernment.moa.ss.erechtclient.init.Constants; +import at.gv.egovernment.moa.ss.erechtclient.util.DOMUtils; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class MOAInvoker +{ + private static Logger logger_ = Logger.getLogger(Constants.LH_MOAINVOKER_); + + private static final String NAME_ERROR_ = "ErrorResponse"; + private static final String NAME_ERROR_CODE_ = "ErrorCode"; + private static final String NAME_ERROR_INFO_ = "Info"; + + /** + * Invokes MOA SS. + * + * @param request The XML request to be sent to MOA SS. + * + * @param endpoint The endpoint of the SOAP service where to send the XML request to. + * + * @param mOASchemaLoc The schema location URI for the MOA schema (for validating the MOA SS service response). + * + * @return the XML response from the service. + * + * @throws Exception if getting the XML response from the SOAP response body fails. + * + * @throws RemoteException if MOA SS signals an error. + * + * @throws ServiceException if the SOAP client invoking MOA SS signals an error. + */ + public static Document invokeSS(Document request, String endpoint, String mOASchemaLoc) throws ERechtClientException + { + QName serviceQName = new QName(Constants.MI_SS_QNAME_); + return invoke(request, endpoint, serviceQName, mOASchemaLoc); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private static Document invoke(Document request, String endpoint, QName serviceQName, String mOASchemaLoc) throws ERechtClientException + { + Document response; + try { + // 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); + response = responseBody.getAsDocument(); + } + catch (Exception e) + { + String message = "MOA SS Service invocation failed."; + logger_.error(message, e); + throw new ERechtClientException(message, e); + } + + // Validate response + DOMConfiguration docConfig = response.getDomConfig(); + DOMErrorHandler errorHandler = new DOMErrorHandler(); + docConfig.setParameter("namespaces", Boolean.FALSE); + docConfig.setParameter("schema-location", mOASchemaLoc); + docConfig.setParameter("schema-type", "http://www.w3.org/2001/XMLSchema"); + docConfig.setParameter("validate", Boolean.TRUE); + docConfig.setParameter("error-handler", errorHandler); + response.normalizeDocument(); + if (errorHandler.getErrorCount() > 0) + { + String message = "Parsing the MOA SS service response failed:\n" + errorHandler.getErrorSummaryMsg(); + logger_.error(message); + throw new ERechtClientException(message); + } + + // Check if first child of response root element is an error element + Element responseElem = response.getDocumentElement(); + Element errorElem = DOMUtils.getChildElem(responseElem, Constants.NSURI_MOA_13_, NAME_ERROR_); + if (errorElem != null) + { + String errorCode = DOMUtils.getChildText(errorElem, Constants.NSURI_MOA_13_, NAME_ERROR_CODE_); + String errorInfo = DOMUtils.getChildText(errorElem, Constants.NSURI_MOA_13_, NAME_ERROR_INFO_); + String message = "MOA SS Service indicated an error:\n" + + "Error code: " + errorCode + "\n" + + "Error info: " + errorInfo; + logger_.error(message); + throw new ERechtClientException(message); + } + + return response; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public static void serializeElement(Element rootElem, OutputStream out) throws ERechtClientException + { + + // TODO Replace with DOMImplementationLS + OutputFormat format = new OutputFormat(rootElem.getOwnerDocument()); + + format.setLineSeparator("\n"); + format.setIndenting(false); + format.setPreserveSpace(true); + format.setOmitXMLDeclaration(false); + format.setEncoding("UTF-8"); + + XMLSerializer serializer = new XMLSerializer(out, format); + try + { + serializer.serialize(rootElem); + } + catch (Exception e) + { + String message = "Serializing the XML document failed."; + logger_.error(message); + throw new ERechtClientException(message); + } + } +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/RequestBuilder.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/RequestBuilder.java new file mode 100644 index 000000000..2c6e0d0e8 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/moainvoker/RequestBuilder.java @@ -0,0 +1,190 @@ +package at.gv.egovernment.moa.ss.erechtclient.moainvoker; + +import java.io.InputStream; +import java.util.Properties; + +import javax.servlet.ServletContext; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import at.gv.egovernment.moa.ss.erechtclient.ERechtClientException; +import at.gv.egovernment.moa.ss.erechtclient.init.Constants; +import at.gv.egovernment.moa.ss.erechtclient.util.DOMUtils; +import at.gv.egovernment.moa.ss.erechtclient.util.Utils; +import at.gv.egovernment.moa.ss.erechtclient.util.XPathUtils; + +public class RequestBuilder +{ + private static final String XPATH_KEYID_ = + "/" + Constants.NSPRE_MOA_13_ + ":" + "CreateXMLSignatureRequest" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "KeyIdentifier"; + + private static final String XPATH_XMLDOC_ = + "/" + Constants.NSPRE_MOA_13_ + ":" + "CreateXMLSignatureRequest" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "SingleSignatureInfo" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "DataObjectInfo" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "DataObject" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "LocRefContent"; + + private static final String XPATH_STYLESHEET_ = + "/" + Constants.NSPRE_MOA_13_ + ":" + "CreateXMLSignatureRequest" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "SingleSignatureInfo" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "DataObjectInfo" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "CreateTransformsInfoProfile" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "Supplement" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "Content" + "[@Reference=\"stylesheet.xsl\"]" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "LocRefContent"; + + private static final String XPATH_IMAGE_ = + "/" + Constants.NSPRE_MOA_13_ + ":" + "CreateXMLSignatureRequest" + + "/" + Constants.NSPRE_MOA_13_ + ":" + "SingleSignatureInfo"; + + private static final String ELEM_NAME_DOI_ = "DataObjectInfo"; + + private static final String ATTR_VALUE_DO_STRUCTURE_ = "detached"; + + private static final String ELEM_NAME_DO_ = "DataObject"; + + private static final String ATTR_NAME_DOI_STRUCTURE_ = "Structure"; + + private static final String ATTR_NAME_DO_REFERENCE_ = "Reference"; + + private static final String ELEM_NAME_CTIP_ = "CreateTransformsInfoProfile"; + + private static final String ELEM_NAME_CTI_ = "CreateTransformsInfo"; + + private static final String ELEM_NAME_FDMI_ = "FinalDataMetaInfo"; + + private static final String ELEM_NAME_FDMIMIMETYPE_ = "MimeType"; + + private static final String ELEM_VALUE_FDMIMIMETYPE_ = "image"; + + private static final String ELEM_NAME_FDMITYPE_ = "Type"; + + private static final String ELEM_VALUE_FDMITYPE_ = "http://www.buergerkarte.at/specifications/" + + "Security-Layer/20031113?Name=SignedImage&InstanceDocRef=0"; + + private static final String ELEM_NAME_LOCREF_ = "LocRefContent"; + + private Document requestDoc_; + + private String contextPath_; + + private Properties initProps_; + + private ServletContext context_; + + private static Logger logger_ = Logger.getLogger(Constants.LH_MOAINVOKER_); + + public RequestBuilder(ServletContext context, String contextPath) throws ERechtClientException + { + contextPath_ = contextPath; + context_ = context; + initProps_ = (Properties) context.getAttribute(Constants.WSCP_INIT_PROPS_); + + // Load template + String requestTemplateLocation = Utils.readInitProperty(initProps_, Constants.IP_SS_REQUEST_TEMPLATE_, logger_); + try + { + InputStream requestTemplateIS = context_.getResourceAsStream(requestTemplateLocation); + requestDoc_ = DOMUtils.parseWellFormed(requestTemplateIS); + } catch (Exception e) + { + String message = "Could not parse MOA SS signature creation request template."; + logger_.error(message, e); + throw new ERechtClientException(message, e); + } + + // Insert key identifier + Element keyIdentifierElem = xPathGetElement(XPATH_KEYID_, requestDoc_); + String keyIdentifierStr = Utils.readInitProperty(initProps_, Constants.IP_SS_KEYID_, logger_); + keyIdentifierElem.appendChild(requestDoc_.createTextNode(keyIdentifierStr)); + } + + public void setXMLDocument(String locationRef) throws ERechtClientException + { + // Set XML document location reference + Element xMLDocLocRefElem = xPathGetElement(XPATH_XMLDOC_, requestDoc_); + String webAppHostPortFromMOASS = Utils.readInitProperty(initProps_, Constants.IP_WEBAPP_HOST_PORT_FROM_MOA_SS_, logger_); + xMLDocLocRefElem.appendChild(requestDoc_.createTextNode(webAppHostPortFromMOASS + contextPath_ + locationRef)); + } + + public void setStylesheet(String locationRef) throws ERechtClientException + { + Element stylesheetLocRefElem = xPathGetElement(XPATH_STYLESHEET_, requestDoc_); + String webAppHostPortFromMOASS = Utils.readInitProperty(initProps_, Constants.IP_WEBAPP_HOST_PORT_FROM_MOA_SS_, logger_); + String stylesheetLocRefStr = webAppHostPortFromMOASS + contextPath_ + locationRef; + stylesheetLocRefElem.appendChild(requestDoc_.createTextNode(webAppHostPortFromMOASS + contextPath_ + locationRef)); + logger_.debug("Setting stylesheet location to: " + stylesheetLocRefStr); + } + + public void useDefaultStylesheet() throws ERechtClientException + { + // Insert stylesheet reference, if it has not been set explicitly + Element stylesheetLocRefElem = xPathGetElement(XPATH_STYLESHEET_, requestDoc_); + String stylesheetLocRefStr = Utils.readInitProperty(initProps_, Constants.IP_SS_STYLESHEET_, logger_); + String webAppHostPortFromMOASS = Utils.readInitProperty(initProps_, Constants.IP_WEBAPP_HOST_PORT_FROM_MOA_SS_, logger_); + stylesheetLocRefStr = webAppHostPortFromMOASS + contextPath_ + stylesheetLocRefStr; + stylesheetLocRefElem.appendChild(requestDoc_.createTextNode(stylesheetLocRefStr)); + logger_.debug("No stylesheet set explicitly, using default one: " + stylesheetLocRefStr); + } + + public void addImage(String name, String locationRef) throws ERechtClientException + { + // Add supplement for image to be signed + Element parentElem = xPathGetElement(XPATH_IMAGE_, requestDoc_); + String webAppHostPortFromMOASS = Utils.readInitProperty(initProps_, Constants.IP_WEBAPP_HOST_PORT_FROM_MOA_SS_, logger_); + + Element dataObjInfo = requestDoc_.createElementNS(Constants.NSURI_MOA_13_, ELEM_NAME_DOI_); + dataObjInfo.setAttributeNS(null, ATTR_NAME_DOI_STRUCTURE_, ATTR_VALUE_DO_STRUCTURE_); + Element dataObj = requestDoc_.createElementNS(Constants.NSURI_MOA_13_, ELEM_NAME_DO_); + Element locRefCont = requestDoc_.createElementNS(Constants.NSURI_MOA_13_, ELEM_NAME_LOCREF_); + locRefCont.appendChild(requestDoc_.createTextNode(webAppHostPortFromMOASS + contextPath_ + locationRef)); + dataObj.appendChild(locRefCont); + dataObj.setAttributeNS(null, ATTR_NAME_DO_REFERENCE_, name); + dataObjInfo.appendChild(dataObj); + Element createTIProf = requestDoc_.createElementNS(Constants.NSURI_MOA_13_, ELEM_NAME_CTIP_); + Element createTI = requestDoc_.createElementNS(Constants.NSURI_MOA_13_, ELEM_NAME_CTI_); + Element finalDataMI = requestDoc_.createElementNS(Constants.NSURI_MOA_13_, ELEM_NAME_FDMI_); + Element finalDataMIMimeType = requestDoc_.createElementNS(Constants.NSURI_MOA_13_, ELEM_NAME_FDMIMIMETYPE_); + finalDataMIMimeType.appendChild(requestDoc_.createTextNode(ELEM_VALUE_FDMIMIMETYPE_)); + finalDataMI.appendChild(finalDataMIMimeType); + Element finalDataMIType = requestDoc_.createElementNS(Constants.NSURI_MOA_13_, ELEM_NAME_FDMITYPE_); + finalDataMIType.appendChild(requestDoc_.createTextNode(ELEM_VALUE_FDMITYPE_)); + finalDataMI.appendChild(finalDataMIType); + + createTI.appendChild(finalDataMI); + createTIProf.appendChild(createTI); + dataObjInfo.appendChild(createTIProf); + + parentElem.appendChild(dataObjInfo); + } + + public Document getRequest() + { + return requestDoc_; + } + + private Element xPathGetElement(String xPath, Document doc) throws ERechtClientException + { + try { + XPathUtils xpUtils = new XPathUtils(); + String additionalNSPrefixes = Constants.NSPRE_MOA_13_ + " " + Constants.NSURI_MOA_13_; + xpUtils.setupContext(xPath, doc.getDocumentElement(), additionalNSPrefixes); + NodeList nodeList = xpUtils.selectNodeSet(doc); + if (nodeList == null) return null; + if (nodeList.getLength() < 1) return null; + if (!(nodeList.item(0) instanceof Element)) return null; + return (Element) nodeList.item(0); + } + catch (Exception e) + { + String message = "MOA SS signature request template seems to be corrupted."; + logger_.error(message, e); + throw new ERechtClientException(message, e); + } + } +} \ No newline at end of file diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/servlets/Dispatcher.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/servlets/Dispatcher.java new file mode 100644 index 000000000..23c4dbb53 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/servlets/Dispatcher.java @@ -0,0 +1,428 @@ +/* + * Created on 25.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.ss.erechtclient.servlets; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.log4j.Logger; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import at.gv.egovernment.moa.ss.erechtclient.ERechtClientException; +import at.gv.egovernment.moa.ss.erechtclient.init.Constants; +import at.gv.egovernment.moa.ss.erechtclient.moainvoker.MOAInvoker; +import at.gv.egovernment.moa.ss.erechtclient.moainvoker.RequestBuilder; +import at.gv.egovernment.moa.ss.erechtclient.util.DOMUtils; +import at.gv.egovernment.moa.ss.erechtclient.util.Utils; +import at.gv.egovernment.moa.ss.erechtclient.util.XPathUtils; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class Dispatcher extends HttpServlet +{ + private static Logger logger_ = Logger.getLogger(Constants.LH_SERVLETS_); + + private static final String XPATH_ALL_IMGS_ = "//" + Constants.NSPRE_XMLBGBL_ + ":" + Constants.XML_LN_XMLBGBL_IMG_; + + private static final String FN_XMLBGBL_ = "xMLBGBl"; + private static final String FN_STYLESHEET_ = "stylesheet"; + private static final String FN_IMAGE_ = "image."; + private static final String FN_XMLSIG_ = "signature"; + + private static final String TS_XMLBGBL_ = "xml"; + private static final String TS_STYLESHEET_ = "xsl"; + private static final String TS_IMAGE_ = "img"; + private static final String TS_XMLSIG_ = "xml"; + + private static final String LN_XMLSIG_ = "Signature"; + private static final String LN_SIGENV_ = "SignatureEnvironment"; + + public Dispatcher() + { + super(); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException + { + try { + String screenName = request.getServletPath(); + if (Constants.SRVN_UPLOAD_XML_.equals(screenName)) + { + // Invalidate session if one exist from a previous use of the web application + HttpSession session = ((HttpServletRequest) request).getSession(false); + if (session != null) session.invalidate(); + + RequestDispatcher dispatcher = request.getRequestDispatcher(Constants.JSPPN_UPLOAD_XML_); + dispatcher.forward(request, response); + } + else + { + String message = "Unproper use of servlet \"" + screenName + "\". Please start with servlet \"" + + Constants.SRVN_UPLOAD_XML_ + "\"."; + throw new ERechtClientException(message); + } + } + catch (Exception e) + { + Utils.returnErrorPage(request, response, e); + } + + } + /* ---------------------------------------------------------------------------------------------------- */ + + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException + { + try + { + String screenName = request.getServletPath(); + if (Constants.SRVN_UPLOAD_XML_.equals(screenName)) + { + // Evaluate uploaded XML BGBl + HttpSession session = request.getSession(true); + + // Read BGBl XML upload from POST request + List params = parseParameters(request); + FileItem xMLBGBlFI = getFileItem(Constants.FPN_UPLOAD_XML_XMLBGBL_, params); + String xMLBGBlFileName = saveFileItem(xMLBGBlFI, FN_XMLBGBL_, TS_XMLBGBL_, session.getId(), this.getServletContext()); + session.setAttribute(Constants.SCP_XMLBGBL_FNAME_, xMLBGBlFileName); + + // Read stylesheet upload from POST request + FileItem stylesheetFI = getFileItem(Constants.FPN_UPLOAD_STYLESHEET_, params); + if (stylesheetFI.getName() != null && !"".equals(stylesheetFI.getName().trim())) + { + // Stylesheet has been uploaded + String stylesheetFileName = saveFileItem(stylesheetFI, FN_STYLESHEET_, TS_STYLESHEET_, session.getId(), this.getServletContext()); + session.setAttribute(Constants.SCP_STYLESHEET_FNAME_, stylesheetFileName); + } + + // Scan BGBl XML for potential images + Document xMLBGBlDoc = parseXMLBGBlDocument(xMLBGBlFileName, this.getServletContext()); + ArrayList imageNames = scanXMLBGBlForImages(xMLBGBlDoc); + + if (!imageNames.isEmpty()) + { + // Images exist in the BGBl XML, therefore continue with image upload + session.setAttribute(Constants.SCP_IMAGE_NAMES_LIST_, imageNames); + RequestDispatcher dispatcher = request.getRequestDispatcher(Constants.JSPPN_UPLOAD_IMG_); + dispatcher.forward(request, response); + return; + } + else + { + // Indicate with empty List in session that there are no images available + session.setAttribute(Constants.SCP_IMAGES_LIST_, new ArrayList(0)); + } + } + else if (Constants.SRVN_UPLOAD_IMG_.equals(screenName)) + { + HttpSession session = ((HttpServletRequest) request).getSession(false); + if (session == null) + { + String message = "Could not read session object."; + throw new ERechtClientException(message); + } + + List images = parseImageParameters(request, this.getServletContext()); + session.setAttribute(Constants.SCP_IMAGES_LIST_, images); + } + else + { + String message = "Unproper use of servlet \"" + screenName + "\". Please start with servlet \"" + + Constants.SRVN_UPLOAD_XML_ + "\"."; + logger_.error(message); + throw new ERechtClientException(message); + } + + // Create and store signature + HttpSession session = request.getSession(false); + Document signatureResponse = createXMLSignature(request, session); + String signatureFileName = saveXMLSignature(signatureResponse, session.getId(), this.getServletContext()); + Properties initProps = (Properties) this.getServletContext().getAttribute(Constants.WSCP_INIT_PROPS_); + String webAppHostPortFromMOASS = Utils.readInitProperty(initProps, Constants.IP_WEBAPP_HOST_PORT_FROM_MOA_SS_, logger_); + session.setAttribute(Constants.SCP_SIGNATURE_URL_, webAppHostPortFromMOASS + request.getContextPath() + signatureFileName); + + // Dispatch Download JSP page + RequestDispatcher dispatcher = request.getRequestDispatcher(Constants.JSPPN_DOWNLOAD_SIG_); + dispatcher.forward(request, response); + } + catch (Exception e) + { + Utils.returnErrorPage(request, response, e); + } + } + + private Document createXMLSignature(HttpServletRequest request, HttpSession session) throws ERechtClientException + { + RequestBuilder requestBuilder = new RequestBuilder(this.getServletContext(), request.getContextPath()); + String xMLBGBlFileName = (String) session.getAttribute(Constants.SCP_XMLBGBL_FNAME_); + if (xMLBGBlFileName == null) + { + String message = "Could not read XML BGBl file name from session."; + logger_.error(message); + throw new ERechtClientException(message); + } + requestBuilder.setXMLDocument(xMLBGBlFileName); + + String stylesheetFileName = (String) session.getAttribute(Constants.SCP_STYLESHEET_FNAME_); + if (stylesheetFileName != null) + { + requestBuilder.setStylesheet(stylesheetFileName); + } + else + { + requestBuilder.useDefaultStylesheet(); + } + + List images = (List) session.getAttribute(Constants.SCP_IMAGES_LIST_); + if (images == null) + { + String message = "Could not read images from session."; + logger_.error(message); + throw new ERechtClientException(message); + } + Iterator imagesIt = images.iterator(); + while (imagesIt.hasNext()) + { + Image currImg = (Image) imagesIt.next(); + requestBuilder.addImage(currImg.name_, currImg.fileLocation_); + } + Document signatureRequest = requestBuilder.getRequest(); + Properties initProps = (Properties) this.getServletContext().getAttribute(Constants.WSCP_INIT_PROPS_); + String serviceEndpoint = Utils.readInitProperty(initProps, Constants.IP_SS_ENDPOINT_, logger_); + String mOASchemaLoc = Utils.readInitProperty(initProps, Constants.IP_MOA_SCHEMA_, logger_); + String webAppHostPort = Utils.readInitProperty(initProps, Constants.IP_WEBAPP_HOST_PORT_, logger_); + Document signatureResponse = MOAInvoker.invokeSS(signatureRequest, serviceEndpoint, + "file:" + this.getServletContext().getRealPath(mOASchemaLoc)); + return signatureResponse; + } + + private List parseImageParameters(HttpServletRequest request, ServletContext context) throws ERechtClientException + { + HttpSession session = request.getSession(false); + if (session == null) + { + String message = "Could not read session object."; + throw new ERechtClientException(message); + } + + ArrayList imageNames = (ArrayList) session.getAttribute(Constants.SCP_IMAGE_NAMES_LIST_); + List params = parseParameters(request); + ArrayList images = new ArrayList(imageNames.size()); + for (int i = 0; i < params.size(); i++) + { + FileItem currItem = (FileItem) params.get(i); + if (currItem.getFieldName().startsWith(Constants.FPN_UPLOAD_IMG_IMG_)) + { + if (currItem.getSize() <= 0) + { + String message = "No content received for image \"" + currItem.getFieldName() + "\"."; + logger_.error(message); + throw new ERechtClientException(message); + } + String imgFileName = saveFileItem(currItem, FN_IMAGE_ + images.size(), TS_IMAGE_, session.getId(), context); + images.add(new Image(currItem.getFieldName().substring(Constants.FPN_UPLOAD_IMG_IMG_.length()), imgFileName)); + } + } + + // Check if there is a file item for each image name + if (imageNames.size() != images.size()) + { + String message = "No correct number of immages has been uploaded (Expected " + + imageNames.size() + ", actually received " + images.size() + ")."; + logger_.error(message); + throw new ERechtClientException(message); + } + + return images; + } + + private Document parseXMLBGBlDocument(String docFileName, ServletContext context) throws ERechtClientException + { + // TODO Change to validating parsing? + // DOMParser xmlParser = (DOMParser) context.getAttribute(Constants.WSCP_XMLPARSER_); + // InputSource docInputSource = new InputSource(docIS); + Document parsedDoc = null; + try + { + // xmlParser.parse(docInputSource); + FileInputStream docIS = new FileInputStream(context.getRealPath(docFileName)); + parsedDoc = DOMUtils.parseWellFormed(docIS); + + } + catch (Exception e) + { + String message = "Parsing XML BGBl document failed."; + logger_.error(message, e); + throw new ERechtClientException(message, e); + } + + Element docElem = parsedDoc.getDocumentElement(); + if (docElem.getNamespaceURI() != Constants.NSURI_XMLBGBL_ || docElem.getLocalName() != Constants.XML_LN_XMLBGBL_ROOT_) + { + String message = "XML BGBl has wrong root element (Local name equals \"" + docElem.getLocalName() + "\", NS-URI equals \"" + docElem.getNamespaceURI() + "\")."; + logger_.error(message); + throw new ERechtClientException(message); + } + + return parsedDoc; + } + + private ArrayList scanXMLBGBlForImages(Document xMLBGBlDoc) throws ERechtClientException + { + // Get all bka:binary elements in XML BGBl document + NodeList imgElems; + try { + XPathUtils xpUtils = new XPathUtils(); + String additionalNSPrefixes = Constants.NSPRE_XMLBGBL_ + " " + Constants.NSURI_XMLBGBL_; + xpUtils.setupContext(XPATH_ALL_IMGS_, xMLBGBlDoc.getDocumentElement(), additionalNSPrefixes); + imgElems = xpUtils.selectNodeSet(xMLBGBlDoc); + } + catch (Exception e) + { + String message = "Scanning for image elements in XML BGBl failed."; + logger_.error(message, e); + throw new ERechtClientException(message, e); + } + + // Collect the file refs of all bka:binary elements (either in bka:binary/@ref or in bka:binary/bka:src) + ArrayList list = new ArrayList(imgElems.getLength()); + for (int i = 0; i < imgElems.getLength(); i++) + { + Element currElem = (Element) imgElems.item(i); + Attr refAttr = currElem.getAttributeNodeNS(null, Constants.XML_LN_XMLBGBL_IMG_REF_); + if (refAttr != null) + { + list.add(i, refAttr.getValue()); + } + else + { + list.add(DOMUtils.getChildText(currElem, Constants.NSURI_XMLBGBL_, Constants.XML_LN_XMLBGBL_IMG_SRC_)); + } + } + return list; + } + + private List parseParameters(HttpServletRequest request) throws ERechtClientException + { + + if (ServletFileUpload.isMultipartContent(request)) + { + // Request is encoded as multipart/form-data + List items; + try + { + FileItemFactory factory = new DiskFileItemFactory(); + ServletFileUpload upload = null;; + upload = new ServletFileUpload(factory); + items = upload.parseRequest(request); + return items; + } + catch (FileUploadException e) + { + String message = "Parsing HTML form parameter failed."; + logger_.error(message, e); + throw new ERechtClientException(message, e); + } + } + else + { + // Request must be encoded als multipart/form-data + throw new ERechtClientException("HTML form encoding is not mulitpart/form-data."); + } + } + + private FileItem getFileItem(String fileItemName, List fileItemParams) + { + Iterator iter = fileItemParams.iterator(); + while (iter.hasNext()) + { + FileItem currentFI = (FileItem) iter.next(); + if (currentFI.getFieldName().equals(fileItemName)) return currentFI; + } + return null; + } + + private String saveFileItem(FileItem fileItem, String name, String typeSuffix, String sessionId, + ServletContext context) throws ERechtClientException + { + Properties initProps = (Properties) this.getServletContext().getAttribute(Constants.WSCP_INIT_PROPS_); + String tempDir = Utils.readInitProperty(initProps, Constants.IP_TEMP_DIR_, logger_); + String fileName = tempDir + sessionId + "." + name + "." + typeSuffix; + String realFileName = context.getRealPath(fileName); + try { + fileItem.write(new File(realFileName)); + } catch (Exception e) + { + String message = "Writing item \"" + name + "\" to file system failed."; + logger_.error(message, e); + throw new ERechtClientException(message, e); + } + return fileName; + } + + private String saveXMLSignature(Document mOAResponse, String sessionId, ServletContext context) + throws ERechtClientException + { + Element sigEnvElem = DOMUtils.getChildElem(mOAResponse.getDocumentElement(), Constants.NSURI_MOA_13_, LN_SIGENV_); + Element signatureElem = DOMUtils.getChildElem(sigEnvElem, Constants.NSURI_DSIG_, LN_XMLSIG_); + + Properties initProps = (Properties) this.getServletContext().getAttribute(Constants.WSCP_INIT_PROPS_); + String tempDir = Utils.readInitProperty(initProps, Constants.IP_TEMP_DIR_, logger_); + String fileName = tempDir + sessionId + "." + FN_XMLSIG_ + "." + TS_XMLSIG_; + String realFileName = context.getRealPath(fileName); + try { + FileOutputStream fileOS = new FileOutputStream(realFileName); + MOAInvoker.serializeElement(signatureElem, fileOS); + fileOS.close(); + } catch (Exception e) + { + String message = "Writing xml signature to file system failed."; + logger_.error(message, e); + throw new ERechtClientException(message, e); + } + return fileName; + } + + class Image + { + public String name_; + public String fileLocation_; + + public Image(String name, String fileLocation) + { + name_ = name; + fileLocation_ = fileLocation; + } + } +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/DOMUtils.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/DOMUtils.java new file mode 100644 index 000000000..d82cf1d1b --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/DOMUtils.java @@ -0,0 +1,169 @@ +/* + * Created on 28.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.ss.erechtclient.util; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.xerces.parsers.DOMParser; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import at.gv.egovernment.moa.ss.erechtclient.init.XMLParserErrorHandler; + + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class DOMUtils +{ + private static final String SAX_NAMESPACES_FEATURE = "http://xml.org/sax/features/namespaces"; + private static final String XERCES_CREATE_ENTITY_REF_NODES_FEATURE = + "http://apache.org/xml/features/dom/create-entity-ref-nodes"; + protected static final String XERCES_DEFER_NODE_EXPANSION_ = + "http://apache.org/xml/features/dom/defer-node-expansion"; + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Gets the first text node of the specified element. + * + * @param elem The element. + * + * @return the first text node of the specified element, or null if element + * equals null, or if the element has no text node. + */ + public static String getText(Element elem) + { + if (elem == null) return null; + NodeList childNodes = elem.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) + { + Node currNode = childNodes.item(i); + if (currNode.getNodeType() == Node.TEXT_NODE) return currNode.getNodeValue(); + } + return null; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Gets the first text node of the specified child element from the specified parent element. + * + * @param parent The parent. + * + * @param childNS The namespace of the child element. + * + * @param childLocName The local name of the child element. + * + * @return the first text node of the specified child, or null if parent equals + * null or has no child element with the specified namespace and local name, or if + * the child element has no text node. + */ + public static String getChildText(Element parent, String childNS, String childLocName) + { + if (parent == null) return null; + Element child = getChildElem(parent, childNS, childLocName); + if (child == null) return null; + return getText(child); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Gets the first child element of the specified parent with the specified namspace and local name. + * + * @param parent The parent. + * + * @param childNS The namespace of the child element to be searched for. + * + * @param childLocName The local name of the child element to be searched for. + * + * @return the first child element as described above, or null if parent is + * null or has no child elements with for the specified namespace and local name. + */ + public static Element getChildElem(Element parent, String childNS, String childLocName) + { + List childElems = getChildElems(parent, childNS, childLocName, true); + return (childElems == null) ? null : (Element) childElems.get(0); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Gets all or the first child element(s) of the specified parent with the specified namspace and local + * name. + * + * @param parent The parent. + * + * @param childNS The namespace of the child elements to be searched for. + * + * @param childLocName The local name of the child elements to be searched for. + * + * @param firstOnly Specifies wheter only the first or all child elements with the specified namespace and + * local name should be returned. + * + * @return a java.util.List with objects of type org.w3c.dom.Element; each + * element in the list represents a child element as specified above. If parent + * equals null, or if there are no child elements as specified above, null + * will be returned. + */ + public static List getChildElems(Element parent, String childNS, String childLocName, boolean firstOnly) + { + if (parent == null) return null; + + ArrayList childElems = new ArrayList(); + NodeList childNodes = parent.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) + { + Node currNode = childNodes.item(i); + if (currNode.getNodeType() == Node.ELEMENT_NODE) + { + Element currElem = (Element) currNode; + if (childNS.equals(currElem.getNamespaceURI()) && childLocName.equals(currElem.getLocalName())) + { + childElems.add(currElem); + if (firstOnly) break; + } + } + } + return (childElems.size() == 0) ? null : childElems; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public static Document parseWellFormed(InputStream is) throws Exception + { + DOMParser xmlParser = new DOMParser(); + try + { + xmlParser.setFeature(SAX_NAMESPACES_FEATURE, true); + xmlParser.setFeature(XERCES_CREATE_ENTITY_REF_NODES_FEATURE, false); + xmlParser.setFeature(XERCES_DEFER_NODE_EXPANSION_, false); + xmlParser.setErrorHandler(new XMLParserErrorHandler(false, true, true)); + } + catch (SAXException e) + { + String message = "Initialization of XML parser failed."; + throw new Exception(message, e); + } + try + { + xmlParser.parse(new InputSource(is)); + return xmlParser.getDocument(); + } + catch (Exception e) + { + String message = "Wellformed parsing failed."; + throw new Exception(message, e); + } + } +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/Utils.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/Utils.java new file mode 100644 index 000000000..2f9e01057 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/Utils.java @@ -0,0 +1,106 @@ +/* + * Created on 25.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.ss.erechtclient.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Properties; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +import at.gv.egovernment.moa.ss.erechtclient.ERechtClientException; +import at.gv.egovernment.moa.ss.erechtclient.init.Constants; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class Utils +{ + public static byte[] readFromInputStream(InputStream inputStream) throws IOException + { + byte[] currentBytes = new byte[500]; + int bytesRead; + ByteArrayOutputStream result = new ByteArrayOutputStream(); + do + { + bytesRead = inputStream.read(currentBytes); + if (bytesRead > 0) + { + result.write(currentBytes, 0, bytesRead); + } + } + while (bytesRead != -1); + return result.toByteArray(); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public static void transferStreams(InputStream in, OutputStream out) throws IOException + { + byte[] currentBytes = new byte[500]; + int bytesRead; + do + { + bytesRead = in.read(currentBytes); + if (bytesRead > 0) + { + out.write(currentBytes, 0, bytesRead); + } + } + while (bytesRead != -1); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public static void returnErrorPage(HttpServletRequest request, HttpServletResponse response, Throwable t) + throws ServletException + { + Logger logger = Logger.getLogger(Constants.LH_SERVLETS_); + + // Store Throwable in request context + request.setAttribute(Constants.RCP_ERROR_THROWABLE_, t); + + RequestDispatcher dispatcher = request.getRequestDispatcher(Constants.JSPPN_ERROR_); + try + { + dispatcher.include(request, response); + } + catch (ServletException e) + { + logger.error("Returning error JSP page failed.", e); + throw e; + } + catch (IOException e) + { + String message = "Returning error JSP page failed."; + logger.error(message, e); + throw new ServletException(message, e); + } + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public static String readInitProperty(Properties initProps, String name, Logger logger) + throws ERechtClientException + { + String value = initProps.getProperty(name); + if (value == null) + { + String message = "Could not read property \"" + name + "\" from configuration properties."; + logger.error(message); + throw new ERechtClientException(message); + } + return value; + } +} diff --git a/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/XPathUtils.java b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/XPathUtils.java new file mode 100644 index 000000000..4f2862f58 --- /dev/null +++ b/erecht.client.ss/src/at/gv/egovernment/moa/ss/erechtclient/util/XPathUtils.java @@ -0,0 +1,162 @@ +/* + * Created on 02.12.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.ss.erechtclient.util; + +import java.util.HashMap; +import java.util.StringTokenizer; + +import org.apache.xml.utils.PrefixResolverDefault; +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; +import org.apache.xpath.objects.XObject; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class XPathUtils +{ + /** + * The XPath context for the XPath engine. + */ + protected XPathContext xPathContext_; + + /** + * The prefix resolver for the XPath engine. + */ + protected PrefixResolver prefixResolver_; + + /** + * The XPath engine. + */ + protected XPath xPath_; + + /* ==================================================================================================== */ + + public void setupContext(String xPathExpr, Node namespaceNode, String additionalNSPrefixes) + throws Exception + { + + try + { + // Set up a new evaluation context + xPathContext_ = new XPathContext(); + + // Set up the namespace prefix resolver for the XPath engine + prefixResolver_ = new PrefixResolver(namespaceNode, additionalNSPrefixes); + + // Initialize XPath engine + xPath_ = new XPath(xPathExpr, null, prefixResolver_, XPath.SELECT, null); + } + catch (Exception e) + { + throw new Exception("Setting up XPath evaluation context failed.", e); + } + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public NodeList selectNodeSet(Node contextNode) throws Exception + { + XObject xObject; + try + { + xObject = xPath_.execute(xPathContext_, contextNode, prefixResolver_); + return xObject.nodelist(); + } + catch (Exception e) + { + throw new Exception("Executing XPath expression failed.", e); + } + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public boolean selectBoolean(Node contextNode) throws Exception + { + XObject xObject; + try + { + xObject = xPath_.execute(xPathContext_, contextNode, prefixResolver_); + return xObject.bool(); + } + catch (Exception e) + { + throw new Exception("Executing XPath expression failed.", e); + } + } + + /* ==================================================================================================== */ + + /** + * Special extension of the {@link org.apache.xml.utils.PrefixResolverDefault} interface. Used to + * configure the Apache Xalan XPath engine which is employed as the backbone of this class. + */ + protected class PrefixResolver extends PrefixResolverDefault + { + + /** + * Contains the additionally specified namespace prefix (key) to namespace URI (value) attributions. + */ + protected HashMap additionalNSPrefixesMap_; + + /* ================================================================================================== */ + + /** + * Basic constructor. + * + * @param xpathExpressionContext The namespace declarations in scope for this node will be used to get + * the namespace uri for a prefix specified in the XPath expression. + * + * @param additionalNSPrefixes Allows the specification of additional prefix to uri attributions apart + * from the declarations in scope for the parameter + * xpathExpressionContext. May be null. + */ + public PrefixResolver(Node xpathExpressionContext, String additionalNSPrefixes) throws Exception + { + super(xpathExpressionContext); + additionalNSPrefixesMap_ = new HashMap(); + + // Register the specified additional namespace prefix to namespace uri attributions + if (additionalNSPrefixes != null) + { + StringTokenizer tokenizer = new StringTokenizer(additionalNSPrefixes, " "); + while (tokenizer.hasMoreTokens()) + { + String prefix = tokenizer.nextToken(); + if (!tokenizer.hasMoreTokens()) + { + + // There must be an even number of tokens in the string + throw new Exception("Parameter \"additionalNSPrefixes\" must have an even number of tokens."); + } + String uri = tokenizer.nextToken(); + additionalNSPrefixesMap_.put(prefix, uri); + } + } + } + + /* -------------------------------------------------------------------------------------------------- */ + + /** + * Gets the namespace uri for the specified namespace prefix. The additionally specified prefixes + * overrule the prefixes found in the specified namespace node. + * + * @param prefix The namespace prefix for which a namespace uri should be found. + * + * @return the namespace uri for the specified namespace prefix. + */ + public String getNamespaceForPrefix(String prefix) + { + String additionalURI = (String) additionalNSPrefixesMap_.get(prefix); + return (additionalURI != null) + ? additionalURI + : super.getNamespaceForPrefix(prefix); + } + } +} + -- cgit v1.2.3