/*
* 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.core.util.xmlsecurity;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.transform.TransformerFactory;
import net.sf.saxon.jaxp.SaxonTransformerFactory;
/**
* Avoid configuring factories each time they are used. Since we started using setFeature to avoid security issues,
* getting a new XML factory object is very expensive.
*/
public class XMLSecureFactoriesCache {
private LoadingCache<XMLFactoryConfig, Object> cache = null;
private static volatile XMLSecureFactoriesCache instance;
public static XMLSecureFactoriesCache getInstance() {
if (instance == null) {
synchronized (XMLSecureFactoriesCache.class) {
if (instance == null) {
instance = new XMLSecureFactoriesCache();
}
}
}
return instance;
}
private XMLSecureFactoriesCache() {
cache = CacheBuilder.newBuilder()
.build(new CacheLoader<XMLFactoryConfig, Object>() {
@Override
public Object load(XMLFactoryConfig key) throws Exception {
return key.createFactory();
}
});
}
public DocumentBuilderFactory getDocumentBuilderFactory(final Boolean externalEntities, final Boolean expandEntities) {
XMLFactoryConfig config = new XMLFactoryConfig(externalEntities, expandEntities, DocumentBuilderFactory.class.toString()) {
@Override
public Object createFactory() {
return DefaultXMLSecureFactories.createDocumentBuilderFactory(this.externalEntities, this.expandEntities);
}
};
return (DocumentBuilderFactory) cache.getUnchecked(config);
}
public SAXParserFactory getSAXParserFactory(Boolean externalEntities, Boolean expandEntities) {
XMLFactoryConfig config = new XMLFactoryConfig(externalEntities, expandEntities, SAXParserFactory.class.toString()) {
@Override
public Object createFactory() {
return DefaultXMLSecureFactories.createSaxParserFactory(this.externalEntities, this.expandEntities);
}
};
return (SAXParserFactory) cache.getUnchecked(config);
}
public XMLInputFactory getXMLInputFactory(Boolean externalEntities, Boolean expandEntities) {
XMLFactoryConfig config = new XMLFactoryConfig(externalEntities, expandEntities, XMLInputFactory.class.toString()) {
@Override
public Object createFactory() {
return DefaultXMLSecureFactories.createXmlInputFactory(this.externalEntities, this.expandEntities);
}
};
return (XMLInputFactory) cache.getUnchecked(config);
}
public TransformerFactory getTransformerFactory(Boolean externalEntities, Boolean expandEntities) {
XMLFactoryConfig config = new XMLFactoryConfig(externalEntities, expandEntities, TransformerFactory.class.toString()) {
@Override
public Object createFactory() {
return DefaultXMLSecureFactories.createTransformerFactory(this.externalEntities, this.expandEntities);
}
};
return (TransformerFactory) cache.getUnchecked(config);
}
public TransformerFactory getSaxonTransformerFactory(Boolean externalEntities, Boolean expandEntities) {
XMLFactoryConfig config = new XMLFactoryConfig(externalEntities, expandEntities, SaxonTransformerFactory.class.toString()) {
@Override
public Object createFactory() {
return DefaultXMLSecureFactories.createSaxonTransformerFactory(this.externalEntities, this.expandEntities);
}
};
return (TransformerFactory) cache.getUnchecked(config);
}
}