
org.carrot2.util.xslt.TemplatesPool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of carrot2-mini Show documentation
Show all versions of carrot2-mini Show documentation
Carrot2 search results clustering framework. Minimal functional subset
(core algorithms and infrastructure, no document sources).
/*
* Carrot2 project.
*
* Copyright (C) 2002-2012, Dawid Weiss, Stanisław Osiński.
* All rights reserved.
*
* Refer to the full license file "carrot2.LICENSE"
* in the root folder of the repository checkout or at:
* http://www.carrot2.org/carrot2.LICENSE
*/
package org.carrot2.util.xslt;
import java.io.InputStream;
import java.util.*;
import javax.xml.transform.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.slf4j.Logger;
import org.xml.sax.SAXException;
/**
* A pool of precompiled XSLT stylesheets ({@link Templates}). Caching can be disabled
* via constructor parameter or via setting a system property:
*
*
* template.caching
*
*
* to false
.
*/
public final class TemplatesPool
{
private final static Logger logger = org.slf4j.LoggerFactory.getLogger(TemplatesPool.class);
/**
* Global system property disabling template caching. This property can also be set at
* runtime (after the pool is initialized).
*/
public static final String TEMPLATE_CACHING_PROPERTY = "template.caching";
/**
* A set of used XSLT processors.
*/
private final static Set reportedProcessors = Collections.synchronizedSet(
new HashSet());
/**
* A map of precompiled stylesheets ({@link Templates} objects).
*/
private volatile HashMap stylesheets = new HashMap();
/**
* If true
the templates will not be cached until the application shuts
* down. This speeds up the application, but may be annoying, especially during
* development.
*/
private final boolean templateCaching;
/**
* {@link SAXTransformerFactory} capable of producing SAX-based transformers.
*/
public final SAXTransformerFactory tFactory;
/**
* Creates a {@link TemplatesPool} with caching enabled.
*/
public TemplatesPool() throws Exception
{
this(true);
}
/**
* Check for required facilities. If not available, an exception will be thrown.
*/
public TemplatesPool(boolean templateCaching) throws Exception
{
final TransformerFactory tFactory = TransformerFactory.newInstance();
final String processorClass = tFactory.getClass().getName();
/*
* Only report XSLT processor class once.
*/
if (!reportedProcessors.contains(processorClass))
{
logger.info("XSLT transformer factory: " + processorClass);
reportedProcessors.add(processorClass);
}
if (!tFactory.getFeature(SAXSource.FEATURE)
|| !tFactory.getFeature(SAXResult.FEATURE))
{
throw new Exception(
"Required source types not supported by the transformer factory.");
}
if (!tFactory.getFeature(SAXResult.FEATURE)
|| !tFactory.getFeature(StreamResult.FEATURE))
{
throw new Exception(
"Required result types not supported by the transformer factory.");
}
if (!(tFactory instanceof SAXTransformerFactory))
{
throw new Exception(
"TransformerFactory not an instance of SAXTransformerFactory: "
+ tFactory.getClass().getName());
}
this.tFactory = ((SAXTransformerFactory) tFactory);
this.tFactory.setErrorListener(new StylesheetErrorListener());
this.templateCaching = templateCaching;
}
/**
* @return returns the identity transformer handler.
*/
public TransformerHandler getIdentityTransformerHandler()
throws TransformerConfigurationException
{
return tFactory.newTransformerHandler();
}
/**
* Retrieves a previously stored template, if available.
*/
public Templates getTemplate(String key)
{
if (!isCaching())
{
return null;
}
return stylesheets.get(key);
}
/**
* Add a new template to the pool. Addition is quite costly as it replaces the
* internal {@link #stylesheets} {@link HashMap}.
*/
public void addTemplate(String key, Templates template)
{
if (!isCaching())
{
return;
}
/*
* Copy-on-write.
*/
synchronized (this)
{
final HashMap newMap = new HashMap(
this.stylesheets);
newMap.put(key, template);
this.stylesheets = newMap;
}
}
/**
* @return true
if template caching is enabled.
*/
private boolean isCaching()
{
/*
* Global override takes precedence.
*/
final String global = System.getProperty(TEMPLATE_CACHING_PROPERTY);
if (global != null)
{
return Boolean.parseBoolean(global);
}
return templateCaching;
}
/**
* Compile a {@link Templates} from a given system identifier. The template is not
* added to the pool, a manual call to {@link #addTemplate(String, Templates)} is
* required.
*/
public Templates compileTemplate(String systemId) throws SAXException
{
final StreamSource source = new StreamSource(systemId);
try
{
return tFactory.newTemplates(source);
}
catch (Exception e)
{
throw new SAXException("Could not compile stylesheet: " + systemId, e);
}
}
/**
* Compile a {@link Templates} from a given stream. The template is not added to the
* pool automatically.
*/
public Templates compileTemplate(InputStream stream) throws SAXException
{
final StreamSource source = new StreamSource(stream);
try
{
return tFactory.newTemplates(source);
}
catch (Exception e)
{
throw new SAXException("Could not compile stylesheet.", e);
}
}
/**
* Return a new {@link TransformerHandler} based on a given precompiled
* {@link Templates}. The handler {@link Transformer}'s {@link ErrorListener} is set
* to {@link TransformerErrorListener} to raise exceptions and give proper warnings.
*/
public TransformerHandler newTransformerHandler(Templates template)
throws TransformerConfigurationException
{
final TransformerHandler handler = this.tFactory.newTransformerHandler(template);
/*
* We want to raise transformer exceptions on , so
* we add a custom listener. Also, various XSLT processors react in different ways
* to transformation errors -- some of them report error as recoverable, some of
* them report error as unrecoverable.
*/
handler.getTransformer().setErrorListener(new TransformerErrorListener());
return handler;
}
/**
* Return a new {@link Transformer}.
*
* @see #newTransformerHandler(Templates)
*/
public Transformer newTransformer(Templates t)
throws TransformerConfigurationException
{
return newTransformerHandler(t).getTransformer();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy