org.mule.runtime.config.spring.api.XmlConfigurationDocumentLoader Maven / Gradle / Ivy
/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.config.spring.api;
import static java.lang.String.format;
import static java.lang.System.lineSeparator;
import static java.lang.Thread.currentThread;
import static java.util.Collections.emptySet;
import static org.mule.runtime.api.i18n.I18nMessageFactory.createStaticMessage;
import org.mule.runtime.api.exception.MuleRuntimeException;
import org.mule.runtime.api.meta.model.ExtensionModel;
import org.mule.runtime.config.spring.internal.DefaultXmlGathererErrorHandlerFactory;
import org.mule.runtime.config.spring.internal.DefaultXmlLoggerErrorHandler;
import org.mule.runtime.config.spring.internal.ModuleDelegatingEntityResolver;
import org.mule.runtime.config.spring.internal.MuleDocumentLoader;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.xml.DelegatingEntityResolver;
import org.w3c.dom.Document;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Loads a mule configuration file into a {@link Document} object.
*
* If when loading the configuration one, or more, {@link ErrorHandler#error(SAXParseException)} are call, at the end of
* {@link #loadDocument(Set, String, InputStream)} will throw an exception containing all the errors.
*
* @see {@link #loadDocument(Set, String, InputStream)}
* @since 4.0
*/
public class XmlConfigurationDocumentLoader {
/**
* Indicates that XSD validation should be used (found no "DOCTYPE" declaration).
*/
private static final int VALIDATION_XSD = 3;
/**
* Indicates that the validation should be disabled.
*/
private static final int NO_VALIDATION = 0;
private final XmlGathererErrorHandlerFactory xmlGathererErrorHandlerFactory;
private final int validationMode;
/**
* Creates an {@link XmlConfigurationDocumentLoader} using the default {@link DefaultXmlGathererErrorHandlerFactory} to
* instantiate {@link XmlGathererErrorHandler}s objects when executing the {@link #loadDocument(Set, String, InputStream)}
* method.
*
* Using the default constructor implies that all XSD validations will take place and, at the end of the parsing, all the errors
* will be contained in an {@link MuleRuntimeException} which will be thrown.
*
* @return a new instance of {@link XmlConfigurationDocumentLoader}
*/
public static XmlConfigurationDocumentLoader schemaValidatingDocumentLoader() {
return new XmlConfigurationDocumentLoader(new DefaultXmlGathererErrorHandlerFactory());
}
/**
* Creates an {@link XmlConfigurationDocumentLoader} using a parametrized {@link XmlGathererErrorHandlerFactory} to instantiate
* {@link XmlGathererErrorHandler}s objects when executing the {@link #loadDocument(Set, String, InputStream)} method.
*
* Depending on what type of {@link XmlGathererErrorHandler} the factory returns, the
* {@link #loadDocument(Set, String, InputStream)} method will not thrown any exception if
* {@link XmlGathererErrorHandler#getErrors()} is an empty list.
*
* @param errorHandlerFactory to create {@link XmlGathererErrorHandler} in the {@link #loadDocument(Set, String, InputStream)}
* @return a new instance of {@link XmlConfigurationDocumentLoader}
*/
public static XmlConfigurationDocumentLoader schemaValidatingDocumentLoader(XmlGathererErrorHandlerFactory errorHandlerFactory) {
return new XmlConfigurationDocumentLoader(errorHandlerFactory);
}
/**
* Creates an {@link XmlConfigurationDocumentLoader} that will ignore XSD validation when executing the
* {@link #loadDocument(Set, String, InputStream)} method.
*
*
* @return a new instance of {@link XmlConfigurationDocumentLoader}
*/
public static XmlConfigurationDocumentLoader noValidationDocumentLoader() {
return new XmlConfigurationDocumentLoader(null);
}
private XmlConfigurationDocumentLoader(XmlGathererErrorHandlerFactory errorHandlerFactory) {
this.validationMode = errorHandlerFactory != null ? VALIDATION_XSD : NO_VALIDATION;
this.xmlGathererErrorHandlerFactory = errorHandlerFactory;
}
/**
* Creates a {@link Document} from an {@link InputStream} with the required configuration of a mule configuration file parsing.
*
* @param inputStream the input stream with the XML configuration content.
* @return a new {@link Document} object with the provided content.
* @throws MuleRuntimeException if an error occurs in {@link org.springframework.beans.factory.xml.DocumentLoader} factory, or
* if the current {@code filename} contains 1 or more errors.
* @see {@link DefaultXmlLoggerErrorHandler#getErrors()}
*/
public Document loadDocument(String filename, InputStream inputStream) {
return loadDocument(emptySet(), filename, inputStream);
}
/**
* Creates a {@link Document} from an {@link InputStream} with the required configuration of a mule configuration file parsing.
*
* @param extensions if the current {@code inputStream} relies in other schemas pending to be loaded from an
* {@link ExtensionModel}, it will be picked up from {@code extensions} set
* @param filename name of the file to display a better error messages (if there are any). Non null.
* @param inputStream the input stream with the XML configuration content.
* @return a new {@link Document} object with the provided content.
* @throws MuleRuntimeException if an error occurs in {@link org.springframework.beans.factory.xml.DocumentLoader} factory, or
* if the current {@code filename} contains 1 or more errors.
* @see {@link DefaultXmlLoggerErrorHandler#getErrors()}
*/
public Document loadDocument(Set extensions, String filename, InputStream inputStream) {
final XmlGathererErrorHandler errorHandler = createXmlGathererErrorHandler();
Document document;
try {
document = new MuleDocumentLoader()
.loadDocument(new InputSource(inputStream),
validationMode == VALIDATION_XSD ? new ModuleDelegatingEntityResolver(extensions)
: new DelegatingEntityResolver(currentThread().getContextClassLoader()),
errorHandler == null ? new DefaultHandler() : errorHandler,
validationMode, true);
} catch (Exception e) {
throw new MuleRuntimeException(createStaticMessage(format("Error loading: %s, %s", filename, e.getMessage())), e);
}
if (validationMode == VALIDATION_XSD) {
throwExceptionIfErrorsWereFound(errorHandler, filename);
}
return document;
}
private void throwExceptionIfErrorsWereFound(XmlGathererErrorHandler errorHandler, String filename) {
final List errors = errorHandler.getErrors();
if (!errors.isEmpty()) {
final String subMessage = format(errors.size() == 1 ? "was '%s' error" : "were '%s' errors", errors.size());
final StringBuilder sb =
new StringBuilder("There " + subMessage + " while parsing the given file"
+ (filename.isEmpty() ? "." : " '" + filename + "'."));
sb.append(lineSeparator()).append("Full list:");
errors.forEach(error -> sb.append(lineSeparator()).append(error));
sb.append(lineSeparator());
throw new MuleRuntimeException(createStaticMessage(sb.toString()));
}
}
private XmlGathererErrorHandler createXmlGathererErrorHandler() {
return validationMode == VALIDATION_XSD ? xmlGathererErrorHandlerFactory.create() : null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy