aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.ws.commons.xmlutil; aoqi@0: aoqi@0: import com.sun.istack.internal.NotNull; aoqi@0: import com.sun.istack.internal.logging.Logger; aoqi@0: import com.sun.xml.internal.ws.api.message.Message; aoqi@0: import com.sun.xml.internal.ws.api.message.Messages; aoqi@0: import com.sun.xml.internal.ws.api.message.Packet; aoqi@0: import com.sun.xml.internal.ws.util.xml.XmlUtil; aoqi@0: aoqi@0: import javax.xml.stream.*; aoqi@0: import javax.xml.xpath.XPathFactoryConfigurationException; aoqi@0: import java.io.*; aoqi@0: import java.lang.reflect.Constructor; aoqi@0: import java.util.concurrent.atomic.AtomicBoolean; aoqi@0: import java.util.logging.Level; aoqi@0: aoqi@0: /** aoqi@0: * Utility class that provides conversion of different XML representations aoqi@0: * from/to various other formats aoqi@0: * aoqi@0: * @author Marek Potociar aoqi@0: */ aoqi@0: public final class Converter { aoqi@0: aoqi@0: public static final String UTF_8 = "UTF-8"; aoqi@0: aoqi@0: private Converter() { aoqi@0: // prevents instantiation aoqi@0: } aoqi@0: private static final Logger LOGGER = Logger.getLogger(Converter.class); aoqi@0: private static final ContextClassloaderLocal xmlOutputFactory = new ContextClassloaderLocal() { aoqi@0: @Override aoqi@0: protected XMLOutputFactory initialValue() throws Exception { aoqi@0: return XMLOutputFactory.newInstance(); aoqi@0: } aoqi@0: }; aoqi@0: private static final AtomicBoolean logMissingStaxUtilsWarning = new AtomicBoolean(false); aoqi@0: aoqi@0: /** aoqi@0: * Converts a throwable to String aoqi@0: * aoqi@0: * @param throwable aoqi@0: * @return String representation of throwable aoqi@0: */ aoqi@0: public static String toString(Throwable throwable) { aoqi@0: if (throwable == null) { aoqi@0: return "[ No exception ]"; aoqi@0: } aoqi@0: aoqi@0: StringWriter stringOut = new StringWriter(); aoqi@0: throwable.printStackTrace(new PrintWriter(stringOut)); aoqi@0: aoqi@0: return stringOut.toString(); aoqi@0: } aoqi@0: aoqi@0: public static String toString(Packet packet) { aoqi@0: if (packet == null) { aoqi@0: return "[ Null packet ]"; aoqi@0: } else if (packet.getMessage() == null) { aoqi@0: return "[ Empty packet ]"; aoqi@0: } aoqi@0: aoqi@0: return toString(packet.getMessage()); aoqi@0: } aoqi@0: aoqi@0: public static String toStringNoIndent(Packet packet) { aoqi@0: if (packet == null) { aoqi@0: return "[ Null packet ]"; aoqi@0: } else if (packet.getMessage() == null) { aoqi@0: return "[ Empty packet ]"; aoqi@0: } aoqi@0: aoqi@0: return toStringNoIndent(packet.getMessage()); aoqi@0: } aoqi@0: aoqi@0: public static String toString(Message message) { aoqi@0: return toString(message, true); aoqi@0: } aoqi@0: aoqi@0: public static String toStringNoIndent(Message message) { aoqi@0: return toString(message, false); aoqi@0: } aoqi@0: aoqi@0: private static String toString(Message message, boolean createIndenter) { aoqi@0: if (message == null) { aoqi@0: return "[ Null message ]"; aoqi@0: } aoqi@0: StringWriter stringOut = null; aoqi@0: try { aoqi@0: stringOut = new StringWriter(); aoqi@0: XMLStreamWriter writer = null; aoqi@0: try { aoqi@0: writer = xmlOutputFactory.get().createXMLStreamWriter(stringOut); aoqi@0: if (createIndenter) { aoqi@0: writer = createIndenter(writer); aoqi@0: } aoqi@0: message.copy().writeTo(writer); aoqi@0: } catch (Exception e) { // WSIT-1596 - Message Dumping should not affect other processing aoqi@0: LOGGER.log(Level.WARNING, "Unexpected exception occured while dumping message", e); aoqi@0: } finally { aoqi@0: if (writer != null) { aoqi@0: try { aoqi@0: writer.close(); aoqi@0: } catch (XMLStreamException ignored) { aoqi@0: LOGGER.fine("Unexpected exception occured while closing XMLStreamWriter", ignored); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: return stringOut.toString(); aoqi@0: } finally { aoqi@0: if (stringOut != null) { aoqi@0: try { aoqi@0: stringOut.close(); aoqi@0: } catch (IOException ex) { aoqi@0: LOGGER.finest("An exception occured when trying to close StringWriter", ex); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public static byte[] toBytes(Message message, String encoding) throws XMLStreamException { aoqi@0: ByteArrayOutputStream baos = new ByteArrayOutputStream(); aoqi@0: aoqi@0: try { aoqi@0: if (message != null) { aoqi@0: XMLStreamWriter xsw = xmlOutputFactory.get().createXMLStreamWriter(baos, encoding); aoqi@0: try { aoqi@0: message.writeTo(xsw); aoqi@0: } finally { aoqi@0: try { aoqi@0: xsw.close(); aoqi@0: } catch (XMLStreamException ex) { aoqi@0: LOGGER.warning("Unexpected exception occured while closing XMLStreamWriter", ex); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return baos.toByteArray(); aoqi@0: } finally { aoqi@0: try { aoqi@0: baos.close(); aoqi@0: } catch (IOException ex) { aoqi@0: LOGGER.warning("Unexpected exception occured while closing ByteArrayOutputStream", ex); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Converts JAX-WS RI message represented as input stream back to Message aoqi@0: * object. aoqi@0: * aoqi@0: * @param dataStream message data stream aoqi@0: * @param encoding message data stream encoding aoqi@0: * aoqi@0: * @return {@link com.sun.xml.internal.ws.api.message.Message} object created from the data stream aoqi@0: */ aoqi@0: public static Message toMessage(@NotNull InputStream dataStream, String encoding) throws XMLStreamException { aoqi@0: XMLStreamReader xsr = XmlUtil.newXMLInputFactory(true).createXMLStreamReader(dataStream, encoding); aoqi@0: return Messages.create(xsr); aoqi@0: } aoqi@0: aoqi@0: public static String messageDataToString(final byte[] data, final String encoding) { aoqi@0: try { aoqi@0: return toString(toMessage(new ByteArrayInputStream(data), encoding)); aoqi@0: // closing ByteArrayInputStream has no effect, so ignoring the redundant call aoqi@0: } catch (XMLStreamException ex) { aoqi@0: LOGGER.warning("Unexpected exception occured while converting message data to string", ex); aoqi@0: return "[ Message Data Conversion Failed ]"; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Wraps {@link javax.xml.stream.XMLStreamWriter} by an indentation engine if possible. aoqi@0: * aoqi@0: *

aoqi@0: * We can do this only when we have stax-utils.jar in the class path. aoqi@0: */ aoqi@0: private static XMLStreamWriter createIndenter(XMLStreamWriter writer) { aoqi@0: try { aoqi@0: Class clazz = Converter.class.getClassLoader().loadClass("javanet.staxutils.IndentingXMLStreamWriter"); aoqi@0: Constructor c = clazz.getConstructor(XMLStreamWriter.class); aoqi@0: writer = XMLStreamWriter.class.cast(c.newInstance(writer)); aoqi@0: } catch (Exception ex) { aoqi@0: // if stax-utils.jar is not in the classpath, this will fail aoqi@0: // so, we'll just have to do without indentation aoqi@0: if (logMissingStaxUtilsWarning.compareAndSet(false, true)) { aoqi@0: LOGGER.log(Level.WARNING, "Put stax-utils.jar to the classpath to indent the dump output", ex); aoqi@0: } aoqi@0: } aoqi@0: return writer; aoqi@0: } aoqi@0: }