/* * #! * Ontopia Navigator * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.utils.ontojsp; import java.util.HashMap; import java.util.Map; import javax.servlet.jsp.tagext.TagSupport; import net.ontopia.topicmaps.nav2.core.NavigatorRuntimeException; import net.ontopia.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * INTERNAL: A TaglibTagFactory that creates the correct tags from the * <code>net.ontopia.nav2.taglibs</code> packages. Used for the * implentation of the call tag and internally for testing. * * @see net.ontopia.topicmaps.nav2.taglibs.logic.CallTag */ public class TaglibTagFactory implements JSPTagFactoryIF { // tagPool = <parentTag, <poolKey, pooledTag>> private Map<TagSupport, Map<String, TagSupport>> tagPool; private final boolean useTagPooling; public static final boolean TAGPOOLING_DEFAULT = false; // initialize logging facility static Logger log = LoggerFactory.getLogger(TaglibTagFactory.class.getName()); // Map between tag names (with namespace prefix) and Java Classes static Map<String, String> classes; public TaglibTagFactory() { this(TAGPOOLING_DEFAULT); } public TaglibTagFactory(boolean useTagPooling) { this.useTagPooling = useTagPooling; if (classes == null) initClassMap(); } public static String getTagName(Class tagclass) { String classname = tagclass.getName(); for (String tagname : classes.keySet()) { if (classes.get(tagname).equals(classname)) return tagname; } return "unresolved tag: " + classname; } public static boolean isKnownTag(String tagname) { if (classes == null) initClassMap(); return (classes.get(tagname) != null); } public TagSupport getTagInstance(String tagname, Map<String, String> attrVals, TagSupport parentTag) throws NavigatorRuntimeException { if (!isKnownTag(tagname)) throw new NavigatorRuntimeException("TaglibTagFactory - " + "Unknown tag: " + tagname); if (useTagPooling) { if (tagPool == null) { tagPool = new HashMap<TagSupport, Map<String, TagSupport>>(); } Map<String, TagSupport> poolEntry = tagPool.get(parentTag); String poolKey = getTagPoolingKey(tagname, attrVals); log.debug("Looking up tag with key '" + poolKey + "' in tag pool for parent tag " + parentTag); if (poolEntry == null) { poolEntry = new HashMap<String, TagSupport>(); tagPool.put(parentTag, poolEntry); } else { TagSupport pooledTag = poolEntry.get(poolKey); if (pooledTag != null) { log.debug("Found matching tag in pool, reusing " + pooledTag); return pooledTag; } } } // create tag instance String classname = classes.get(tagname); TagSupport tag = null; try { // try to get class for tag classname ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class tagclass = Class.forName(classname, true, classLoader); // try to instaniate an object of tag class tag = (TagSupport) tagclass.newInstance(); } catch (Exception e) { String msg = "TaglibTagFactory - unable to create instance of class " + classname + " for tag " + tagname; throw new NavigatorRuntimeException(msg, e); } if (useTagPooling) { Map<String, TagSupport> poolEntry = tagPool.get(parentTag); String poolKey = getTagPoolingKey(tagname, attrVals); log.debug("Found no tag in pool, storing tag " + tag); poolEntry.put(poolKey, tag); } return tag; } // --- internal helper method private String getTagPoolingKey(String tagname, Map<String, String> attrVals) { return tagname + " " + StringUtils.join(attrVals.keySet(), " "); } private static void initClassMap() { classes = new HashMap<String, String>(); // package base name for all tag classes String tlpackage = "net.ontopia.topicmaps.nav2.taglibs."; String tlpackage2 = "net.ontopia.topicmaps.webed.taglibs."; String ptlpackage = "net.ontopia.topicmaps.nav2.portlets.taglib."; String core = "org.apache.taglibs.standard.tag.el.core."; // setup class <-> tagname mapping classes.put("tm:associated", tlpackage + "TMvalue.AssociatedTag"); classes.put("tm:associations", tlpackage + "TMvalue.AssociationsTag"); classes.put("tm:associationTypeLoop", tlpackage + "TMvalue.AssociationTypeLoopTag"); classes.put("tm:classesOf", tlpackage + "TMvalue.ClassesOfTag"); classes.put("tm:classes", tlpackage + "TMvalue.ClassesTag"); classes.put("tm:filter", tlpackage + "TMvalue.FilterTag"); classes.put("tm:subjectAddress", tlpackage + "TMvalue.SubjectAddressTag"); classes.put("tm:indicators", tlpackage + "TMvalue.IndicatorsTag"); classes.put("tm:instances", tlpackage + "TMvalue.InstancesTag"); classes.put("tm:locator", tlpackage + "TMvalue.LocatorTag"); classes.put("tm:lookup", tlpackage + "TMvalue.LookupTag"); classes.put("tm:name", tlpackage + "TMvalue.NameTag"); classes.put("tm:names", tlpackage + "TMvalue.NamesTag"); classes.put("tm:occurrences", tlpackage + "TMvalue.OccurrencesTag"); classes.put("tm:reifier", tlpackage + "TMvalue.ReifierTag"); classes.put("tm:reified", tlpackage + "TMvalue.ReifiedTag"); classes.put("tm:roles", tlpackage + "TMvalue.RolesTag"); classes.put("tm:scope", tlpackage + "TMvalue.ScopeTag"); classes.put("tm:splitter", tlpackage + "TMvalue.SplitterTag"); classes.put("tm:sourceLocators", tlpackage + "TMvalue.SourceLocatorsTag"); classes.put("tm:subclasses", tlpackage + "TMvalue.SubclassesTag"); classes.put("tm:superclasses", tlpackage + "TMvalue.SuperclassesTag"); classes.put("tm:topics", tlpackage + "TMvalue.TopicsTag"); classes.put("tm:themes", tlpackage + "TMvalue.ThemesTag"); classes.put("tm:variants", tlpackage + "TMvalue.VariantsTag"); classes.put("tm:tolog", tlpackage + "TMvalue.TologQueryTag"); classes.put("logic:call", tlpackage + "logic.CallTag"); classes.put("logic:context", tlpackage + "logic.ContextTag"); classes.put("logic:error", tlpackage + "logic.ErrorTag"); classes.put("logic:foreach", tlpackage + "logic.ForEachTag"); // deprecated: ("logic:function", tlpackage + "logic.FunctionTag"); classes.put("logic:include", tlpackage + "logic.IncludeTag"); classes.put("logic:externalFunction", tlpackage + "logic.ExternalFunctionTag"); classes.put("logic:if", tlpackage + "logic.IfTag"); classes.put("logic:then", tlpackage + "logic.IfThenTag"); classes.put("logic:else", tlpackage + "logic.IfElseTag"); classes.put("logic:set", tlpackage + "logic.SetTag"); classes.put("logic:bind", tlpackage + "logic.BindTag"); classes.put("output:content", tlpackage + "output.ContentTag"); classes.put("output:count", tlpackage + "output.CountTag"); classes.put("output:link", tlpackage + "output.LinkTag"); classes.put("output:name", tlpackage + "output.NameTag"); classes.put("output:objectid", tlpackage + "output.ObjectIdTag"); classes.put("output:property", tlpackage + "output.PropertyTag"); classes.put("output:locator", tlpackage + "output.LocatorTag"); classes.put("output:element", tlpackage + "output.ElementTag"); classes.put("output:attribute", tlpackage + "output.AttributeTag"); // classes.put("output:treediagram", tlpackage + "output.TreeDiagramTag"); classes.put("output:id", tlpackage + "output.SymbolicIdTag"); classes.put("output:debug", tlpackage + "output.DebugTag"); classes.put("value:copy", tlpackage + "value.CopyTag"); classes.put("value:difference", tlpackage + "value.DifferenceTag"); classes.put("value:intersection", tlpackage + "value.IntersectionTag"); classes.put("value:string", tlpackage + "value.StringTag"); classes.put("value:union", tlpackage + "value.UnionTag"); classes.put("value:sequence", tlpackage + "value.SequenceTag"); classes.put("framework:getcontext", tlpackage + "framework.GetContextTag"); classes.put("framework:setcontext", tlpackage + "framework.SetContextTag"); classes.put("framework:pluginList", tlpackage + "framework.PluginListTag"); classes.put("webed:form", tlpackage2 + "form.FormTag"); classes.put("webed:list", tlpackage2 + "form.ListTag"); classes.put("webed:field", tlpackage2 + "form.FieldTag"); classes.put("webed:button", tlpackage2 + "form.ButtonTag"); classes.put("webed:checkbox", tlpackage2 + "form.CheckboxTag"); classes.put("webed:invoke", tlpackage2 + "form.InvokeTag"); classes.put("webed:actionid", tlpackage2 + "form.ActionIDTag"); classes.put("tolog:choose", tlpackage + "tolog.ChooseTag"); classes.put("tolog:context", tlpackage + "logic.ContextTag"); classes.put("tolog:declare", tlpackage + "tolog.DeclareTag"); classes.put("tolog:foreach", tlpackage + "tolog.ForEachTag"); classes.put("tolog:id", tlpackage + "tolog.SymbolicIdTag"); classes.put("tolog:if", tlpackage + "tolog.IfTag"); classes.put("tolog:otherwise", tlpackage + "tolog.OtherwiseTag"); classes.put("tolog:oid", tlpackage + "tolog.ObjectIdTag"); classes.put("tolog:out", tlpackage + "tolog.OutTag"); classes.put("tolog:query", tlpackage + "tolog.QueryTag"); classes.put("tolog:set", tlpackage + "tolog.SetTag"); classes.put("tolog:when", tlpackage + "tolog.WhenTag"); classes.put("tolog:normalize", tlpackage + "tolog.NormalizeWhitespaceTag"); classes.put("portlet:related", ptlpackage + "RelatedTag"); classes.put("c:forEach", core + "ForEachTag"); classes.put("c:out", core + "OutTag"); classes.put("fmt:message", "org.apache.taglibs.standard.tag.el.fmt.MessageTag"); } }