1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.ws.commons.xmlutil; 27 28 import com.sun.istack.internal.NotNull; 29 import com.sun.istack.internal.logging.Logger; 30 import com.sun.xml.internal.ws.api.message.Message; 31 import com.sun.xml.internal.ws.api.message.Messages; 32 import com.sun.xml.internal.ws.api.message.Packet; 33 import com.sun.xml.internal.ws.util.xml.XmlUtil; 34 35 import javax.xml.stream.*; 36 import javax.xml.xpath.XPathFactoryConfigurationException; 37 import java.io.*; 38 import java.lang.reflect.Constructor; 39 import java.util.concurrent.atomic.AtomicBoolean; 40 import java.util.logging.Level; 41 42 /** 43 * Utility class that provides conversion of different XML representations 44 * from/to various other formats 45 * 46 * @author Marek Potociar 47 */ 48 public final class Converter { 49 50 public static final String UTF_8 = "UTF-8"; 51 52 private Converter() { 53 // prevents instantiation 54 } 55 private static final Logger LOGGER = Logger.getLogger(Converter.class); 56 private static final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance(); 57 private static final AtomicBoolean logMissingStaxUtilsWarning = new AtomicBoolean(false); 58 59 /** 60 * Converts a throwable to String 61 * 62 * @param throwable 63 * @return String representation of throwable 64 */ 65 public static String toString(Throwable throwable) { 66 if (throwable == null) { 67 return "[ No exception ]"; 68 } 69 70 StringWriter stringOut = new StringWriter(); 71 throwable.printStackTrace(new PrintWriter(stringOut)); 72 73 return stringOut.toString(); 74 } 75 76 public static String toString(Packet packet) { 77 if (packet == null) { 78 return "[ Null packet ]"; 79 } else if (packet.getMessage() == null) { 80 return "[ Empty packet ]"; 81 } 82 83 return toString(packet.getMessage()); 84 85 } 86 87 public static String toString(Message message) { 88 if (message == null) { 89 return "[ Null message ]"; 90 } 91 StringWriter stringOut = null; 92 try { 93 stringOut = new StringWriter(); 94 XMLStreamWriter writer = null; 95 try { 96 writer = xmlOutputFactory.createXMLStreamWriter(stringOut); 97 writer = createIndenter(writer); 98 message.copy().writeTo(writer); 99 } catch (Exception e) { // WSIT-1596 - Message Dumping should not affect other processing 100 LOGGER.log(Level.WARNING, "Unexpected exception occured while dumping message", e); 101 } finally { 102 if (writer != null) { 103 try { 104 writer.close(); 105 } catch (XMLStreamException ignored) { 106 LOGGER.fine("Unexpected exception occured while closing XMLStreamWriter", ignored); 107 } 108 } 109 } 110 return stringOut.toString(); 111 } finally { 112 if (stringOut != null) { 113 try { 114 stringOut.close(); 115 } catch (IOException ex) { 116 LOGGER.finest("An exception occured when trying to close StringWriter", ex); 117 } 118 } 119 } 120 } 121 122 public static byte[] toBytes(Message message, String encoding) throws XMLStreamException { 123 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 124 125 try { 126 if (message != null) { 127 XMLStreamWriter xsw = xmlOutputFactory.createXMLStreamWriter(baos, encoding); 128 try { 129 message.writeTo(xsw); 130 } finally { 131 try { 132 xsw.close(); 133 } catch (XMLStreamException ex) { 134 LOGGER.warning("Unexpected exception occured while closing XMLStreamWriter", ex); 135 } 136 } 137 } 138 139 return baos.toByteArray(); 140 } finally { 141 try { 142 baos.close(); 143 } catch (IOException ex) { 144 LOGGER.warning("Unexpected exception occured while closing ByteArrayOutputStream", ex); 145 } 146 } 147 } 148 149 /** 150 * Converts JAX-WS RI message represented as input stream back to Message 151 * object. 152 * 153 * @param dataStream message data stream 154 * @param encoding message data stream encoding 155 * 156 * @return {@link com.sun.xml.internal.ws.api.message.Message} object created from the data stream 157 */ 158 public static Message toMessage(@NotNull InputStream dataStream, String encoding) throws XMLStreamException { 159 XMLStreamReader xsr = XmlUtil.newXMLInputFactory(true).createXMLStreamReader(dataStream, encoding); 160 return Messages.create(xsr); 161 } 162 163 public static String messageDataToString(final byte[] data, final String encoding) { 164 try { 165 return toString(toMessage(new ByteArrayInputStream(data), encoding)); 166 // closing ByteArrayInputStream has no effect, so ignoring the redundant call 167 } catch (XMLStreamException ex) { 168 LOGGER.warning("Unexpected exception occured while converting message data to string", ex); 169 return "[ Message Data Conversion Failed ]"; 170 } 171 } 172 173 /** 174 * Wraps {@link javax.xml.stream.XMLStreamWriter} by an indentation engine if possible. 175 * 176 * <p> 177 * We can do this only when we have <tt>stax-utils.jar</tt> in the class path. 178 */ 179 private static XMLStreamWriter createIndenter(XMLStreamWriter writer) { 180 try { 181 Class<?> clazz = Converter.class.getClassLoader().loadClass("javanet.staxutils.IndentingXMLStreamWriter"); 182 Constructor<?> c = clazz.getConstructor(XMLStreamWriter.class); 183 writer = XMLStreamWriter.class.cast(c.newInstance(writer)); 184 } catch (Exception ex) { 185 // if stax-utils.jar is not in the classpath, this will fail 186 // so, we'll just have to do without indentation 187 if (logMissingStaxUtilsWarning.compareAndSet(false, true)) { 188 LOGGER.log(Level.WARNING, "Put stax-utils.jar to the classpath to indent the dump output", ex); 189 } 190 } 191 return writer; 192 } 193 }