/* * 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.util.HashMap; import java.util.Map; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.UnmarshalException; import javax.xml.bind.Unmarshaller; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.SLUnmarshaller; public class SLCommandFactory extends SLUnmarshaller { private final Logger log = LoggerFactory.getLogger(SLCommandFactory.class); private static class SLCommandFactoryInstance { private static final SLCommandFactory INSTANCE = new SLCommandFactory(); } /** * The mapping of a requests's qualified name to a concrete command factories. */ private Map slCommandFactories = new HashMap(); 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.toString()); } slCommandFactories = factories; } /** * Get an instance of the SLCommandFactory. */ public synchronized static SLCommandFactory getInstance() { return SLCommandFactoryInstance.INSTANCE; } /** * Private constructor used by {@link #getInstance()}. */ private SLCommandFactory() { super(); } /** * Creates a new SLCommand from the given source and * context. * * @param source * the Source to unmarshall from * @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 */ public SLCommand createSLCommand(Source source) 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 = unmarshalRequest(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.\n{}", object.toString()); throw new SLRequestException(3002, SLExceptionMessages.EC3002_INVALID, new Object[] { object.toString() }); } return createSLCommand((JAXBElement) object); } /** * Creates a new SLCommand from the given element * and context. * * @param element * the request element * @return the SLCommand for for the given element * @throws SLCommandException * if command ist not supported * @throws SLVersionException */ public SLCommand createSLCommand(JAXBElement element) throws SLCommandException, SLVersionException { QName qName = element.getName(); if (SLCommand.NAMESPACE_URI_20020831.equals(qName.getNamespaceURI()) || SLCommand.NAMESPACE_URI_20020225.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(element); } /** * 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 unmarshalRequest(Source source) throws SLRuntimeException, SLRequestException { try { return unmarshal(source); } 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 (e.getLinkedException() != null) { throw new SLRequestException(3002, SLExceptionMessages.EC3002_INVALID, new Object[] { e.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); } } }