org.apache.activemq.artemis.utils.XmlProvider Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.utils;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import java.util.Map;
import org.w3c.dom.ls.LSInput;
import org.xml.sax.SAXException;
public class XmlProvider {
public static final String ARTEMIS_DISABLE_XXE_PROPERTY = "artemis.disableXxe";
public static final String XINCLUDE_AWARE_PROPERTY = "XINCLUDE_AWARE";
public static final String NAMESPACE_AWARE_PROPERTY = "NAMESPACE_AWARE";
public static final String IGNORE_COMMENTS_PROPERTY = "IGNORE_COMMENTS";
public static final String IGNORE_ELEMENT_CONTENT_WHITESPACE_PROPERTY = "IGNORE_ELEMENT_CONTENT_WHITESPACE";
private static final String ACTIVEMQ_CORE_NS = "urn:activemq:core";
private static final String ACTIVEMQ_JMS_NS = "urn:activemq:jms";
private static final String ARTEMIS_XML_SCHEMA_SID = "xml.xsd";
private static final String ARTEMIS_CONFIGURATION_SCHEMA_SID = "artemis-configuration.xsd";
private static final String ARTEMIS_JMS_SCHEMA_SID = "artemis-jms.xsd";
private static final String ARTEMIS_SCHEMA_BASE_URL = "schema/";
private static final String ARTEMIS_XML_SCHEMA_URL = ARTEMIS_SCHEMA_BASE_URL + ARTEMIS_XML_SCHEMA_SID;
private static final String ARTEMIS_CONFIGURATION_SCHEMA_URL = ARTEMIS_SCHEMA_BASE_URL + ARTEMIS_CONFIGURATION_SCHEMA_SID;
private static final String ARTEMIS_JMS_SCHEMA_URL = ARTEMIS_SCHEMA_BASE_URL + ARTEMIS_JMS_SCHEMA_SID;
private static boolean xxeEnabled = !"".equals(System.getProperty(ARTEMIS_DISABLE_XXE_PROPERTY)) &&
!Boolean.parseBoolean(System.getProperty(ARTEMIS_DISABLE_XXE_PROPERTY, Boolean.FALSE.toString()));
public static boolean isXxeEnabled() {
return xxeEnabled;
}
public static void setXxeEnabled(boolean enabled) {
xxeEnabled = enabled;
}
public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
return newDocumentBuilder(null, null);
}
public static DocumentBuilder newDocumentBuilder(Map features, Map properties) throws ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
if (features != null) {
for (Map.Entry feature : features.entrySet()) {
factory.setFeature(feature.getKey(), feature.getValue());
}
}
if (properties != null) {
for (Map.Entry property : properties.entrySet()) {
if (XINCLUDE_AWARE_PROPERTY.equals(property.getKey())) {
factory.setXIncludeAware(property.getValue());
} else if (NAMESPACE_AWARE_PROPERTY.equals(property.getKey())) {
factory.setNamespaceAware(property.getValue());
} else if (IGNORE_COMMENTS_PROPERTY.equals(property.getKey())) {
factory.setIgnoringComments(property.getValue());
} else if (IGNORE_ELEMENT_CONTENT_WHITESPACE_PROPERTY.equals(property.getKey())) {
factory.setIgnoringElementContentWhitespace(property.getValue());
} else {
throw new IllegalArgumentException("Property not supported: " + property.getKey());
}
}
}
if (!isXxeEnabled()) {
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
}
return factory.newDocumentBuilder();
}
public static XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException {
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
if (!isXxeEnabled()) {
// This disables DTDs entirely for that factory
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
// disable external entities
xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
}
return xmlInputFactory.createXMLStreamReader(inputStream);
}
public static Schema newSchema(Source schema, Map features) throws SAXException {
return newSchemaFactory(features).newSchema(schema);
}
private static SchemaFactory newSchemaFactory(Map features) throws SAXException {
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
if (features != null) {
for (Map.Entry feature : features.entrySet()) {
factory.setFeature(feature.getKey(), feature.getValue());
}
}
if (!isXxeEnabled()) {
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
factory.setResourceResolver((type, namespaceURI, publicId, systemId, baseURI) -> {
if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(type) && XMLConstants.XML_NS_URI.equals(namespaceURI) && ARTEMIS_XML_SCHEMA_SID.equals(systemId)) {
return newLSInput(publicId, systemId, baseURI, Thread.currentThread().getContextClassLoader().getResourceAsStream(ARTEMIS_XML_SCHEMA_URL));
} else if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(type) && ACTIVEMQ_CORE_NS.equals(namespaceURI) && ARTEMIS_CONFIGURATION_SCHEMA_SID.equals(systemId)) {
return newLSInput(publicId, systemId, baseURI, Thread.currentThread().getContextClassLoader().getResourceAsStream(ARTEMIS_CONFIGURATION_SCHEMA_URL));
} else if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(type) && ACTIVEMQ_JMS_NS.equals(namespaceURI) && ARTEMIS_JMS_SCHEMA_SID.equals(systemId)) {
return newLSInput(publicId, systemId, baseURI, Thread.currentThread().getContextClassLoader().getResourceAsStream(ARTEMIS_JMS_SCHEMA_URL));
}
return null;
});
}
return factory;
}
public static Transformer newTransformer() throws TransformerConfigurationException {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
if (!isXxeEnabled()) {
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
}
return transformerFactory.newTransformer();
}
public static Validator newValidator(URL schema) throws SAXException {
Validator validator = newSchemaFactory(null).newSchema(schema).newValidator();
if (!isXxeEnabled()) {
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
}
return validator;
}
private static LSInput newLSInput(String publicId, String systemId, String baseURI, InputStream byteStream) {
return new LSInput() {
@Override
public Reader getCharacterStream() {
return null;
}
@Override
public void setCharacterStream(Reader reader) {
}
@Override
public InputStream getByteStream() {
return byteStream;
}
@Override
public void setByteStream(InputStream inputStream) {
}
@Override
public String getStringData() {
return null;
}
@Override
public void setStringData(String s) {
}
@Override
public String getSystemId() {
return systemId;
}
@Override
public void setSystemId(String s) {
}
@Override
public String getPublicId() {
return publicId;
}
@Override
public void setPublicId(String s) {
}
@Override
public String getBaseURI() {
return baseURI;
}
@Override
public void setBaseURI(String s) {
}
@Override
public String getEncoding() {
return null;
}
@Override
public void setEncoding(String s) {
}
@Override
public boolean getCertifiedText() {
return false;
}
@Override
public void setCertifiedText(boolean b) {
}
};
}
}