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.util.xml; 27 28 import com.sun.istack.internal.Nullable; 29 import com.sun.org.apache.xml.internal.resolver.Catalog; 30 import com.sun.org.apache.xml.internal.resolver.CatalogManager; 31 import com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver; 32 import com.sun.xml.internal.ws.server.ServerRtException; 33 import com.sun.xml.internal.ws.util.ByteArrayBuffer; 34 import org.w3c.dom.Attr; 35 import org.w3c.dom.Element; 36 import org.w3c.dom.EntityReference; 37 import org.w3c.dom.Node; 38 import org.w3c.dom.NodeList; 39 import org.w3c.dom.Text; 40 import org.xml.sax.EntityResolver; 41 import org.xml.sax.ErrorHandler; 42 import org.xml.sax.SAXException; 43 import org.xml.sax.SAXParseException; 44 import org.xml.sax.XMLReader; 45 import org.xml.sax.InputSource; 46 47 import javax.xml.namespace.QName; 48 import javax.xml.parsers.ParserConfigurationException; 49 import javax.xml.parsers.SAXParserFactory; 50 import javax.xml.transform.Result; 51 import javax.xml.transform.Source; 52 import javax.xml.transform.Transformer; 53 import javax.xml.transform.TransformerConfigurationException; 54 import javax.xml.transform.TransformerException; 55 import javax.xml.transform.TransformerFactory; 56 import javax.xml.transform.sax.SAXTransformerFactory; 57 import javax.xml.transform.sax.TransformerHandler; 58 import javax.xml.transform.stream.StreamSource; 59 import javax.xml.ws.WebServiceException; 60 import java.io.IOException; 61 import java.io.InputStream; 62 import java.io.OutputStreamWriter; 63 import java.io.Writer; 64 import java.net.URL; 65 import java.util.ArrayList; 66 import java.util.Enumeration; 67 import java.util.Iterator; 68 import java.util.List; 69 import java.util.StringTokenizer; 70 71 /** 72 * @author WS Development Team 73 */ 74 public class XmlUtil { 75 private final static String LEXICAL_HANDLER_PROPERTY = 76 "http://xml.org/sax/properties/lexical-handler"; 77 78 public static String getPrefix(String s) { 79 int i = s.indexOf(':'); 80 if (i == -1) 81 return null; 82 return s.substring(0, i); 83 } 84 85 public static String getLocalPart(String s) { 86 int i = s.indexOf(':'); 87 if (i == -1) 88 return s; 89 return s.substring(i + 1); 90 } 91 92 93 94 public static String getAttributeOrNull(Element e, String name) { 95 Attr a = e.getAttributeNode(name); 96 if (a == null) 97 return null; 98 return a.getValue(); 99 } 100 101 public static String getAttributeNSOrNull( 102 Element e, 103 String name, 104 String nsURI) { 105 Attr a = e.getAttributeNodeNS(nsURI, name); 106 if (a == null) 107 return null; 108 return a.getValue(); 109 } 110 111 public static String getAttributeNSOrNull( 112 Element e, 113 QName name) { 114 Attr a = e.getAttributeNodeNS(name.getNamespaceURI(), name.getLocalPart()); 115 if (a == null) 116 return null; 117 return a.getValue(); 118 } 119 120 /* public static boolean matchesTagNS(Element e, String tag, String nsURI) { 121 try { 122 return e.getLocalName().equals(tag) 123 && e.getNamespaceURI().equals(nsURI); 124 } catch (NullPointerException npe) { 125 126 // localname not null since parsing would fail before here 127 throw new WSDLParseException( 128 "null.namespace.found", 129 e.getLocalName()); 130 } 131 } 132 133 public static boolean matchesTagNS( 134 Element e, 135 javax.xml.namespace.QName name) { 136 try { 137 return e.getLocalName().equals(name.getLocalPart()) 138 && e.getNamespaceURI().equals(name.getNamespaceURI()); 139 } catch (NullPointerException npe) { 140 141 // localname not null since parsing would fail before here 142 throw new WSDLParseException( 143 "null.namespace.found", 144 e.getLocalName()); 145 } 146 }*/ 147 148 public static Iterator getAllChildren(Element element) { 149 return new NodeListIterator(element.getChildNodes()); 150 } 151 152 public static Iterator getAllAttributes(Element element) { 153 return new NamedNodeMapIterator(element.getAttributes()); 154 } 155 156 public static List<String> parseTokenList(String tokenList) { 157 List<String> result = new ArrayList<String>(); 158 StringTokenizer tokenizer = new StringTokenizer(tokenList, " "); 159 while (tokenizer.hasMoreTokens()) { 160 result.add(tokenizer.nextToken()); 161 } 162 return result; 163 } 164 165 public static String getTextForNode(Node node) { 166 StringBuffer sb = new StringBuffer(); 167 168 NodeList children = node.getChildNodes(); 169 if (children.getLength() == 0) 170 return null; 171 172 for (int i = 0; i < children.getLength(); ++i) { 173 Node n = children.item(i); 174 175 if (n instanceof Text) 176 sb.append(n.getNodeValue()); 177 else if (n instanceof EntityReference) { 178 String s = getTextForNode(n); 179 if (s == null) 180 return null; 181 else 182 sb.append(s); 183 } else 184 return null; 185 } 186 187 return sb.toString(); 188 } 189 190 public static InputStream getUTF8Stream(String s) { 191 try { 192 ByteArrayBuffer bab = new ByteArrayBuffer(); 193 Writer w = new OutputStreamWriter(bab, "utf-8"); 194 w.write(s); 195 w.close(); 196 return bab.newInputStream(); 197 } catch (IOException e) { 198 throw new RuntimeException("should not happen"); 199 } 200 } 201 202 static final ContextClassloaderLocal<TransformerFactory> transformerFactory = new ContextClassloaderLocal<TransformerFactory>() { 203 @Override 204 protected TransformerFactory initialValue() throws Exception { 205 return TransformerFactory.newInstance(); 206 } 207 }; 208 209 static final ContextClassloaderLocal<SAXParserFactory> saxParserFactory = new ContextClassloaderLocal<SAXParserFactory>() { 210 @Override 211 protected SAXParserFactory initialValue() throws Exception { 212 SAXParserFactory factory = SAXParserFactory.newInstance(); 213 factory.setNamespaceAware(true); 214 return factory; 215 } 216 }; 217 218 /** 219 * Creates a new identity transformer. 220 */ 221 public static Transformer newTransformer() { 222 try { 223 return transformerFactory.get().newTransformer(); 224 } catch (TransformerConfigurationException tex) { 225 throw new IllegalStateException("Unable to create a JAXP transformer"); 226 } 227 } 228 229 /** 230 * Performs identity transformation. 231 */ 232 public static <T extends Result> 233 T identityTransform(Source src, T result) throws TransformerException, SAXException, ParserConfigurationException, IOException { 234 if (src instanceof StreamSource) { 235 // work around a bug in JAXP in JDK6u4 and earlier where the namespace processing 236 // is not turned on by default 237 StreamSource ssrc = (StreamSource) src; 238 TransformerHandler th = ((SAXTransformerFactory) transformerFactory.get()).newTransformerHandler(); 239 th.setResult(result); 240 XMLReader reader = saxParserFactory.get().newSAXParser().getXMLReader(); 241 reader.setContentHandler(th); 242 reader.setProperty(LEXICAL_HANDLER_PROPERTY, th); 243 reader.parse(toInputSource(ssrc)); 244 } else { 245 newTransformer().transform(src, result); 246 } 247 return result; 248 } 249 250 private static InputSource toInputSource(StreamSource src) { 251 InputSource is = new InputSource(); 252 is.setByteStream(src.getInputStream()); 253 is.setCharacterStream(src.getReader()); 254 is.setPublicId(src.getPublicId()); 255 is.setSystemId(src.getSystemId()); 256 return is; 257 } 258 259 /* 260 * Gets an EntityResolver using XML catalog 261 */ 262 public static EntityResolver createEntityResolver(@Nullable URL catalogUrl) { 263 // set up a manager 264 CatalogManager manager = new CatalogManager(); 265 manager.setIgnoreMissingProperties(true); 266 // Using static catalog may result in to sharing of the catalog by multiple apps running in a container 267 manager.setUseStaticCatalog(false); 268 Catalog catalog = manager.getCatalog(); 269 try { 270 if (catalogUrl != null) { 271 catalog.parseCatalog(catalogUrl); 272 } 273 } catch (IOException e) { 274 throw new ServerRtException("server.rt.err",e); 275 } 276 return workaroundCatalogResolver(catalog); 277 } 278 279 /** 280 * Gets a default EntityResolver for catalog at META-INF/jaxws-catalog.xml 281 */ 282 public static EntityResolver createDefaultCatalogResolver() { 283 284 // set up a manager 285 CatalogManager manager = new CatalogManager(); 286 manager.setIgnoreMissingProperties(true); 287 // Using static catalog may result in to sharing of the catalog by multiple apps running in a container 288 manager.setUseStaticCatalog(false); 289 // parse the catalog 290 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 291 Enumeration<URL> catalogEnum; 292 Catalog catalog = manager.getCatalog(); 293 try { 294 if (cl == null) { 295 catalogEnum = ClassLoader.getSystemResources("META-INF/jax-ws-catalog.xml"); 296 } else { 297 catalogEnum = cl.getResources("META-INF/jax-ws-catalog.xml"); 298 } 299 300 while(catalogEnum.hasMoreElements()) { 301 URL url = catalogEnum.nextElement(); 302 catalog.parseCatalog(url); 303 } 304 } catch (IOException e) { 305 throw new WebServiceException(e); 306 } 307 308 return workaroundCatalogResolver(catalog); 309 } 310 311 /** 312 * Default CatalogResolver implementation is broken as it depends on CatalogManager.getCatalog() which will always create a new one when 313 * useStaticCatalog is false. 314 * This returns a CatalogResolver that uses the catalog passed as parameter. 315 * @param catalog 316 * @return CatalogResolver 317 */ 318 private static CatalogResolver workaroundCatalogResolver(final Catalog catalog) { 319 // set up a manager 320 CatalogManager manager = new CatalogManager() { 321 @Override 322 public Catalog getCatalog() { 323 return catalog; 324 } 325 }; 326 manager.setIgnoreMissingProperties(true); 327 // Using static catalog may result in to sharing of the catalog by multiple apps running in a container 328 manager.setUseStaticCatalog(false); 329 330 return new CatalogResolver(manager); 331 } 332 333 /** 334 * {@link ErrorHandler} that always treat the error as fatal. 335 */ 336 public static final ErrorHandler DRACONIAN_ERROR_HANDLER = new ErrorHandler() { 337 public void warning(SAXParseException exception) { 338 } 339 340 public void error(SAXParseException exception) throws SAXException { 341 throw exception; 342 } 343 344 public void fatalError(SAXParseException exception) throws SAXException { 345 throw exception; 346 } 347 }; 348 }