teichmann@5831: package org.dive4elements.river.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@5785: import javax.xml.parsers.DocumentBuilder; teichmann@5785: import javax.xml.parsers.DocumentBuilderFactory; teichmann@5785: import javax.xml.parsers.ParserConfigurationException; 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@5785: pool.add(new Builder(cloneDocument(document))); teichmann@5779: } teichmann@5779: } teichmann@5779: teichmann@5779: private final static Document cloneDocument(Document document) { teichmann@5785: teichmann@5779: try { teichmann@5785: DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); teichmann@5785: DocumentBuilder db = dbf.newDocumentBuilder(); teichmann@5785: teichmann@5785: Node origRoot = document.getDocumentElement(); teichmann@5785: teichmann@5785: Document copy = db.newDocument(); teichmann@5785: Node copyRoot = copy.importNode(origRoot, true); teichmann@5785: copy.appendChild(copyRoot); teichmann@5785: teichmann@5785: return copy; teichmann@5779: } teichmann@5785: catch (ParserConfigurationException pce) { teichmann@5785: log.error(pce); teichmann@5779: } teichmann@5779: teichmann@5785: log.error("Returning original document. This will lead to threading issues."); 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 :