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 public static String toStringNoIndent(Packet packet) { 87 if (packet == null) { 88 return "[ Null packet ]"; 89 } else if (packet.getMessage() == null) { 90 return "[ Empty packet ]"; 91 } 92 93 return toStringNoIndent(packet.getMessage()); 94 } 95 96 public static String toString(Message message) { 97 return toString(message, true); 98 } 99 100 public static String toStringNoIndent(Message message) { 101 return toString(message, false); 102 } 103 104 private static String toString(Message message, boolean createIndenter) { 105 if (message == null) { 106 return "[ Null message ]"; 107 } 108 StringWriter stringOut = null; 109 try { 110 stringOut = new StringWriter(); 111 XMLStreamWriter writer = null; 112 try { 113 writer = xmlOutputFactory.createXMLStreamWriter(stringOut); 114 if (createIndenter) { 115 writer = createIndenter(writer); 116 } 117 message.copy().writeTo(writer); 118 } catch (Exception e) { // WSIT-1596 - Message Dumping should not affect other processing 119 LOGGER.log(Level.WARNING, "Unexpected exception occured while dumping message", e); 120 } finally { 121 if (writer != null) { 122 try { 123 writer.close(); 124 } catch (XMLStreamException ignored) { 125 LOGGER.fine("Unexpected exception occured while closing XMLStreamWriter", ignored); 126 } 127 } 128 } 129 return stringOut.toString(); 130 } finally { 131 if (stringOut != null) { 132 try { 133 stringOut.close(); 134 } catch (IOException ex) { 135 LOGGER.finest("An exception occured when trying to close StringWriter", ex); 136 } 137 } 138 } 139 } 140 141 public static byte[] toBytes(Message message, String encoding) throws XMLStreamException { 142 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 143 144 try { 145 if (message != null) { 146 XMLStreamWriter xsw = xmlOutputFactory.createXMLStreamWriter(baos, encoding); 147 try { 148 message.writeTo(xsw); 149 } finally { 150 try { 151 xsw.close(); 152 } catch (XMLStreamException ex) { 153 LOGGER.warning("Unexpected exception occured while closing XMLStreamWriter", ex); 154 } 155 } 156 } 157 158 return baos.toByteArray(); 159 } finally { 160 try { 161 baos.close(); 162 } catch (IOException ex) { 163 LOGGER.warning("Unexpected exception occured while closing ByteArrayOutputStream", ex); 164 } 165 } 166 } 167 168 /** 169 * Converts JAX-WS RI message represented as input stream back to Message 170 * object. 171 * 172 * @param dataStream message data stream 173 * @param encoding message data stream encoding 174 * 175 * @return {@link com.sun.xml.internal.ws.api.message.Message} object created from the data stream 176 */ 177 public static Message toMessage(@NotNull InputStream dataStream, String encoding) throws XMLStreamException { 178 XMLStreamReader xsr = XmlUtil.newXMLInputFactory(true).createXMLStreamReader(dataStream, encoding); 179 return Messages.create(xsr); 180 } 181 182 public static String messageDataToString(final byte[] data, final String encoding) { 183 try { 184 return toString(toMessage(new ByteArrayInputStream(data), encoding)); 185 // closing ByteArrayInputStream has no effect, so ignoring the redundant call 186 } catch (XMLStreamException ex) { 187 LOGGER.warning("Unexpected exception occured while converting message data to string", ex); 188 return "[ Message Data Conversion Failed ]"; 189 } 190 } 191 192 /** 193 * Wraps {@link javax.xml.stream.XMLStreamWriter} by an indentation engine if possible. 194 * 195 * <p> 196 * We can do this only when we have <tt>stax-utils.jar</tt> in the class path. 197 */ 198 private static XMLStreamWriter createIndenter(XMLStreamWriter writer) { 199 try { 200 Class<?> clazz = Converter.class.getClassLoader().loadClass("javanet.staxutils.IndentingXMLStreamWriter"); 201 Constructor<?> c = clazz.getConstructor(XMLStreamWriter.class); 202 writer = XMLStreamWriter.class.cast(c.newInstance(writer)); 203 } catch (Exception ex) { 204 // if stax-utils.jar is not in the classpath, this will fail 205 // so, we'll just have to do without indentation 206 if (logMissingStaxUtilsWarning.compareAndSet(false, true)) { 207 LOGGER.log(Level.WARNING, "Put stax-utils.jar to the classpath to indent the dump output", ex); 208 } 209 } 210 return writer; 211 } 212 }