package railo.runtime.tag; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import javax.servlet.jsp.tagext.Tag; import railo.commons.lang.ClassUtil; import railo.runtime.config.ConfigWeb; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.PageException; import railo.runtime.op.Caster; // TODO kann man nicht auf context ebene /** * Pool to Handle Tags */ public final class TagHandlerPool { private ConcurrentHashMap<String,Queue<Tag>> map=new ConcurrentHashMap<String,Queue<Tag>>(); private ConfigWeb config; public TagHandlerPool(ConfigWeb config) { this.config=config; } /** * return a tag to use from a class * @param tagClass * @return Tag * @throws PageException */ public Tag use(String tagClass) throws PageException { Queue<Tag> queue = getQueue(tagClass); Tag tag = queue.poll(); if(tag!=null) return tag; return loadTag(tagClass); } /** * free a tag for reusing * @param tag * @throws ExpressionException */ public void reuse(Tag tag) { tag.release(); Queue<Tag> queue = getQueue(tag.getClass().getName()); queue.add(tag); } private Tag loadTag(String tagClass) throws PageException { try { Class<Tag> clazz = ClassUtil.loadClass(config.getClassLoader(),tagClass); return clazz.newInstance(); } catch (Exception e) { throw Caster.toPageException(e); } } private Queue<Tag> getQueue(String tagClass) { Queue<Tag> queue = map.get(tagClass);// doing get before, do avoid constructing ConcurrentLinkedQueue Object all the time if(queue!=null) return queue; Queue<Tag> nq,oq; oq=map.putIfAbsent(tagClass, nq=new ConcurrentLinkedQueue<Tag>()); if(oq!=null) return oq; return nq; } public void reset() { map.clear(); } }