From d89f36b67ea1d838a78523538a24e044518f3587 Mon Sep 17 00:00:00 2001 From: mcentner Date: Tue, 26 Jan 2010 16:22:56 +0000 Subject: MOCCA 1.2.11 with SHA-2 enabled. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/branches/mocca-1.2.11-sha2@599 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/slcommands/SLCommandFactory.java | 395 +++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 mocca-1.2.11/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java (limited to 'mocca-1.2.11/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java') diff --git a/mocca-1.2.11/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java b/mocca-1.2.11/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java new file mode 100644 index 00000000..6e84867e --- /dev/null +++ b/mocca-1.2.11/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java @@ -0,0 +1,395 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands; + +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.UnmarshalException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.ValidationEvent; +import javax.xml.bind.ValidationEventLocator; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.bku.slexceptions.SLRequestException; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.slexceptions.SLVersionException; +import at.gv.egiz.bku.utils.DebugReader; +import at.gv.egiz.slbinding.RedirectEventFilter; +import at.gv.egiz.slbinding.RedirectUnmarshallerListener; +import at.gv.egiz.validation.ReportingValidationEventHandler; + +public class SLCommandFactory { + + /** + * Schema files required for Security Layer command validation. + */ + public static final String[] SCHEMA_FILES = new String[]{ + "at/gv/egiz/bku/slcommands/schema/xml.xsd", + "at/gv/egiz/bku/slcommands/schema/xmldsig-core-schema.xsd", + "at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd", + "at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd", + "at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd" + }; + /** + * Logging facility. + */ + static Log log = LogFactory.getLog(SLCommandFactory.class); + /** + * The instance returned by {@link #getInstance()}. + */ + private static SLCommandFactory instance; + /** + * Schema for Security Layer command validation. + */ + private Schema slSchema; + /** + * The JAXBContext. + */ + private JAXBContext jaxbContext; + /** + * The map of : to implementation class of the + * corresponding {@link SLCommand}. + */ + private Map> slRequestTypeMap = new HashMap>(); + + /** + * The mapping of a requests's qualified name to a concrete command factories. + */ + private Map slCommandFactories = new HashMap(); + + /** + * Configures the singleton instance with command implementations + * @param commandImplMap + * @throws ClassNotFoundException + */ + @SuppressWarnings("unchecked") + public void setCommandImpl(Map commandImplMap) throws ClassNotFoundException { + ClassLoader cl = getClass().getClassLoader(); + for (String key : commandImplMap.keySet()) { + Class impl = (Class) cl.loadClass(commandImplMap.get(key)); + log.debug("Registering sl command implementation for :"+key+ "; implementation class: "+impl.getCanonicalName()); + slRequestTypeMap.put(key, impl); + } + } + + public void setConcreteFactories(Map factories) { + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Registered sl command factory for"); + for (QName qname : factories.keySet()) { + sb.append("\n " + qname + " : " + factories.get(qname).getClass()); + } + log.debug(sb); + } + slCommandFactories = factories; + } + + /** + * Register an {@link SLCommand} implementation class of a Security Layer + * command with the given namespaceUri and localname + * . + * + * @param namespaceUri + * the namespace URI of the Security Layer command + * @param localname + * the localname of the Security Layer command + * @param slCommandClass + * the implementation class, or null to deregister a + * currently registered class + */ + public void setImplClass(String namespaceUri, String localname, + Class slCommandClass) { + if (slCommandClass != null) { + slRequestTypeMap.put(namespaceUri + ":" + localname, slCommandClass); + } else { + slRequestTypeMap.remove(namespaceUri + ":" + localname); + } + } + + /** + * Returns the implementation class of an {@link SLCommand} with the given + * name, or null if no such class is registered. + * + * @param name + * the QName of the Security Layer command + * @return the implementation class, or null if no class is + * registered for the given name + */ + public Class getImplClass(QName name) { + String namespaceURI = name.getNamespaceURI(); + String localPart = name.getLocalPart(); + return slRequestTypeMap.get(namespaceURI + ":" + localPart); + } + + /** + * Sets the schema to validate Security Layer commands with. + * + * @param slSchema the schema to validate Security Layer commands with + */ + public void setSLSchema(Schema slSchema) { + this.slSchema = slSchema; + } + + /** + * @return the jaxbContext + */ + public JAXBContext getJaxbContext() { + ensureJaxbContext(); + return jaxbContext; + } + + /** + * @param jaxbContext the jaxbContext to set + */ + public void setJaxbContext(JAXBContext jaxbContext) { + this.jaxbContext = jaxbContext; + } + + /** + * Initialize the JAXBContext. + */ + private synchronized void ensureJaxbContext() { + if (jaxbContext == null) { + try { + String slPkg = at.buergerkarte.namespaces.securitylayer._1.ObjectFactory.class.getPackage().getName(); + String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); + String cardChannelPkg = at.buergerkarte.namespaces.cardchannel.ObjectFactory.class.getPackage().getName(); + String slPkgLegacy1_0 = at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory.class.getPackage().getName(); + String slPkgLegacy1_1 = at.buergerkarte.namespaces.securitylayer._20020831_.ObjectFactory.class.getPackage().getName(); + setJaxbContext(JAXBContext.newInstance(slPkg + ":" + xmldsigPkg + ":" + cardChannelPkg + + ":" + slPkgLegacy1_0 + ":" + slPkgLegacy1_1)); + } catch (JAXBException e) { + log.error("Failed to setup JAXBContext security layer request.", e); + throw new SLRuntimeException(e); + } + } + } + + /** + * Initialize the security layer schema. + */ + private synchronized void ensureSchema() { + if (slSchema == null) { + try { + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + ClassLoader cl = SLCommandFactory.class.getClassLoader(); + Source[] sources = new Source[SCHEMA_FILES.length]; + for (int i = 0; i < SCHEMA_FILES.length; i++) { + String schemaFile = SCHEMA_FILES[i]; + URL schemaURL = cl.getResource(schemaFile); + if (schemaURL == null) { + throw new SLRuntimeException("Failed to load schema file " + schemaFile + "."); + } + log.debug("Schema location: " + schemaURL); + sources[i] = new StreamSource(schemaURL.openStream()); + } + Schema schema = schemaFactory.newSchema(sources); + log.debug("Schema successfully created."); + setSLSchema(schema); + } catch (SAXException e) { + log.error("Failed to load security layer schema.", e); + throw new SLRuntimeException("Failed to load security layer schema.", e); + } catch (IOException e) { + log.error("Failed to load security layer schema.", e); + throw new SLRuntimeException("Failed to load security layer schema.", e); + } + + } + } + + /** + * Get an instance of the SLCommandFactory. + */ + public synchronized static SLCommandFactory getInstance() { + if (instance == null) { + instance = new SLCommandFactory(); + instance.ensureJaxbContext(); + instance.ensureSchema(); + } + return instance; + } + + /** + * Private constructor used by {@link #getInstance()}. + */ + private SLCommandFactory() { + } + + /** + * Unmarshalls from the given source. + * + * @see Unmarshaller#unmarshal(Source) + * + * Note:Could replace JAXB's unmarshal-time validation engine (see commented code), however, + * we need a redirect filter. + * + * @param source + * the source to unmarshal from + * @return the object returned by {@link Unmarshaller#unmarshal(Source)} + * @throws SLRequestException + * if unmarshalling fails + * @throws SLRuntimeException + * if an unexpected error occurs configuring the unmarshaller or if + * unmarshalling fails with an unexpected error + */ + protected Object unmarshal(Source source) throws SLRuntimeException, + SLRequestException { + + Object object; + ReportingValidationEventHandler validationEventHandler = new ReportingValidationEventHandler(); + try { + + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + XMLEventReader eventReader = inputFactory.createXMLEventReader(source); + RedirectEventFilter redirectEventFilter = new RedirectEventFilter(); + XMLEventReader filteredReader = inputFactory.createFilteredReader(eventReader, redirectEventFilter); + + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + unmarshaller.setListener(new RedirectUnmarshallerListener(redirectEventFilter)); + if (slSchema != null) { + unmarshaller.setSchema(slSchema); + } + log.trace("Before unmarshal()."); + unmarshaller.setEventHandler(validationEventHandler); + object = unmarshaller.unmarshal(filteredReader); + log.trace("After unmarshal()."); + } catch (UnmarshalException e) { + if (log.isDebugEnabled()) { + log.debug("Failed to unmarshall security layer request.", e); + } else { + log.info("Failed to unmarshall security layer request." + e.getMessage()); + } + if (validationEventHandler.getErrorEvent() != null) { + // Validation Error + ValidationEvent errorEvent = validationEventHandler.getErrorEvent(); + ValidationEventLocator locator = errorEvent.getLocator(); + throw new SLRequestException(3002, + SLExceptionMessages.EC3002_INVALID, new Object[]{errorEvent.getMessage()}); + } + Throwable cause = e.getCause(); + if (cause instanceof SAXParseException) { + throw new SLRequestException(3000, + SLExceptionMessages.EC3000_UNCLASSIFIED, new Object[]{cause.getMessage()}); + } else { + throw new SLRequestException(3000, + SLExceptionMessages.EC3000_UNCLASSIFIED, new Object[]{e}); + } + } catch (JAXBException e) { + // unexpected error + log.error("Failed to unmarshall security layer request.", e); + throw new SLRuntimeException(e); + } catch (XMLStreamException e) { + // unexpected error + log.error("Failed to unmarshall security layer request.", e); + throw new SLRuntimeException(e); + } + + return object; + + } + + /** + * Creates a new SLCommand from the given source and + * context. + * + * @param source + * the Source to unmarshall from + * @param context + * the context for the created SLCommand + * @return the SLCommand unmarshalled from the given + * source + * @throws SLRequestException + * if unmarshalling fails + * @throws SLCommandException + * if command ist not supported + * @throws SLRuntimeException + * if an unexpected error occurs configuring the unmarshaller, if + * unmarshalling fails with an unexpected error or if the + * corresponding SLCommand could not be instantiated + * @throws SLVersionException + */ + @SuppressWarnings("unchecked") + public SLCommand createSLCommand(Source source, SLCommandContext context) + throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { + + DebugReader dr = null; + if (log.isTraceEnabled() && source instanceof StreamSource) { + StreamSource streamSource = (StreamSource) source; + if (streamSource.getReader() != null) { + dr = new DebugReader(streamSource.getReader(), "SLCommand unmarshalled from:\n"); + streamSource.setReader(dr); + } + } + + Object object; + try { + object = unmarshal(source); + } catch (SLRequestException e) { + throw e; + } finally { + if (dr != null) { + log.trace(dr.getCachedString()); + } + } + + if (!(object instanceof JAXBElement)) { + // invalid request + log.info("Invalid security layer request. " + object.toString()); + throw new SLRequestException(3002, SLExceptionMessages.EC3002_INVALID, + new Object[]{object.toString()}); + } + + QName qName = ((JAXBElement) object).getName(); + if (!SLCommand.NAMESPACE_URI.equals(qName.getNamespaceURI())) { + // security layer request version not supported + log.info("Unsupported security layer request version : " + qName.getNamespaceURI()); + throw new SLVersionException(qName.getNamespaceURI()); + } + + AbstractSLCommandFactory concreteFactory = slCommandFactories.get(qName); + if (concreteFactory == null) { + // command not supported + log.info("Unsupported command received: " + qName.toString()); + throw new SLCommandException(4011, + SLExceptionMessages.EC4011_NOTIMPLEMENTED, new Object[]{qName.toString()}); + } + + return concreteFactory.createSLCommand(context, (JAXBElement) object); + + } +} \ No newline at end of file -- cgit v1.2.3