/** * Copyright (c) 2014, the Railo Company Ltd. * Copyright (c) 2015, Lucee Assosication Switzerland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ package lucee.runtime.tag; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import javax.servlet.jsp.tagext.Tag; import lucee.runtime.config.ConfigWeb; import lucee.runtime.config.Identification; import lucee.runtime.exp.ExpressionException; import lucee.runtime.exp.PageException; import lucee.runtime.op.Caster; import lucee.transformer.library.ClassDefinitionImpl; // 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 className,String tagBundleName, String tagBundleVersion, Identification id) throws PageException { Queue<Tag> queue = getQueue(toId(className,tagBundleName,tagBundleVersion)); Tag tag = queue.poll(); if(tag!=null) return tag; return loadTag(className,tagBundleName,tagBundleVersion,id); } private String toId(String className, String tagBundleName, String tagBundleVersion) { if(tagBundleName==null && tagBundleVersion==null) return className; if(tagBundleVersion==null) return className+":"+tagBundleName; return className+":"+tagBundleName+":"+tagBundleVersion; } /** * 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); } public void reuse(Tag tag, String bundleName, String bundleVersion) { tag.release(); Queue<Tag> queue = getQueue(toId(tag.getClass().getName(),bundleName,bundleVersion)); queue.add(tag); } private Tag loadTag(String className,String tagBundleName, String tagBundleVersion, Identification id) throws PageException { try { return (Tag) new ClassDefinitionImpl(className, tagBundleName, tagBundleVersion,id).getClazz().newInstance(); //Class<Tag> clazz = ClassUtil.loadClass(config.getClassLoader(),tagClass); //return clazz.newInstance(); } catch (Exception e) { throw Caster.toPageException(e); } } private Queue<Tag> getQueue(String id) { Queue<Tag> queue = map.get(id);// doing get before, do avoid constructing ConcurrentLinkedQueue Object all the time if(queue!=null) return queue; Queue<Tag> nq,oq; oq=map.putIfAbsent(id, nq=new ConcurrentLinkedQueue<Tag>()); if(oq!=null) return oq; return nq; } public void reset() { map.clear(); } }