<commit_before>/*
 * $Log: TransformerPool.java,v $
 * Revision 1.17  2007-07-26 16:26:18  europe\L190409
 * added configureTransformer()
 *
 * Revision 1.16  2007/05/08 16:02:19  <NAME> <<EMAIL>>
 * added transform() with result as parameter
 *
 * Revision 1.15  2007/02/12 14:12:03  <NAME> <<EMAIL>>
 * Logger from LogUtil
 *
 * Revision 1.14  2007/02/05 15:05:03  <NAME> <<EMAIL>>
 * use SoftReferencePool
 *
 * Revision 1.13  2005/10/20 15:22:44  <NAME> <<EMAIL>>
 * added explicit namespaceAware-setting for direct-string transformation
 *
 * Revision 1.12  2005/06/13 11:49:44  <NAME> <<EMAIL>>
 * use separate version of stringToSource, optimized for single use
 *
 * Revision 1.11  2005/06/13 10:01:55  <NAME> <<EMAIL>>
 * optimized for single transformation of strings
 *
 * Revision 1.10  2005/05/31 09:48:22  <NAME> <<EMAIL>>
 * using stringToSource() and always clearing parameters
 *
 * Revision 1.9  2005/03/31 08:16:27  <NAME> <<EMAIL>>
 * generalized Source
 *
 * Revision 1.8  2005/03/04 07:52:45  <NAME> <<EMAIL>>
 * Multi-threading caused problems with closed streams on creating transfomers.
 * Transformers are now instantiated by a Templates object, which solves this problem
 * and increases perfomance
 *
 * Revision 1.7  2005/01/10 08:56:10  <NAME> <<EMAIL>>
 * Xslt parameter handling by Maps instead of by Ibis parameter system
 *
 * Revision 1.6  2004/12/20 15:11:56  <NAME> <<EMAIL>>
 * Bugfix: systemID now properly handled. Transformer was created before system id was set.
 *
 * Revision 1.5  2004/10/26 16:26:03  <NAME> <<EMAIL>>
 * set UTF-8 as default inputstream encoding
 *
 * Revision 1.4  2004/10/19 15:27:19  <NAME> <<EMAIL>>
 * moved transformation to pool
 *
 * Revision 1.3  2004/10/14 16:12:00  <NAME> <<EMAIL>>
 * made creation of Transformes synchronized
 *
 * Revision 1.2  2004/10/12 15:15:03  <NAME> <<EMAIL>>
 * corrected XmlDeclaration-handling
 *
 * Revision 1.1  2004/10/05 09:56:59  <NAME> <<EMAIL>>
 * introduction of TransformerPool
 *
 */
package nl.nn.adapterframework.util;

import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import nl.nn.adapterframework.configuration.ConfigurationException;
import nl.nn.adapterframework.parameters.Parameter;
import nl.nn.adapterframework.parameters.ParameterList;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.SoftReferenceObjectPool;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;

/**
 * Pool of transformers. As of IBIS 4.2.e the Templates object is used to improve
 * performance and work around threading problems with the api.  
 * 
 * @author <NAME>
 */
public class TransformerPool {
	public static final String version = "$RCSfile: TransformerPool.java,v $ $Revision: 1.17 $ $Date: 2007-07-26 16:26:18 $";
	protected Logger log = LogUtil.getLogger(this);

	private TransformerFactory tFactory = TransformerFactory.newInstance();

	private Templates templates;
	
	private ObjectPool pool = new SoftReferenceObjectPool(new BasePoolableObjectFactory() {
		public Object makeObject() throws Exception {
			return createTransformer();			
		}
	}); 

	public TransformerPool(Source source, String sysId) throws TransformerConfigurationException {
		super();
		if (StringUtils.isNotEmpty(sysId)) {
			source.setSystemId(sysId);
			log.debug("setting systemId to ["+sysId+"]");
		}
		templates=tFactory.newTemplates(source);

		// check if a transformer can be initiated
		Transformer t = getTransformer();
		
		releaseTransformer(t);
	}	
	
