teichmann@5779: package de.intevation.flys.artifacts.datacage.templating; teichmann@5779: teichmann@5779: import java.util.ArrayDeque; teichmann@5779: import java.util.Deque; teichmann@5779: import java.util.List; teichmann@5779: import java.util.Map; teichmann@5779: teichmann@5779: import java.sql.SQLException; teichmann@5779: teichmann@5779: import javax.xml.transform.Transformer; teichmann@5779: import javax.xml.transform.TransformerConfigurationException; teichmann@5779: import javax.xml.transform.TransformerException; teichmann@5779: import javax.xml.transform.TransformerFactory; teichmann@5779: teichmann@5779: import javax.xml.transform.dom.DOMResult; teichmann@5779: import javax.xml.transform.dom.DOMSource; teichmann@5779: teichmann@5779: import org.apache.log4j.Logger; teichmann@5779: teichmann@5779: import org.w3c.dom.Document; teichmann@5779: import org.w3c.dom.Node; teichmann@5779: teichmann@5779: /** A little round robin pool of builders to mitigate teichmann@5779: * the fact the XML DOM documents are not thread safe. teichmann@5779: */ teichmann@5779: public class BuilderPool teichmann@5779: { teichmann@5779: private static Logger log = Logger.getLogger(BuilderPool.class); teichmann@5779: teichmann@5779: private static final int DEFAULT_POOL_SIZE = 4; teichmann@5779: teichmann@5779: private static final int POOL_SIZE = Math.max( teichmann@5779: Integer.getInteger("flys.datacage.pool.size", DEFAULT_POOL_SIZE), 1); teichmann@5779: teichmann@5779: private Deque pool; teichmann@5779: teichmann@5779: public BuilderPool(Document document) { teichmann@5779: this(document, POOL_SIZE); teichmann@5779: } teichmann@5779: teichmann@5779: public BuilderPool(Document document, int poolSize) { teichmann@5779: teichmann@5779: if (log.isDebugEnabled()) { teichmann@5779: log.debug("Create build pool with " + poolSize + " elements."); teichmann@5779: } teichmann@5779: teichmann@5779: pool = new ArrayDeque(poolSize); teichmann@5779: for (int i = 0; i < poolSize; ++i) { teichmann@5779: Document doc = i > 0 // Clone all but the first. teichmann@5779: ? cloneDocument(document) teichmann@5779: : document; teichmann@5779: pool.add(new Builder(doc)); teichmann@5779: } teichmann@5779: } teichmann@5779: teichmann@5779: private final static Document cloneDocument(Document document) { teichmann@5779: try { teichmann@5779: TransformerFactory tfactory = TransformerFactory.newInstance(); teichmann@5779: Transformer xformer = tfactory.newTransformer(); teichmann@5779: DOMSource src = new DOMSource(document); teichmann@5779: DOMResult dst = new DOMResult(); teichmann@5779: xformer.transform(src, dst); teichmann@5779: return (Document)dst.getNode(); teichmann@5779: } teichmann@5779: catch (TransformerConfigurationException tce) { teichmann@5779: log.error(tce); teichmann@5779: } teichmann@5779: catch (TransformerException te) { teichmann@5779: log.error(te); teichmann@5779: } teichmann@5779: teichmann@5779: log.error( teichmann@5779: "Returning original DOM document. " + teichmann@5779: "This will result in threading errors!"); teichmann@5779: teichmann@5779: return document; teichmann@5779: } teichmann@5779: teichmann@5779: public void build( teichmann@5779: List connections, teichmann@5779: Node output, teichmann@5779: Map parameters teichmann@5779: ) teichmann@5779: throws SQLException teichmann@5779: { teichmann@5779: Builder builder; teichmann@5779: synchronized (pool) { teichmann@5779: try { teichmann@5779: while ((builder = pool.poll()) == null) { teichmann@5779: pool.wait(); teichmann@5779: } teichmann@5779: } teichmann@5779: catch (InterruptedException ie) { teichmann@5779: log.debug("Waiting for builder interrupted. Build canceled."); teichmann@5779: return; teichmann@5779: } teichmann@5779: } teichmann@5779: try { teichmann@5779: builder.build(connections, output, parameters); teichmann@5779: } teichmann@5779: finally { teichmann@5779: synchronized (pool) { teichmann@5779: pool.add(builder); teichmann@5779: pool.notify(); teichmann@5779: } teichmann@5779: } teichmann@5779: } teichmann@5779: } teichmann@5779: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :