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.xml.internal.ws.server.ServerRtException;
30 import com.sun.xml.internal.ws.util.ByteArrayBuffer;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.OutputStreamWriter;
34 import java.io.Writer;
35 import java.lang.reflect.Method;
36 import java.net.URI;
37 import java.net.URL;
38 import java.security.AccessController;
39 import java.security.PrivilegedAction;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.Enumeration;
43 import java.util.Iterator;
44 import java.util.List;
45 import java.util.StringTokenizer;
46 import java.util.logging.Level;
47 import java.util.logging.Logger;
48 import java.util.stream.Collectors;
49 import javax.xml.XMLConstants;
50 import javax.xml.catalog.CatalogFeatures;
51 import javax.xml.catalog.CatalogFeatures.Feature;
52 import javax.xml.catalog.CatalogManager;
53 import javax.xml.namespace.QName;
54 import javax.xml.parsers.DocumentBuilderFactory;
55 import javax.xml.parsers.ParserConfigurationException;
56 import javax.xml.parsers.SAXParserFactory;
57 import javax.xml.stream.XMLInputFactory;
58 import javax.xml.transform.Result;
59 import javax.xml.transform.Source;
60 import javax.xml.transform.Transformer;
61 import javax.xml.transform.TransformerConfigurationException;
62 import javax.xml.transform.TransformerException;
63 import javax.xml.transform.TransformerFactory;
64 import javax.xml.transform.sax.SAXTransformerFactory;
65 import javax.xml.transform.sax.TransformerHandler;
66 import javax.xml.transform.stream.StreamSource;
67 import javax.xml.validation.SchemaFactory;
68 import javax.xml.ws.WebServiceException;
69 import javax.xml.xpath.XPathFactory;
70 import javax.xml.xpath.XPathFactoryConfigurationException;
71 import org.w3c.dom.Attr;
72 import org.w3c.dom.Element;
73 import org.w3c.dom.EntityReference;
74 import org.w3c.dom.Node;
75 import org.w3c.dom.NodeList;
76 import org.w3c.dom.Text;
77 import org.xml.sax.EntityResolver;
78 import org.xml.sax.ErrorHandler;
79 import org.xml.sax.InputSource;
80 import org.xml.sax.SAXException;
81 import org.xml.sax.SAXParseException;
82 import org.xml.sax.XMLReader;
83
84 /**
85 * @author WS Development Team
86 */
87 public class XmlUtil {
88
89 // not in older JDK, so must be duplicated here, otherwise javax.xml.XMLConstants should be used
90 private static final String ACCESS_EXTERNAL_SCHEMA = "http://javax.xml.XMLConstants/property/accessExternalSchema";
91
92 private final static String LEXICAL_HANDLER_PROPERTY =
93 "http://xml.org/sax/properties/lexical-handler";
94
95 private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName());
96
97 private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.ws.disableXmlSecurity";
98
99 private static boolean XML_SECURITY_DISABLED = AccessController.doPrivileged(
100 new PrivilegedAction<Boolean>() {
167 return e.getLocalName().equals(name.getLocalPart())
168 && e.getNamespaceURI().equals(name.getNamespaceURI());
169 } catch (NullPointerException npe) {
170
171 // localname not null since parsing would fail before here
172 throw new WSDLParseException(
173 "null.namespace.found",
174 e.getLocalName());
175 }
176 }*/
177
178 public static Iterator getAllChildren(Element element) {
179 return new NodeListIterator(element.getChildNodes());
180 }
181
182 public static Iterator getAllAttributes(Element element) {
183 return new NamedNodeMapIterator(element.getAttributes());
184 }
185
186 public static List<String> parseTokenList(String tokenList) {
187 List<String> result = new ArrayList<String>();
188 StringTokenizer tokenizer = new StringTokenizer(tokenList, " ");
189 while (tokenizer.hasMoreTokens()) {
190 result.add(tokenizer.nextToken());
191 }
192 return result;
193 }
194
195 public static String getTextForNode(Node node) {
196 StringBuilder sb = new StringBuilder();
197
198 NodeList children = node.getChildNodes();
199 if (children.getLength() == 0)
200 return null;
201
202 for (int i = 0; i < children.getLength(); ++i) {
203 Node n = children.item(i);
204
205 if (n instanceof Text)
206 sb.append(n.getNodeValue());
207 else if (n instanceof EntityReference) {
230 }
231
232 static final ContextClassloaderLocal<TransformerFactory> transformerFactory = new ContextClassloaderLocal<TransformerFactory>() {
233 @Override
234 protected TransformerFactory initialValue() throws Exception {
235 return TransformerFactory.newInstance();
236 }
237 };
238
239 static final ContextClassloaderLocal<SAXParserFactory> saxParserFactory = new ContextClassloaderLocal<SAXParserFactory>() {
240 @Override
241 protected SAXParserFactory initialValue() throws Exception {
242 SAXParserFactory factory = newSAXParserFactory(true);
243 factory.setNamespaceAware(true);
244 return factory;
245 }
246 };
247
248 /**
249 * Creates a new identity transformer.
250 */
251 public static Transformer newTransformer() {
252 try {
253 return transformerFactory.get().newTransformer();
254 } catch (TransformerConfigurationException tex) {
255 throw new IllegalStateException("Unable to create a JAXP transformer");
256 }
257 }
258
259 /**
260 * Performs identity transformation.
261 */
262 public static <T extends Result>
263 T identityTransform(Source src, T result) throws TransformerException, SAXException, ParserConfigurationException, IOException {
264 if (src instanceof StreamSource) {
265 // work around a bug in JAXP in JDK6u4 and earlier where the namespace processing
266 // is not turned on by default
267 StreamSource ssrc = (StreamSource) src;
268 TransformerHandler th = ((SAXTransformerFactory) transformerFactory.get()).newTransformerHandler();
269 th.setResult(result);
270 XMLReader reader = saxParserFactory.get().newSAXParser().getXMLReader();
271 reader.setContentHandler(th);
272 reader.setProperty(LEXICAL_HANDLER_PROPERTY, th);
273 reader.parse(toInputSource(ssrc));
274 } else {
275 newTransformer().transform(src, result);
276 }
277 return result;
278 }
279
280 private static InputSource toInputSource(StreamSource src) {
281 InputSource is = new InputSource();
282 is.setByteStream(src.getInputStream());
283 is.setCharacterStream(src.getReader());
284 is.setPublicId(src.getPublicId());
285 is.setSystemId(src.getSystemId());
286 return is;
287 }
288
289 /*
290 * Gets an EntityResolver using XML catalog
291 */
292 public static EntityResolver createEntityResolver(@Nullable URL catalogUrl) {
293 ArrayList<URL> urlsArray = new ArrayList<URL>();
294 EntityResolver er;
295 if (catalogUrl != null) {
296 urlsArray.add(catalogUrl);
297 }
298 try {
299 er = createCatalogResolver(urlsArray);
300 } catch (Exception e) {
301 throw new ServerRtException("server.rt.err",e);
302 }
303 return er;
304 }
305
306 /**
307 * Gets a default EntityResolver for catalog at META-INF/jaxws-catalog.xml
308 */
309 public static EntityResolver createDefaultCatalogResolver() {
310 EntityResolver er;
311 try {
312 /**
313 * Gets a URLs for catalog defined at META-INF/jaxws-catalog.xml
314 */
315 ClassLoader cl = Thread.currentThread().getContextClassLoader();
316 Enumeration<URL> catalogEnum;
317 if (cl == null) {
318 catalogEnum = ClassLoader.getSystemResources("META-INF/jax-ws-catalog.xml");
319 } else {
320 catalogEnum = cl.getResources("META-INF/jax-ws-catalog.xml");
321 }
322 er = createCatalogResolver(Collections.list(catalogEnum));
323 } catch (Exception e) {
324 throw new WebServiceException(e);
325 }
326
327 return er;
328 }
329
330 /**
331 * Instantiate catalog resolver using new catalog API (javax.xml.catalog.*)
332 * added in JDK9. Usage of new API removes dependency on internal API
333 * (com.sun.org.apache.xml.internal) for modular runtime.
334 */
335 private static EntityResolver createCatalogResolver(ArrayList<URL> urls) throws Exception {
336 // Prepare array of catalog URIs
337 URI[] uris = urls.stream()
338 .map(u -> URI.create(u.toExternalForm()))
339 .toArray(URI[]::new);
340
341 //Create CatalogResolver with new JDK9+ API
342 return (EntityResolver) CatalogManager.catalogResolver(catalogFeatures, uris);
343 }
344
345 // Cache CatalogFeatures instance for future usages.
346 // Resolve feature is set to "continue" value for backward compatibility.
347 private static CatalogFeatures catalogFeatures = CatalogFeatures.builder()
348 .with(Feature.RESOLVE, "continue")
349 .build();
350
351 /**
352 * {@link ErrorHandler} that always treat the error as fatal.
353 */
354 public static final ErrorHandler DRACONIAN_ERROR_HANDLER = new ErrorHandler() {
355 @Override
356 public void warning(SAXParseException exception) {
357 }
358
359 @Override
360 public void error(SAXParseException exception) throws SAXException {
361 throw exception;
362 }
363
364 @Override
365 public void fatalError(SAXParseException exception) throws SAXException {
366 throw exception;
367 }
368 };
369
374 } catch (ParserConfigurationException e) {
375 LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } );
376 }
377 return factory;
378 }
379
380 public static TransformerFactory newTransformerFactory(boolean disableSecurity) {
381 TransformerFactory factory = TransformerFactory.newInstance();
382 try {
383 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity));
384 } catch (TransformerConfigurationException e) {
385 LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()});
386 }
387 return factory;
388 }
389
390 public static SAXParserFactory newSAXParserFactory(boolean disableSecurity) {
391 SAXParserFactory factory = SAXParserFactory.newInstance();
392 try {
393 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity));
394 } catch (Exception e) {
395 LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()});
396 }
397 return factory;
398 }
399
400 public static XPathFactory newXPathFactory(boolean disableSecurity) {
401 XPathFactory factory = XPathFactory.newInstance();
402 try {
403 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity));
404 } catch (XPathFactoryConfigurationException e) {
405 LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } );
406 }
407 return factory;
408 }
409
410 public static XMLInputFactory newXMLInputFactory(boolean disableSecurity) {
411 XMLInputFactory factory = XMLInputFactory.newInstance();
412 if (xmlSecurityDisabled(disableSecurity)) {
413 // TODO-Miran: are those apppropriate defaults?
414 factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
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.xml.internal.ws.util.ByteArrayBuffer;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStreamWriter;
33 import java.io.Writer;
34 import java.net.URL;
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37 import java.util.ArrayList;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.StringTokenizer;
41 import java.util.logging.Level;
42 import java.util.logging.Logger;
43 import javax.xml.XMLConstants;
44 import javax.xml.namespace.QName;
45 import javax.xml.parsers.DocumentBuilderFactory;
46 import javax.xml.parsers.ParserConfigurationException;
47 import javax.xml.parsers.SAXParserFactory;
48 import javax.xml.stream.XMLInputFactory;
49 import javax.xml.transform.Result;
50 import javax.xml.transform.Source;
51 import javax.xml.transform.Transformer;
52 import javax.xml.transform.TransformerConfigurationException;
53 import javax.xml.transform.TransformerException;
54 import javax.xml.transform.TransformerFactory;
55 import javax.xml.transform.sax.SAXTransformerFactory;
56 import javax.xml.transform.sax.TransformerHandler;
57 import javax.xml.transform.stream.StreamSource;
58 import javax.xml.validation.SchemaFactory;
59 import javax.xml.xpath.XPathFactory;
60 import javax.xml.xpath.XPathFactoryConfigurationException;
61 import org.w3c.dom.Attr;
62 import org.w3c.dom.Element;
63 import org.w3c.dom.EntityReference;
64 import org.w3c.dom.Node;
65 import org.w3c.dom.NodeList;
66 import org.w3c.dom.Text;
67 import org.xml.sax.EntityResolver;
68 import org.xml.sax.ErrorHandler;
69 import org.xml.sax.InputSource;
70 import org.xml.sax.SAXException;
71 import org.xml.sax.SAXNotRecognizedException;
72 import org.xml.sax.SAXNotSupportedException;
73 import org.xml.sax.SAXParseException;
74 import org.xml.sax.XMLReader;
75
76 /**
77 * @author WS Development Team
78 */
79 public class XmlUtil {
80
81 // not in older JDK, so must be duplicated here, otherwise javax.xml.XMLConstants should be used
82 private static final String ACCESS_EXTERNAL_SCHEMA = "http://javax.xml.XMLConstants/property/accessExternalSchema";
83
84 private final static String LEXICAL_HANDLER_PROPERTY =
85 "http://xml.org/sax/properties/lexical-handler";
86
87 private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName());
88
89 private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.ws.disableXmlSecurity";
90
91 private static boolean XML_SECURITY_DISABLED = AccessController.doPrivileged(
92 new PrivilegedAction<Boolean>() {
159 return e.getLocalName().equals(name.getLocalPart())
160 && e.getNamespaceURI().equals(name.getNamespaceURI());
161 } catch (NullPointerException npe) {
162
163 // localname not null since parsing would fail before here
164 throw new WSDLParseException(
165 "null.namespace.found",
166 e.getLocalName());
167 }
168 }*/
169
170 public static Iterator getAllChildren(Element element) {
171 return new NodeListIterator(element.getChildNodes());
172 }
173
174 public static Iterator getAllAttributes(Element element) {
175 return new NamedNodeMapIterator(element.getAttributes());
176 }
177
178 public static List<String> parseTokenList(String tokenList) {
179 List<String> result = new ArrayList<>();
180 StringTokenizer tokenizer = new StringTokenizer(tokenList, " ");
181 while (tokenizer.hasMoreTokens()) {
182 result.add(tokenizer.nextToken());
183 }
184 return result;
185 }
186
187 public static String getTextForNode(Node node) {
188 StringBuilder sb = new StringBuilder();
189
190 NodeList children = node.getChildNodes();
191 if (children.getLength() == 0)
192 return null;
193
194 for (int i = 0; i < children.getLength(); ++i) {
195 Node n = children.item(i);
196
197 if (n instanceof Text)
198 sb.append(n.getNodeValue());
199 else if (n instanceof EntityReference) {
222 }
223
224 static final ContextClassloaderLocal<TransformerFactory> transformerFactory = new ContextClassloaderLocal<TransformerFactory>() {
225 @Override
226 protected TransformerFactory initialValue() throws Exception {
227 return TransformerFactory.newInstance();
228 }
229 };
230
231 static final ContextClassloaderLocal<SAXParserFactory> saxParserFactory = new ContextClassloaderLocal<SAXParserFactory>() {
232 @Override
233 protected SAXParserFactory initialValue() throws Exception {
234 SAXParserFactory factory = newSAXParserFactory(true);
235 factory.setNamespaceAware(true);
236 return factory;
237 }
238 };
239
240 /**
241 * Creates a new identity transformer.
242 * @return
243 */
244 public static Transformer newTransformer() {
245 try {
246 return transformerFactory.get().newTransformer();
247 } catch (TransformerConfigurationException tex) {
248 throw new IllegalStateException("Unable to create a JAXP transformer");
249 }
250 }
251
252 /**
253 * Performs identity transformation.
254 * @param <T>
255 * @param src
256 * @param result
257 * @return
258 * @throws javax.xml.transform.TransformerException
259 * @throws java.io.IOException
260 * @throws org.xml.sax.SAXException
261 * @throws javax.xml.parsers.ParserConfigurationException
262 */
263 public static <T extends Result> T identityTransform(Source src, T result)
264 throws TransformerException, SAXException, ParserConfigurationException, IOException {
265 if (src instanceof StreamSource) {
266 // work around a bug in JAXP in JDK6u4 and earlier where the namespace processing
267 // is not turned on by default
268 StreamSource ssrc = (StreamSource) src;
269 TransformerHandler th = ((SAXTransformerFactory) transformerFactory.get()).newTransformerHandler();
270 th.setResult(result);
271 XMLReader reader = saxParserFactory.get().newSAXParser().getXMLReader();
272 reader.setContentHandler(th);
273 reader.setProperty(LEXICAL_HANDLER_PROPERTY, th);
274 reader.parse(toInputSource(ssrc));
275 } else {
276 newTransformer().transform(src, result);
277 }
278 return result;
279 }
280
281 private static InputSource toInputSource(StreamSource src) {
282 InputSource is = new InputSource();
283 is.setByteStream(src.getInputStream());
284 is.setCharacterStream(src.getReader());
285 is.setPublicId(src.getPublicId());
286 is.setSystemId(src.getSystemId());
287 return is;
288 }
289
290 /**
291 * Gets an EntityResolver using XML catalog
292 *
293 * @param catalogUrl
294 * @return
295 */
296 public static EntityResolver createEntityResolver(@Nullable URL catalogUrl) {
297 return XmlCatalogUtil.createEntityResolver(catalogUrl);
298 }
299
300 /**
301 * Gets a default EntityResolver for catalog at META-INF/jaxws-catalog.xml
302 *
303 * @return
304 */
305 public static EntityResolver createDefaultCatalogResolver() {
306 return XmlCatalogUtil.createDefaultCatalogResolver();
307 }
308
309 /**
310 * {@link ErrorHandler} that always treat the error as fatal.
311 */
312 public static final ErrorHandler DRACONIAN_ERROR_HANDLER = new ErrorHandler() {
313 @Override
314 public void warning(SAXParseException exception) {
315 }
316
317 @Override
318 public void error(SAXParseException exception) throws SAXException {
319 throw exception;
320 }
321
322 @Override
323 public void fatalError(SAXParseException exception) throws SAXException {
324 throw exception;
325 }
326 };
327
332 } catch (ParserConfigurationException e) {
333 LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } );
334 }
335 return factory;
336 }
337
338 public static TransformerFactory newTransformerFactory(boolean disableSecurity) {
339 TransformerFactory factory = TransformerFactory.newInstance();
340 try {
341 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity));
342 } catch (TransformerConfigurationException e) {
343 LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()});
344 }
345 return factory;
346 }
347
348 public static SAXParserFactory newSAXParserFactory(boolean disableSecurity) {
349 SAXParserFactory factory = SAXParserFactory.newInstance();
350 try {
351 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity));
352 } catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
353 LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()});
354 }
355 return factory;
356 }
357
358 public static XPathFactory newXPathFactory(boolean disableSecurity) {
359 XPathFactory factory = XPathFactory.newInstance();
360 try {
361 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity));
362 } catch (XPathFactoryConfigurationException e) {
363 LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } );
364 }
365 return factory;
366 }
367
368 public static XMLInputFactory newXMLInputFactory(boolean disableSecurity) {
369 XMLInputFactory factory = XMLInputFactory.newInstance();
370 if (xmlSecurityDisabled(disableSecurity)) {
371 // TODO-Miran: are those apppropriate defaults?
372 factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|