/**************************************************************************** * Copyright (C) 2012 ecsec GmbH. * All rights reserved. * Contact: ecsec GmbH (info@ecsec.de) * * This file is part of the Open eCard App. * * GNU General Public License Usage * This file may be used under the terms of the GNU General Public * License version 3.0 as published by the Free Software Foundation * and appearing in the file LICENSE.GPL included in the packaging of * this file. Please review the following information to ensure the * GNU General Public License version 3.0 requirements will be met: * http://www.gnu.org/copyleft/gpl.html. * * Other Usage * Alternatively, this file may be used in accordance with the terms * and conditions contained in a signed written agreement between * you and ecsec GmbH. * ***************************************************************************/ package org.openecard.ws.jaxb; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import javax.xml.bind.JAXBException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.openecard.ws.marshal.MarshallingTypeException; import org.openecard.ws.marshal.WSMarshaller; import org.openecard.ws.marshal.WSMarshallerException; import org.openecard.ws.marshal.WhitespaceFilter; import org.openecard.ws.soap.MessageFactory; import org.openecard.ws.soap.SOAPBody; import org.openecard.ws.soap.SOAPException; import org.openecard.ws.soap.SOAPMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Implementation of a WSMarshaller utilizing JAXB and Javas default XML facilities. * * @author Tobias Wich <tobias.wich@ecsec.de> */ public final class JAXBMarshaller implements WSMarshaller { private static final Logger logger = LoggerFactory.getLogger(JAXBMarshaller.class); // Marshaller and Unmarshaller private final MarshallerImpl marshaller; // w3 factory private final DocumentBuilderFactory w3Factory; private final DocumentBuilder w3Builder; private final Transformer serializer; // soap private final MessageFactory soapFactory; /** * Creates a JAXBMarshaller capable of marshalling und unmarshalling all JAXB element types found in the classpath * resource classes.lst. */ public JAXBMarshaller() { MarshallerImpl tmpMarshaller = null; DocumentBuilderFactory tmpW3Factory = null; DocumentBuilder tmpW3Builder = null; Transformer tmpSerializer = null; MessageFactory tmpSoapFactory = null; try { tmpMarshaller = new MarshallerImpl(); // instantiate w3 stuff tmpW3Factory = DocumentBuilderFactory.newInstance(); tmpW3Factory.setNamespaceAware(true); tmpW3Factory.setIgnoringComments(true); tmpW3Builder = tmpW3Factory.newDocumentBuilder(); TransformerFactory tfactory = TransformerFactory.newInstance(); tmpSerializer = tfactory.newTransformer(); tmpSerializer.setOutputProperty(OutputKeys.INDENT, "yes"); tmpSerializer.setOutputProperty(OutputKeys.STANDALONE, "yes"); tmpSerializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); tmpSerializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); // instantiate soap stuff tmpSoapFactory = MessageFactory.newInstance(); } catch (Exception ex) { logger.error("Failed to initialize XML components.", ex); System.exit(1); // non recoverable } marshaller = tmpMarshaller; w3Factory = tmpW3Factory; w3Builder = tmpW3Builder; serializer = tmpSerializer; soapFactory = tmpSoapFactory; } //////////////////////////////////////////////////////////////////////////// // public functions to marshal and convert stuff //////////////////////////////////////////////////////////////////////////// @Override public void addXmlTypeClass(Class xmlTypeClass) throws MarshallingTypeException { marshaller.addXmlClass(xmlTypeClass); } @Override public void removeAllTypeClasses() { marshaller.removeAllClasses(); } @Override public synchronized Document str2doc(String docStr) throws SAXException { try { // read dom as w3 StringReader strReader = new StringReader(docStr); InputSource inSrc = new InputSource(strReader); Document doc = w3Builder.parse(inSrc); WhitespaceFilter.filter(doc); return doc; } catch (IOException ex) { throw new SAXException(ex); } } @Override public synchronized Document str2doc(InputStream docStr) throws SAXException, IOException { // read dom as w3 Document doc = w3Builder.parse(docStr); WhitespaceFilter.filter(doc); return doc; } @Override public synchronized String doc2str(Node doc) throws TransformerException { ByteArrayOutputStream out = new ByteArrayOutputStream(); serializer.transform(new DOMSource(doc), new StreamResult(out)); String result; try { result = out.toString("UTF-8"); } catch (UnsupportedEncodingException ex) { throw new TransformerException(ex); } return result; } @Override public synchronized Object unmarshal(Node n) throws MarshallingTypeException, WSMarshallerException { Document newDoc = null; if (n instanceof Document) { newDoc = (Document) n; } else if(n instanceof Element) { newDoc = w3Builder.newDocument(); Node root = newDoc.importNode(n, true); newDoc.appendChild(root); } else { throw new WSMarshallerException("Only w3c Document and Element are accepted."); } Object result; try { result = marshaller.getUnmarshaller().unmarshal(newDoc); //NOI18N } catch (JAXBException ex) { throw new MarshallingTypeException(ex); } return result; } @Override public synchronized Document marshal(Object o) throws MarshallingTypeException { try { StringWriter sw = new StringWriter(); XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(sw); // wrap writer so specific ns prefixes are written out correctly XMLStreamWriterWrapper xmlwrap = new XMLStreamWriterWrapper(xmlStreamWriter); marshaller.getMarshaller().marshal(o, xmlwrap); return str2doc(sw.toString()); } catch (Exception ex) { throw new MarshallingTypeException(ex); } } @Override public synchronized SOAPMessage doc2soap(Document envDoc) throws SOAPException { SOAPMessage msg = soapFactory.createMessage(envDoc); return msg; } @Override public synchronized SOAPMessage add2soap(Document content) throws SOAPException { SOAPMessage msg = soapFactory.createMessage(); SOAPBody body = msg.getSOAPBody(); body.addDocument(content); return msg; } }