alanb@368: /* mkos@397: * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. alanb@368: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. alanb@368: * alanb@368: * This code is free software; you can redistribute it and/or modify it alanb@368: * under the terms of the GNU General Public License version 2 only, as alanb@368: * published by the Free Software Foundation. Oracle designates this alanb@368: * particular file as subject to the "Classpath" exception as provided alanb@368: * by Oracle in the LICENSE file that accompanied this code. alanb@368: * alanb@368: * This code is distributed in the hope that it will be useful, but WITHOUT alanb@368: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or alanb@368: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License alanb@368: * version 2 for more details (a copy is included in the LICENSE file that alanb@368: * accompanied this code). alanb@368: * alanb@368: * You should have received a copy of the GNU General Public License version alanb@368: * 2 along with this work; if not, write to the Free Software Foundation, alanb@368: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. alanb@368: * alanb@368: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA alanb@368: * or visit www.oracle.com if you need additional information or have any alanb@368: * questions. alanb@368: */ alanb@368: alanb@368: package com.sun.xml.internal.bind.v2.util; alanb@368: alanb@368: import com.sun.xml.internal.bind.Util; alanb@368: import com.sun.xml.internal.bind.v2.Messages; alanb@368: import java.util.logging.Level; alanb@368: import java.util.logging.Logger; alanb@368: import javax.xml.XMLConstants; alanb@368: import javax.xml.parsers.DocumentBuilderFactory; alanb@368: import javax.xml.parsers.ParserConfigurationException; alanb@368: import javax.xml.parsers.SAXParserFactory; alanb@368: import javax.xml.transform.TransformerConfigurationException; alanb@368: import javax.xml.transform.TransformerFactory; alanb@368: import javax.xml.validation.SchemaFactory; alanb@368: import javax.xml.xpath.XPathFactory; alanb@368: import javax.xml.xpath.XPathFactoryConfigurationException; mkos@397: mkos@397: import org.xml.sax.SAXException; alanb@368: import org.xml.sax.SAXNotRecognizedException; alanb@368: import org.xml.sax.SAXNotSupportedException; alanb@368: alanb@368: /** alanb@368: * Provides helper methods for creating properly configured XML parser alanb@368: * factory instances with namespace support turned on and configured for alanb@368: * security. alanb@368: * @author snajper alanb@368: */ alanb@368: public class XmlFactory { alanb@368: mkos@397: // not in older JDK, so must be duplicated here, otherwise javax.xml.XMLConstants should be used mkos@397: public static final String ACCESS_EXTERNAL_SCHEMA = "http://javax.xml.XMLConstants/property/accessExternalSchema"; mkos@397: alanb@368: private static final Logger LOGGER = Logger.getLogger(XmlFactory.class.getName()); alanb@368: alanb@368: /** alanb@368: * If true XML security features when parsing XML documents will be disabled. alanb@368: * The default value is false. alanb@368: * alanb@368: * Boolean alanb@368: * @since 2.2.6 alanb@368: */ alanb@368: private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.bind.disableXmlSecurity"; alanb@368: alanb@368: public static final boolean DISABLE_SECURE_PROCESSING = alanb@368: Boolean.parseBoolean(Util.getSystemProperty(DISABLE_XML_SECURITY)); alanb@368: alanb@368: private static boolean xmlFeatureValue(boolean runtimeSetting) { alanb@368: return !(DISABLE_SECURE_PROCESSING || runtimeSetting); alanb@368: } alanb@368: alanb@368: /** alanb@368: * Returns properly configured (e.g. security features) schema factory alanb@368: * - namespaceAware == true alanb@368: * - securityProcessing == is set based on security processing property, default is true alanb@368: */ alanb@368: public static SchemaFactory createSchemaFactory(final String language, boolean disableSecureProcessing) throws IllegalStateException { alanb@368: try { alanb@368: SchemaFactory factory = SchemaFactory.newInstance(language); alanb@368: if (LOGGER.isLoggable(Level.FINE)) { alanb@368: LOGGER.log(Level.FINE, "SchemaFactory instance: {0}", factory); alanb@368: } alanb@368: factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, xmlFeatureValue(disableSecureProcessing)); alanb@368: return factory; alanb@368: } catch (SAXNotRecognizedException ex) { alanb@368: LOGGER.log(Level.SEVERE, null, ex); alanb@368: throw new IllegalStateException(ex); alanb@368: } catch (SAXNotSupportedException ex) { alanb@368: LOGGER.log(Level.SEVERE, null, ex); alanb@368: throw new IllegalStateException(ex); alanb@368: } catch (AbstractMethodError er) { alanb@368: LOGGER.log(Level.SEVERE, null, er); alanb@368: throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er); alanb@368: } alanb@368: } alanb@368: alanb@368: /** alanb@368: * Returns properly configured (e.g. security features) parser factory alanb@368: * - namespaceAware == true alanb@368: * - securityProcessing == is set based on security processing property, default is true alanb@368: */ alanb@368: public static SAXParserFactory createParserFactory(boolean disableSecureProcessing) throws IllegalStateException { alanb@368: try { alanb@368: SAXParserFactory factory = SAXParserFactory.newInstance(); alanb@368: if (LOGGER.isLoggable(Level.FINE)) { alanb@368: LOGGER.log(Level.FINE, "SAXParserFactory instance: {0}", factory); alanb@368: } alanb@368: factory.setNamespaceAware(true); alanb@368: factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, xmlFeatureValue(disableSecureProcessing)); alanb@368: return factory; alanb@368: } catch (ParserConfigurationException ex) { alanb@368: LOGGER.log(Level.SEVERE, null, ex); alanb@368: throw new IllegalStateException( ex); alanb@368: } catch (SAXNotRecognizedException ex) { alanb@368: LOGGER.log(Level.SEVERE, null, ex); alanb@368: throw new IllegalStateException( ex); alanb@368: } catch (SAXNotSupportedException ex) { alanb@368: LOGGER.log(Level.SEVERE, null, ex); alanb@368: throw new IllegalStateException( ex); alanb@368: } catch (AbstractMethodError er) { alanb@368: LOGGER.log(Level.SEVERE, null, er); alanb@368: throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er); alanb@368: } alanb@368: } alanb@368: alanb@368: /** alanb@368: * Returns properly configured (e.g. security features) factory alanb@368: * - securityProcessing == is set based on security processing property, default is true alanb@368: */ alanb@368: public static XPathFactory createXPathFactory(boolean disableSecureProcessing) throws IllegalStateException { alanb@368: try { alanb@368: XPathFactory factory = XPathFactory.newInstance(); alanb@368: if (LOGGER.isLoggable(Level.FINE)) { alanb@368: LOGGER.log(Level.FINE, "XPathFactory instance: {0}", factory); alanb@368: } alanb@368: factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, xmlFeatureValue(disableSecureProcessing)); alanb@368: return factory; alanb@368: } catch (XPathFactoryConfigurationException ex) { alanb@368: LOGGER.log(Level.SEVERE, null, ex); alanb@368: throw new IllegalStateException( ex); alanb@368: } catch (AbstractMethodError er) { alanb@368: LOGGER.log(Level.SEVERE, null, er); alanb@368: throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er); alanb@368: } alanb@368: } alanb@368: alanb@368: /** alanb@368: * Returns properly configured (e.g. security features) factory alanb@368: * - securityProcessing == is set based on security processing property, default is true alanb@368: */ alanb@368: public static TransformerFactory createTransformerFactory(boolean disableSecureProcessing) throws IllegalStateException { alanb@368: try { alanb@368: TransformerFactory factory = TransformerFactory.newInstance(); alanb@368: if (LOGGER.isLoggable(Level.FINE)) { alanb@368: LOGGER.log(Level.FINE, "TransformerFactory instance: {0}", factory); alanb@368: } alanb@368: factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, xmlFeatureValue(disableSecureProcessing)); alanb@368: return factory; alanb@368: } catch (TransformerConfigurationException ex) { alanb@368: LOGGER.log(Level.SEVERE, null, ex); alanb@368: throw new IllegalStateException( ex); alanb@368: } catch (AbstractMethodError er) { alanb@368: LOGGER.log(Level.SEVERE, null, er); alanb@368: throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er); alanb@368: } alanb@368: } alanb@368: alanb@368: /** alanb@368: * Returns properly configured (e.g. security features) factory alanb@368: * - namespaceAware == true alanb@368: * - securityProcessing == is set based on security processing property, default is true alanb@368: */ alanb@368: public static DocumentBuilderFactory createDocumentBuilderFactory(boolean disableSecureProcessing) throws IllegalStateException { alanb@368: try { alanb@368: DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); alanb@368: if (LOGGER.isLoggable(Level.FINE)) { alanb@368: LOGGER.log(Level.FINE, "DocumentBuilderFactory instance: {0}", factory); alanb@368: } alanb@368: factory.setNamespaceAware(true); alanb@368: factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, xmlFeatureValue(disableSecureProcessing)); alanb@368: return factory; alanb@368: } catch (ParserConfigurationException ex) { alanb@368: LOGGER.log(Level.SEVERE, null, ex); alanb@368: throw new IllegalStateException( ex); alanb@368: } catch (AbstractMethodError er) { alanb@368: LOGGER.log(Level.SEVERE, null, er); alanb@368: throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er); alanb@368: } alanb@368: } alanb@368: mkos@397: public static SchemaFactory allowFileAccess(SchemaFactory sf, boolean disableSecureProcessing) { mkos@397: mkos@397: // if feature secure processing enabled, nothing to do, file is allowed, mkos@397: // or user is able to control access by standard JAXP mechanisms mkos@397: if (disableSecureProcessing) { mkos@397: return sf; mkos@397: } mkos@397: mkos@397: try { mkos@397: sf.setProperty(ACCESS_EXTERNAL_SCHEMA, "file"); mkos@397: LOGGER.log(Level.FINE, Messages.JAXP_SUPPORTED_PROPERTY.format(ACCESS_EXTERNAL_SCHEMA)); mkos@397: } catch (SAXException ignored) { mkos@397: // nothing to do; support depends on version JDK or SAX implementation mkos@397: LOGGER.log(Level.CONFIG, Messages.JAXP_UNSUPPORTED_PROPERTY.format(ACCESS_EXTERNAL_SCHEMA), ignored); mkos@397: } mkos@397: return sf; mkos@397: } mkos@397: alanb@368: }