Tue, 09 Apr 2013 14:51:13 +0100
8010393: Update JAX-WS RI to 2.2.9-b12941
Reviewed-by: alanb, erikj
Contributed-by: miroslav.kos@oracle.com, martin.grebac@oracle.com
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 */
26 package com.sun.xml.internal.ws.util.xml;
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.*;
42 import javax.xml.XMLConstants;
43 import javax.xml.namespace.QName;
44 import javax.xml.parsers.DocumentBuilderFactory;
45 import javax.xml.parsers.ParserConfigurationException;
46 import javax.xml.parsers.SAXParserFactory;
47 import javax.xml.stream.XMLInputFactory;
48 import javax.xml.transform.Result;
49 import javax.xml.transform.Source;
50 import javax.xml.transform.Transformer;
51 import javax.xml.transform.TransformerConfigurationException;
52 import javax.xml.transform.TransformerException;
53 import javax.xml.transform.TransformerFactory;
54 import javax.xml.transform.sax.SAXTransformerFactory;
55 import javax.xml.transform.sax.TransformerHandler;
56 import javax.xml.transform.stream.StreamSource;
57 import javax.xml.ws.WebServiceException;
58 import javax.xml.xpath.XPathFactory;
59 import javax.xml.xpath.XPathFactoryConfigurationException;
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 import java.util.logging.Level;
71 import java.util.logging.Logger;
73 /**
74 * @author WS Development Team
75 */
76 public class XmlUtil {
77 private final static String LEXICAL_HANDLER_PROPERTY =
78 "http://xml.org/sax/properties/lexical-handler";
80 private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName());
82 private static boolean globalSecureXmlProcessingEnabled;
84 static {
85 String disableSecureXmlProcessing = System.getProperty("disableSecureXmlProcessing");
86 globalSecureXmlProcessingEnabled = disableSecureXmlProcessing == null || !Boolean.valueOf(disableSecureXmlProcessing);
87 }
89 public static String getPrefix(String s) {
90 int i = s.indexOf(':');
91 if (i == -1)
92 return null;
93 return s.substring(0, i);
94 }
96 public static String getLocalPart(String s) {
97 int i = s.indexOf(':');
98 if (i == -1)
99 return s;
100 return s.substring(i + 1);
101 }
105 public static String getAttributeOrNull(Element e, String name) {
106 Attr a = e.getAttributeNode(name);
107 if (a == null)
108 return null;
109 return a.getValue();
110 }
112 public static String getAttributeNSOrNull(
113 Element e,
114 String name,
115 String nsURI) {
116 Attr a = e.getAttributeNodeNS(nsURI, name);
117 if (a == null)
118 return null;
119 return a.getValue();
120 }
122 public static String getAttributeNSOrNull(
123 Element e,
124 QName name) {
125 Attr a = e.getAttributeNodeNS(name.getNamespaceURI(), name.getLocalPart());
126 if (a == null)
127 return null;
128 return a.getValue();
129 }
131 /* public static boolean matchesTagNS(Element e, String tag, String nsURI) {
132 try {
133 return e.getLocalName().equals(tag)
134 && e.getNamespaceURI().equals(nsURI);
135 } catch (NullPointerException npe) {
137 // localname not null since parsing would fail before here
138 throw new WSDLParseException(
139 "null.namespace.found",
140 e.getLocalName());
141 }
142 }
144 public static boolean matchesTagNS(
145 Element e,
146 javax.xml.namespace.QName name) {
147 try {
148 return e.getLocalName().equals(name.getLocalPart())
149 && e.getNamespaceURI().equals(name.getNamespaceURI());
150 } catch (NullPointerException npe) {
152 // localname not null since parsing would fail before here
153 throw new WSDLParseException(
154 "null.namespace.found",
155 e.getLocalName());
156 }
157 }*/
159 public static Iterator getAllChildren(Element element) {
160 return new NodeListIterator(element.getChildNodes());
161 }
163 public static Iterator getAllAttributes(Element element) {
164 return new NamedNodeMapIterator(element.getAttributes());
165 }
167 public static List<String> parseTokenList(String tokenList) {
168 List<String> result = new ArrayList<String>();
169 StringTokenizer tokenizer = new StringTokenizer(tokenList, " ");
170 while (tokenizer.hasMoreTokens()) {
171 result.add(tokenizer.nextToken());
172 }
173 return result;
174 }
176 public static String getTextForNode(Node node) {
177 StringBuilder sb = new StringBuilder();
179 NodeList children = node.getChildNodes();
180 if (children.getLength() == 0)
181 return null;
183 for (int i = 0; i < children.getLength(); ++i) {
184 Node n = children.item(i);
186 if (n instanceof Text)
187 sb.append(n.getNodeValue());
188 else if (n instanceof EntityReference) {
189 String s = getTextForNode(n);
190 if (s == null)
191 return null;
192 else
193 sb.append(s);
194 } else
195 return null;
196 }
198 return sb.toString();
199 }
201 public static InputStream getUTF8Stream(String s) {
202 try {
203 ByteArrayBuffer bab = new ByteArrayBuffer();
204 Writer w = new OutputStreamWriter(bab, "utf-8");
205 w.write(s);
206 w.close();
207 return bab.newInputStream();
208 } catch (IOException e) {
209 throw new RuntimeException("should not happen");
210 }
211 }
213 static final TransformerFactory transformerFactory = newTransformerFactory();
215 static final SAXParserFactory saxParserFactory = newSAXParserFactory(true);
217 static {
218 saxParserFactory.setNamespaceAware(true);
219 }
221 /**
222 * Creates a new identity transformer.
223 */
224 public static Transformer newTransformer() {
225 try {
226 return transformerFactory.newTransformer();
227 } catch (TransformerConfigurationException tex) {
228 throw new IllegalStateException("Unable to create a JAXP transformer");
229 }
230 }
232 /**
233 * Performs identity transformation.
234 */
235 public static <T extends Result>
236 T identityTransform(Source src, T result) throws TransformerException, SAXException, ParserConfigurationException, IOException {
237 if (src instanceof StreamSource) {
238 // work around a bug in JAXP in JDK6u4 and earlier where the namespace processing
239 // is not turned on by default
240 StreamSource ssrc = (StreamSource) src;
241 TransformerHandler th = ((SAXTransformerFactory) transformerFactory).newTransformerHandler();
242 th.setResult(result);
243 XMLReader reader = saxParserFactory.newSAXParser().getXMLReader();
244 reader.setContentHandler(th);
245 reader.setProperty(LEXICAL_HANDLER_PROPERTY, th);
246 reader.parse(toInputSource(ssrc));
247 } else {
248 newTransformer().transform(src, result);
249 }
250 return result;
251 }
253 private static InputSource toInputSource(StreamSource src) {
254 InputSource is = new InputSource();
255 is.setByteStream(src.getInputStream());
256 is.setCharacterStream(src.getReader());
257 is.setPublicId(src.getPublicId());
258 is.setSystemId(src.getSystemId());
259 return is;
260 }
262 /*
263 * Gets an EntityResolver using XML catalog
264 */
265 public static EntityResolver createEntityResolver(@Nullable URL catalogUrl) {
266 // set up a manager
267 CatalogManager manager = new CatalogManager();
268 manager.setIgnoreMissingProperties(true);
269 // Using static catalog may result in to sharing of the catalog by multiple apps running in a container
270 manager.setUseStaticCatalog(false);
271 Catalog catalog = manager.getCatalog();
272 try {
273 if (catalogUrl != null) {
274 catalog.parseCatalog(catalogUrl);
275 }
276 } catch (IOException e) {
277 throw new ServerRtException("server.rt.err",e);
278 }
279 return workaroundCatalogResolver(catalog);
280 }
282 /**
283 * Gets a default EntityResolver for catalog at META-INF/jaxws-catalog.xml
284 */
285 public static EntityResolver createDefaultCatalogResolver() {
287 // set up a manager
288 CatalogManager manager = new CatalogManager();
289 manager.setIgnoreMissingProperties(true);
290 // Using static catalog may result in to sharing of the catalog by multiple apps running in a container
291 manager.setUseStaticCatalog(false);
292 // parse the catalog
293 ClassLoader cl = Thread.currentThread().getContextClassLoader();
294 Enumeration<URL> catalogEnum;
295 Catalog catalog = manager.getCatalog();
296 try {
297 if (cl == null) {
298 catalogEnum = ClassLoader.getSystemResources("META-INF/jax-ws-catalog.xml");
299 } else {
300 catalogEnum = cl.getResources("META-INF/jax-ws-catalog.xml");
301 }
303 while(catalogEnum.hasMoreElements()) {
304 URL url = catalogEnum.nextElement();
305 catalog.parseCatalog(url);
306 }
307 } catch (IOException e) {
308 throw new WebServiceException(e);
309 }
311 return workaroundCatalogResolver(catalog);
312 }
314 /**
315 * Default CatalogResolver implementation is broken as it depends on CatalogManager.getCatalog() which will always create a new one when
316 * useStaticCatalog is false.
317 * This returns a CatalogResolver that uses the catalog passed as parameter.
318 * @param catalog
319 * @return CatalogResolver
320 */
321 private static CatalogResolver workaroundCatalogResolver(final Catalog catalog) {
322 // set up a manager
323 CatalogManager manager = new CatalogManager() {
324 @Override
325 public Catalog getCatalog() {
326 return catalog;
327 }
328 };
329 manager.setIgnoreMissingProperties(true);
330 // Using static catalog may result in to sharing of the catalog by multiple apps running in a container
331 manager.setUseStaticCatalog(false);
333 return new CatalogResolver(manager);
334 }
336 /**
337 * {@link ErrorHandler} that always treat the error as fatal.
338 */
339 public static final ErrorHandler DRACONIAN_ERROR_HANDLER = new ErrorHandler() {
340 @Override
341 public void warning(SAXParseException exception) {
342 }
344 @Override
345 public void error(SAXParseException exception) throws SAXException {
346 throw exception;
347 }
349 @Override
350 public void fatalError(SAXParseException exception) throws SAXException {
351 throw exception;
352 }
353 };
355 public static DocumentBuilderFactory newDocumentBuilderFactory() {
356 return newDocumentBuilderFactory(true);
357 }
359 public static DocumentBuilderFactory newDocumentBuilderFactory(boolean secureXmlProcessing) {
360 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
361 try {
362 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, checkGlobalOverride(secureXmlProcessing));
363 } catch (ParserConfigurationException e) {
364 LOGGER.log(Level.WARNING, "Factory [{}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } );
365 }
366 return factory;
367 }
369 public static TransformerFactory newTransformerFactory(boolean secureXmlProcessingEnabled) {
370 TransformerFactory factory = TransformerFactory.newInstance();
371 try {
372 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, checkGlobalOverride(secureXmlProcessingEnabled));
373 } catch (TransformerConfigurationException e) {
374 LOGGER.log(Level.WARNING, "Factory [{}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()});
375 }
376 return factory;
377 }
379 public static TransformerFactory newTransformerFactory() {
380 return newTransformerFactory(true);
381 }
383 public static SAXParserFactory newSAXParserFactory(boolean secureXmlProcessingEnabled) {
384 SAXParserFactory factory = SAXParserFactory.newInstance();
385 try {
386 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, checkGlobalOverride(secureXmlProcessingEnabled));
387 } catch (Exception e) {
388 LOGGER.log(Level.WARNING, "Factory [{}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()});
389 }
390 return factory;
391 }
393 public static XPathFactory newXPathFactory(boolean secureXmlProcessingEnabled) {
394 XPathFactory factory = XPathFactory.newInstance();
395 try {
396 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, checkGlobalOverride(secureXmlProcessingEnabled));
397 } catch (XPathFactoryConfigurationException e) {
398 LOGGER.log(Level.WARNING, "Factory [{}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } );
399 }
400 return factory;
401 }
403 public static XMLInputFactory newXMLInputFactory(boolean secureXmlProcessingEnabled) {
404 XMLInputFactory factory = XMLInputFactory.newInstance();
405 if (checkGlobalOverride(secureXmlProcessingEnabled)) {
406 // TODO-Miran: are those apppropriate defaults?
407 factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
408 factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
409 }
410 return factory;
411 }
413 private static boolean checkGlobalOverride(boolean localSecureXmlProcessingEnabled) {
414 return globalSecureXmlProcessingEnabled && localSecureXmlProcessingEnabled;
415 }
417 }