	public TransformerPool(Source source) throws TransformerConfigurationException {
		this(source,null);
	}	

	public TransformerPool(URL url) throws TransformerConfigurationException, IOException {
		this(new StreamSource(url.openStream(),Misc.DEFAULT_INPUT_STREAM_ENCODING),url.toString());
	}
	
	public TransformerPool(String xsltString) throws TransformerConfigurationException {
		this(new StreamSource(new StringReader(xsltString)));
	}

	public TransformerPool(String xsltString, String sysId) throws TransformerConfigurationException {
		this(new StreamSource(new StringReader(xsltString)), sysId);
	}

	public static TransformerPool configureTransformer(String logPrefix, String xPathExpression, String styleSheetName, String outputType, boolean includeXmlDeclaration, ParameterList params) throws ConfigurationException {
		TransformerPool result;
		if (logPrefix==null) {
			logPrefix="";
		}
		if (!StringUtils.isEmpty(xPathExpression)) {
			if (!StringUtils.isEmpty(styleSheetName)) {
				throw new ConfigurationException(logPrefix+"cannot have both an xpathExpression and a styleSheetName specified");
			}
			try {
				List paramNames = null;
				if (params!=null) {
					paramNames = new ArrayList();
					Iterator iterator = params.iterator();
					while (iterator.hasNext()) {
						paramNames.add(((Parameter)iterator.next()).getName());
					}
				}
				result = new TransformerPool(XmlUtils.createXPathEvaluatorSource("",xPathExpression, outputType, includeXmlDeclaration, paramNames));
			} 
			catch (TransformerConfigurationException te) {
				throw new ConfigurationException(logPrefix+"got error creating transformer from xpathExpression [" + xPathExpression + "]", te);
			}
		} 
		else {
			if (!StringUtils.isEmpty(styleSheetName)) {
				URL resource = ClassUtils.getResourceURL(TransformerPool.class, styleSheetName);
				if (resource==null) {
					throw new ConfigurationException(logPrefix+"cannot find ["+ styleSheetName + "]"); 
				}
				try {
					result = new TransformerPool(resource);
				} catch (IOException e) {
					throw new ConfigurationException(logPrefix+"cannot retrieve ["+ styleSheetName + "], resource ["+resource.toString()+"]", e);
				} catch (TransformerConfigurationException te) {
					throw new ConfigurationException(logPrefix+"got error creating transformer from file [" + styleSheetName + "]", te);
				}
			} else {
				throw new ConfigurationException(logPrefix+"either xpathExpression or styleSheetName must be specified");
			}
		}
		return result;
	}
	

	
	public void open() throws Exception {
	}
	
	public void close() {
		try {
			pool.clear();			
		} catch (Exception e) {
			log.warn("exception clearing transformerPool",e);
		}
	}
	
