org.opensaml.xml.XMLConfigurator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xmltooling Show documentation
Show all versions of xmltooling Show documentation
XMLTooling-J is a low-level library that may be used to construct libraries that allow developers to work with XML in a Java beans manner.
The newest version!
/*
* Licensed to the University Corporation for Advanced Internet Development,
* Inc. (UCAID) under one or more contributor license agreements. See the
* NOTICE file distributed with this work for additional information regarding
* copyright ownership. The UCAID 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.opensaml.xml;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.parse.BasicParserPool;
import org.opensaml.xml.parse.XMLParserException;
import org.opensaml.xml.util.DatatypeHelper;
import org.opensaml.xml.util.XMLConstants;
import org.opensaml.xml.util.XMLHelper;
import org.opensaml.xml.validation.Validator;
import org.opensaml.xml.validation.ValidatorSuite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Reads in an XML configuration and configures the XMLTooling library accordingly.
*/
public class XMLConfigurator {
/** Class logger. */
private final Logger log = LoggerFactory.getLogger(XMLConfigurator.class);
/** Whether the XML configuration elements that configured object providers should be retained. */
private boolean retainXMLConfiguration;
/** Pool of parsers used to read and validate configurations. */
private BasicParserPool parserPool;
/** Schema used to validate configruation files. */
private Schema configurationSchema;
/**
* Constructor.
*
* @throws ConfigurationException thrown if the validation schema for configuration files can not be created
*/
public XMLConfigurator() throws ConfigurationException {
this(false);
}
/**
* Constructor.
*
* @param retainXML whether to retain the XML configuration elements within the {@link Configuration}.
*
* @throws ConfigurationException thrown if the validation schema for configuration files can not be created
*
* @deprecated this method will be removed once {@link Configuration} no longer has the option to store the XML configuration fragements
*/
public XMLConfigurator(boolean retainXML) throws ConfigurationException {
retainXMLConfiguration = retainXML;
parserPool = new BasicParserPool();
SchemaFactory factory = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source schemaSource = new StreamSource(XMLConfigurator.class
.getResourceAsStream(XMLConstants.XMLTOOLING_SCHEMA_LOCATION));
try {
configurationSchema = factory.newSchema(schemaSource);
parserPool.setIgnoreComments(true);
parserPool.setIgnoreElementContentWhitespace(true);
parserPool.setSchema(configurationSchema);
} catch (SAXException e) {
throw new ConfigurationException("Unable to read XMLTooling configuration schema", e);
}
}
/**
* Loads the configuration file(s) from the given file. If the file is a directory each file within the directory is
* loaded.
*
* @param configurationFile the configuration file(s) to be loaded
*
* @throws ConfigurationException thrown if the configuration file(s) can not be be read or invalid
*/
public void load(File configurationFile) throws ConfigurationException {
if (configurationFile == null || !configurationFile.canRead()) {
log.error("Unable to read configuration file {}", configurationFile);
}
try {
if (configurationFile.isDirectory()) {
File[] configurations = configurationFile.listFiles();
for (int i = 0; i < configurations.length; i++) {
log.debug("Parsing configuration file {}", configurations[i].getAbsolutePath());
load(new FileInputStream(configurations[i]));
}
} else {
// Given file is not a directory so try to load it directly
log.debug("Parsing configuration file {}", configurationFile.getAbsolutePath());
load(new FileInputStream(configurationFile));
}
} catch (FileNotFoundException e) {
// ignore, we already have the files
}
}
/**
* Loads a configuration file from an input stream.
*
* @param configurationStream configuration stream
*
* @throws ConfigurationException thrown if the given configuration is invalid or can not be read
*/
public void load(InputStream configurationStream) throws ConfigurationException {
try {
Document configuration = parserPool.parse(configurationStream);
load(configuration);
} catch (XMLParserException e) {
log.error("Invalid configuration file", e);
throw new ConfigurationException("Unable to create DocumentBuilder", e);
}
}
/**
* Loads the configuration docuement.
*
* @param configuration the configurationd document
* @throws ConfigurationException thrown if the configuration file(s) can not be be read or invalid
*/
public void load(Document configuration) throws ConfigurationException {
log.debug("Loading configuration from XML Document");
log.trace("{}", XMLHelper.nodeToString(configuration.getDocumentElement()));
// Schema validation
log.debug("Schema validating configuration Document");
validateConfiguration(configuration);
log.debug("Configuration document validated");
load(configuration.getDocumentElement());
}
/**
* Loads a configuration after it's been schema validated.
*
* @param configurationRoot root of the configuration
*
* @throws ConfigurationException thrown if there is a problem processing the configuration
*/
protected void load(Element configurationRoot) throws ConfigurationException {
// Initialize object providers
NodeList objectProviders = configurationRoot.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"ObjectProviders");
if (objectProviders.getLength() > 0) {
log.debug("Preparing to load ObjectProviders");
initializeObjectProviders((Element) objectProviders.item(0));
log.debug("ObjectProviders load complete");
}
// Initialize validator suites
NodeList validatorSuitesNodes = configurationRoot.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"ValidatorSuites");
if (validatorSuitesNodes.getLength() > 0) {
log.debug("Preparing to load ValidatorSuites");
initializeValidatorSuites((Element) validatorSuitesNodes.item(0));
log.debug("ValidatorSuites load complete");
}
// Initialize ID attributes
NodeList idAttributesNodes = configurationRoot.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"IDAttributes");
if (idAttributesNodes.getLength() > 0) {
log.debug("Preparing to load IDAttributes");
initializeIDAttributes((Element) idAttributesNodes.item(0));
log.debug("IDAttributes load complete");
}
}
/**
* Intializes the object providers defined in the configuration file.
*
* @param objectProviders the configuration for the various object providers
*
* @throws ConfigurationException thrown if the configuration elements are invalid
*/
protected void initializeObjectProviders(Element objectProviders) throws ConfigurationException {
// Process ObjectProvider child elements
Element objectProvider;
Attr qNameAttrib;
QName objectProviderName;
Element configuration;
XMLObjectBuilder builder;
Marshaller marshaller;
Unmarshaller unmarshaller;
NodeList providerList = objectProviders.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"ObjectProvider");
for (int i = 0; i < providerList.getLength(); i++) {
objectProvider = (Element) providerList.item(i);
// Get the element name of type this object provider is for
qNameAttrib = objectProvider.getAttributeNodeNS(null, "qualifiedName");
objectProviderName = XMLHelper.getAttributeValueAsQName(qNameAttrib);
log.debug("Initializing object provider {}", objectProviderName);
try {
configuration = (Element) objectProvider.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"BuilderClass").item(0);
builder = (XMLObjectBuilder) createClassInstance(configuration);
configuration = (Element) objectProvider.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"MarshallingClass").item(0);
marshaller = (Marshaller) createClassInstance(configuration);
configuration = (Element) objectProvider.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"UnmarshallingClass").item(0);
unmarshaller = (Unmarshaller) createClassInstance(configuration);
if(retainXMLConfiguration){
Configuration.registerObjectProvider(objectProviderName, builder, marshaller, unmarshaller,
objectProvider);
}else{
Configuration.registerObjectProvider(objectProviderName, builder, marshaller, unmarshaller);
}
log.debug("{} intialized and configuration cached", objectProviderName);
} catch (ConfigurationException e) {
log.error("Error initializing object provier " + objectProvider, e);
// clean up any parts of the object provider that might have been registered before the failure
Configuration.deregisterObjectProvider(objectProviderName);
throw e;
}
}
}
/**
* Initializes the validator suites specified in the configuration file.
*
* @param validatorSuitesElement the ValidatorSuites element from the configuration file
*
* @throws ConfigurationException thrown if there is a problem initializing the validator suites, usually because of
* malformed elements
*/
protected void initializeValidatorSuites(Element validatorSuitesElement) throws ConfigurationException {
ValidatorSuite validatorSuite;
Validator validator;
Element validatorSuiteElement;
String validatorSuiteId;
Element validatorElement;
QName validatorQName;
NodeList validatorSuiteList = validatorSuitesElement.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"ValidatorSuite");
for (int i = 0; i < validatorSuiteList.getLength(); i++) {
validatorSuiteElement = (Element) validatorSuiteList.item(i);
validatorSuiteId = validatorSuiteElement.getAttributeNS(null, "id");
validatorSuite = new ValidatorSuite(validatorSuiteId);
log.debug("Initializing ValidatorSuite {}", validatorSuiteId);
log.trace(XMLHelper.nodeToString(validatorSuiteElement));
NodeList validatorList = validatorSuiteElement.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"Validator");
for (int j = 0; j < validatorList.getLength(); j++) {
validatorElement = (Element) validatorList.item(j);
validatorQName = XMLHelper.getAttributeValueAsQName(validatorElement.getAttributeNodeNS(null,
"qualifiedName"));
validator = (Validator) createClassInstance(validatorElement);
validatorSuite.registerValidator(validatorQName, validator);
}
log.debug("ValidtorSuite {} has been initialized", validatorSuiteId);
if(retainXMLConfiguration){
Configuration.registerValidatorSuite(validatorSuiteId, validatorSuite, validatorSuiteElement);
}else{
Configuration.registerValidatorSuite(validatorSuiteId, validatorSuite);
}
}
}
/**
* Registers the global ID attributes specified in the configuration file.
*
* @param idAttributesElement the IDAttributes element from the configuration file
*
* @throws ConfigurationException thrown if there is a problem with a parsing or registering the the ID attribute
*/
protected void initializeIDAttributes(Element idAttributesElement) throws ConfigurationException {
Element idAttributeElement;
QName attributeQName;
NodeList idAttributeList = idAttributesElement.getElementsByTagNameNS(XMLConstants.XMLTOOLING_CONFIG_NS,
"IDAttribute");
for (int i = 0; i < idAttributeList.getLength(); i++) {
idAttributeElement = (Element) idAttributeList.item(i);
attributeQName = XMLHelper.getElementContentAsQName(idAttributeElement);
if (attributeQName == null) {
log.debug("IDAttribute element was empty, no registration performed");
} else {
Configuration.registerIDAttribute(attributeQName);
log.debug("IDAttribute {} has been registered", attributeQName);
}
}
}
/**
* Constructs an instance of the given class.
*
* @param configuration the current configuration element
*
* @return an instance of the given class
*
* @throws ConfigurationException thrown if the class can not be instaniated
*/
protected Object createClassInstance(Element configuration) throws ConfigurationException {
String className = configuration.getAttributeNS(null, "className");
className = DatatypeHelper.safeTrimOrNullString(className);
if (className == null) {
return null;
}
try {
log.trace("Creating instance of {}", className);
ClassLoader classLoader = this.getClass().getClassLoader();
if (classLoader == null) {
classLoader = ClassLoader.getSystemClassLoader();
}
Class clazz = classLoader.loadClass(className);
Constructor constructor = clazz.getConstructor();
return constructor.newInstance();
} catch (Exception e) {
log.error("Can not create instance of " + className, e);
throw new ConfigurationException("Can not create instance of " + className, e);
}
}
/**
* Schema validates the given configuration.
*
* @param configuration the configuration to validate
*
* @throws ConfigurationException thrown if the configuration is not schema-valid
*/
protected void validateConfiguration(Document configuration) throws ConfigurationException {
try {
javax.xml.validation.Validator schemaValidator = configurationSchema.newValidator();
schemaValidator.validate(new DOMSource(configuration));
} catch (IOException e) {
// Should never get here as the DOM is already in memory
String errorMsg = "Unable to read configuration file DOM";
log.error(errorMsg, e);
throw new ConfigurationException(errorMsg, e);
} catch (SAXException e) {
String errorMsg = "Configuration file does not validate against schema";
log.error(errorMsg, e);
throw new ConfigurationException(errorMsg, e);
}
}
}