	protected Transformer getTransformer() throws TransformerConfigurationException {
		try {
			return (Transformer)pool.borrowObject();
		} catch (Exception e) {<commit_msg>implemented auto reload (still experimental)<commit_after>/*
 * $Log: TransformerPool.java,v $
 * Revision 1.18  2008-05-15 15:21:54  europe\L190409
 * implemented auto reload (still experimental)
 *
 * Revision 1.17  2007/07/26 16:26:18  <NAME> <<EMAIL>>
 * added configureTransformer()
 *
 * Revision 1.16  2007/05/08 16:02:19  <NAME> <<EMAIL>>
 * added transform() with result as parameter
 *
 * Revision 1.15  2007/02/12 14:12:03  <NAME> <<EMAIL>>
 * Logger from LogUtil
 *
 * Revision 1.14  2007/02/05 15:05:03  <NAME> <<EMAIL>>
 * use SoftReferencePool
 *
 * Revision 1.13  2005/10/20 15:22:44  <NAME> <<EMAIL>>
 * added explicit namespaceAware-setting for direct-string transformation
 *
 * Revision 1.12  2005/06/13 11:49:44  <NAME> <<EMAIL>>
 * use separate version of stringToSource, optimized for single use
 *
 * Revision 1.11  2005/06/13 10:01:55  <NAME> <<EMAIL>>
 * optimized for single transformation of strings
 *
 * Revision 1.10  2005/05/31 09:48:22  <NAME> <<EMAIL>>
 * using stringToSource() and always clearing parameters
 *
 * Revision 1.9  2005/03/31 08:16:27  <NAME> <<EMAIL>>
 * generalized Source
 *
 * Revision 1.8  2005/03/04 07:52:45  <NAME> <<EMAIL>>
 * Multi-threading caused problems with closed streams on creating transfomers.
 * Transformers are now instantiated by a Templates object, which solves this problem
 * and increases perfomance
 *
 * Revision 1.7  2005/01/10 08:56:10  <NAME> <<EMAIL>>
 * Xslt parameter handling by Maps instead of by Ibis parameter system
 *
 * Revision 1.6  2004/12/20 15:11:56  <NAME> <<EMAIL>>
 * Bugfix: systemID now properly handled. Transformer was created before system id was set.
 *
 * Revision 1.5  2004/10/26 16:26:03  <NAME> <<EMAIL>>
 * set UTF-8 as default inputstream encoding
 *
 * Revision 1.4  2004/10/19 15:27:19  <NAME> <<EMAIL>>
 * moved transformation to pool
 *
 * Revision 1.3  2004/10/14 16:12:00  <NAME> <<EMAIL>>
 * made creation of Transformes synchronized
 *
 * Revision 1.2  2004/10/12 15:15:03  <NAME> <<EMAIL>>
 * corrected XmlDeclaration-handling
 *
 * Revision 1.1  2004/10/05 09:56:59  <NAME> <<EMAIL>>
 * introduction of TransformerPool
 *
 */
package nl.nn.adapterframework.util;

import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import nl.nn.adapterframework.configuration.ConfigurationException;
import nl.nn.adapterframework.parameters.Parameter;
import nl.nn.adapterframework.parameters.ParameterList;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.SoftReferenceObjectPool;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;

/**
 * Pool of transformers. As of IBIS 4.2.e the Templates object is used to improve
 * performance and work around threading problems with the api.  
 * 
 * @author <NAME>
 */
public class TransformerPool {
	public static final String version = "$RCSfile: TransformerPool.java,v $ $Revision: 1.18 $ $Date: 2008-05-15 15:21:54 $";
	protected Logger log = LogUtil.getLogger(this);

	private TransformerFactory tFactory = TransformerFactory.newInstance();

	private Templates templates;
	private URL reloadURL=null;
	
	private ObjectPool pool = new SoftReferenceObjectPool(new BasePoolableObjectFactory() {
		public Object makeObject() throws Exception {
			return createTransformer();			
		}
	}); 

	public TransformerPool(Source source, String sysId) throws TransformerConfigurationException {
		super();
		initTransformerPool(source, sysId);

		// check if a transformer can be initiated
		Transformer t = getTransformer();
		
		releaseTransformer(t);
	}	
	
	public TransformerPool(Source source) throws TransformerConfigurationException {
		this(source,null);
	}	

	public TransformerPool(URL url) throws TransformerConfigurationException, IOException {
		this(new StreamSource(url.openStream(),Misc.DEFAULT_INPUT_STREAM_ENCODING),url.toString());
	}
	
	public TransformerPool(String xsltString) throws TransformerConfigurationException {
		this(new StreamSource(new StringReader(xsltString)));
	}

	public TransformerPool(String xsltString, String sysId) throws TransformerConfigurationException {
		this(new StreamSource(new StringReader(xsltString)), sysId);
	}

	private void initTransformerPool(Source source, String sysId) throws TransformerConfigurationException {
		if (StringUtils.isNotEmpty(sysId)) {
			source.setSystemId(sysId);
			log.debug("setting systemId to ["+sysId+"]");
		}
		templates=tFactory.newTemplates(source);
	}

	private void reloadTransformerPool() throws TransformerConfigurationException, IOException {
		if (reloadURL!=null) {
			initTransformerPool(new StreamSource(reloadURL.openStream(),Misc.DEFAULT_INPUT_STREAM_ENCODING),reloadURL.toString());
			try {
				pool.clear();
			} catch (Exception e) {
				throw new TransformerConfigurationException("Could not clear pool",e);
			}
		}
	}

	public static TransformerPool configureTransformer(String logPrefix, String xPathExpression, String styleSheetName, String outputType, boolean includeXmlDeclaration, ParameterList params, boolean mandatory) throws ConfigurationException {
		if (mandatory || StringUtils.isNotEmpty(xPathExpression) || StringUtils.isNotEmpty(styleSheetName)) {
			return configureTransformer(logPrefix,xPathExpression,styleSheetName, outputType, includeXmlDeclaration, params);
		} 
		return null;
	}
	
	public static TransformerPool configureTransformer(String logPrefix, String xPathExpression, String styleSheetName, String outputType, boolean includeXmlDeclaration, ParameterList params) throws ConfigurationException {
		TransformerPool result;
		if (logPrefix==null) {
			logPrefix="";
		}
		if (!StringUtils.isEmpty(xPathExpression)) {
			if (!StringUtils.isEmpty(styleSheetName)) {
				throw new ConfigurationException(logPrefix+"cannot have both an xpathExpression and a styleSheetName specified");
			}
			try {
				List paramNames = null;
				if (params!=null) {
					paramNames = new ArrayList();
					Iterator iterator = params.iterator();
					while (iterator.hasNext()) {
						paramNames.add(((Parameter)iterator.next()).getName());
					}
				}
				result = new TransformerPool(XmlUtils.createXPathEvaluatorSource("",xPathExpression, outputType, includeXmlDeclaration, paramNames));
			} 
			catch (TransformerConfigurationException te) {
				throw new ConfigurationException(logPrefix+"got error creating transformer from xpathExpression [" + xPathExpression + "]", te);
			}
		} 
		else {
			if (!StringUtils.isEmpty(styleSheetName)) {
				URL resource = ClassUtils.getResourceURL(TransformerPool.class, styleSheetName);
				if (resource==null) {
					throw new ConfigurationException(logPrefix+"cannot find ["+ styleSheetName + "]"); 
				}
				try {
					result = new TransformerPool(resource);
				} catch (IOException e) {
					throw new ConfigurationException(logPrefix+"cannot retrieve ["+ styleSheetName + "], resource ["+resource.toString()+"]", e);
				} catch (TransformerConfigurationException te) {
					throw new ConfigurationException(logPrefix+"got error creating transformer from file [" + styleSheetName + "]", te);
				}
				if (XmlUtils.isAutoReload()) {
					result.reloadURL=resource;
				}
			} else {
				throw new ConfigurationException(logPrefix+"either xpathExpression or styleSheetName must be specified");
			}
		}
		return result;
	}
	

	
	public void open() throws Exception {
	}
	
	public void close() {
		try {
			pool.clear();			
		} catch (Exception e) {
			log.warn("exception clearing transformerPool",e);
		}
	}
	
	protected Transformer getTransformer() throws TransformerConfigurationException {
		try {
			reloadTransformerPool();
			return (Transformer)pool.borrowObject();
		} catch (Exception e) {
{'fraction_non_alphanumeric': 0.10929821112640063, 'fraction_numerical': 0.04147827796343621, 'mean_word_length': 4.7505651846269785, 'pattern_counts': {'":': 0, '<': 104, '<?xml version=': 0, '>': 104, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 18}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3433369', 'n_tokens_mistral': 5268, 'n_tokens_neox': 4438, 'n_words': 1167}