| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 org.apache.jasper.compiler; |
| |
| import java.io.IOException; |
| import java.net.URL; |
| import java.util.Collection; |
| import java.util.Hashtable; |
| import java.util.Set; |
| import java.util.Vector; |
| |
| import javax.servlet.ServletContext; |
| import javax.servlet.jsp.tagext.FunctionInfo; |
| import javax.servlet.jsp.tagext.TagFileInfo; |
| import javax.servlet.jsp.tagext.TagInfo; |
| import javax.servlet.jsp.tagext.TagLibraryInfo; |
| |
| import org.apache.jasper.Constants; |
| import org.apache.jasper.JasperException; |
| import org.apache.jasper.JspCompilationContext; |
| import org.apache.tomcat.util.descriptor.tld.ImplicitTldRuleSet; |
| import org.apache.tomcat.util.descriptor.tld.TaglibXml; |
| import org.apache.tomcat.util.descriptor.tld.TldParser; |
| import org.apache.tomcat.util.descriptor.tld.TldResourcePath; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * Class responsible for generating an implicit tag library containing tag |
| * handlers corresponding to the tag files in "/WEB-INF/tags/" or a |
| * subdirectory of it. |
| * |
| * @author Jan Luehe |
| */ |
| class ImplicitTagLibraryInfo extends TagLibraryInfo { |
| |
| private static final String WEB_INF_TAGS = "/WEB-INF/tags"; |
| private static final String TAG_FILE_SUFFIX = ".tag"; |
| private static final String TAGX_FILE_SUFFIX = ".tagx"; |
| private static final String TAGS_SHORTNAME = "tags"; |
| private static final String TLIB_VERSION = "1.0"; |
| private static final String JSP_VERSION = "2.0"; |
| private static final String IMPLICIT_TLD = "implicit.tld"; |
| |
| // Maps tag names to tag file paths |
| private final Hashtable<String,String> tagFileMap; |
| |
| private final ParserController pc; |
| private final PageInfo pi; |
| private final Vector<TagFileInfo> vec; |
| |
| /** |
| * Constructor. |
| */ |
| public ImplicitTagLibraryInfo(JspCompilationContext ctxt, |
| ParserController pc, |
| PageInfo pi, |
| String prefix, |
| String tagdir, |
| ErrorDispatcher err) throws JasperException { |
| super(prefix, null); |
| this.pc = pc; |
| this.pi = pi; |
| this.tagFileMap = new Hashtable<>(); |
| this.vec = new Vector<>(); |
| |
| // Implicit tag libraries have no functions: |
| this.functions = new FunctionInfo[0]; |
| |
| tlibversion = TLIB_VERSION; |
| jspversion = JSP_VERSION; |
| |
| if (!tagdir.startsWith(WEB_INF_TAGS)) { |
| err.jspError("jsp.error.invalid.tagdir", tagdir); |
| } |
| |
| // Determine the value of the <short-name> subelement of the |
| // "imaginary" <taglib> element |
| if (tagdir.equals(WEB_INF_TAGS) |
| || tagdir.equals( WEB_INF_TAGS + "/")) { |
| shortname = TAGS_SHORTNAME; |
| } else { |
| shortname = tagdir.substring(WEB_INF_TAGS.length()); |
| shortname = shortname.replace('/', '-'); |
| } |
| |
| // Populate mapping of tag names to tag file paths |
| Set<String> dirList = ctxt.getResourcePaths(tagdir); |
| if (dirList != null) { |
| for (String path : dirList) { |
| if (path.endsWith(TAG_FILE_SUFFIX) |
| || path.endsWith(TAGX_FILE_SUFFIX)) { |
| /* |
| * Use the filename of the tag file, without the .tag or |
| * .tagx extension, respectively, as the <name> subelement |
| * of the "imaginary" <tag-file> element |
| */ |
| String suffix = path.endsWith(TAG_FILE_SUFFIX) ? |
| TAG_FILE_SUFFIX : TAGX_FILE_SUFFIX; |
| String tagName = path.substring(path.lastIndexOf('/') + 1); |
| tagName = tagName.substring(0, |
| tagName.lastIndexOf(suffix)); |
| tagFileMap.put(tagName, path); |
| } else if (path.endsWith(IMPLICIT_TLD)) { |
| TaglibXml taglibXml; |
| try { |
| URL url = ctxt.getResource(path); |
| TldResourcePath resourcePath = new TldResourcePath(url, path); |
| ServletContext servletContext = ctxt.getServletContext(); |
| boolean validate = Boolean.parseBoolean( |
| servletContext.getInitParameter( |
| Constants.XML_VALIDATION_TLD_INIT_PARAM)); |
| String blockExternalString = servletContext.getInitParameter( |
| Constants.XML_BLOCK_EXTERNAL_INIT_PARAM); |
| boolean blockExternal; |
| if (blockExternalString == null) { |
| blockExternal = true; |
| } else { |
| blockExternal = Boolean.parseBoolean(blockExternalString); |
| } |
| TldParser parser = new TldParser(true, validate, |
| new ImplicitTldRuleSet(), blockExternal); |
| taglibXml = parser.parse(resourcePath); |
| } catch (IOException | SAXException e) { |
| err.jspError(e); |
| // unreached |
| throw new JasperException(e); |
| } |
| this.tlibversion = taglibXml.getTlibVersion(); |
| this.jspversion = taglibXml.getJspVersion(); |
| try { |
| double version = Double.parseDouble(this.jspversion); |
| if (version < 2.0) { |
| err.jspError("jsp.error.invalid.implicit.version", path); |
| } |
| } catch (NumberFormatException e) { |
| err.jspError("jsp.error.invalid.implicit.version", path); |
| } |
| |
| // Add implicit TLD to dependency list |
| if (pi != null) { |
| pi.addDependant(path, ctxt.getLastModified(path)); |
| } |
| } |
| } |
| } |
| |
| } |
| |
| /** |
| * Checks to see if the given tag name maps to a tag file path, |
| * and if so, parses the corresponding tag file. |
| * |
| * @return The TagFileInfo corresponding to the given tag name, or null if |
| * the given tag name is not implemented as a tag file |
| */ |
| @Override |
| public TagFileInfo getTagFile(String shortName) { |
| |
| TagFileInfo tagFile = super.getTagFile(shortName); |
| if (tagFile == null) { |
| String path = tagFileMap.get(shortName); |
| if (path == null) { |
| return null; |
| } |
| |
| TagInfo tagInfo = null; |
| try { |
| tagInfo = TagFileProcessor.parseTagFileDirectives(pc, |
| shortName, |
| path, |
| null, |
| this); |
| } catch (JasperException je) { |
| throw new RuntimeException(je.toString(), je); |
| } |
| |
| tagFile = new TagFileInfo(shortName, path, tagInfo); |
| vec.addElement(tagFile); |
| |
| this.tagFiles = new TagFileInfo[vec.size()]; |
| vec.copyInto(this.tagFiles); |
| } |
| |
| return tagFile; |
| } |
| |
| @Override |
| public TagLibraryInfo[] getTagLibraryInfos() { |
| Collection<TagLibraryInfo> coll = pi.getTaglibs(); |
| return coll.toArray(new TagLibraryInfo[0]); |
| } |
| |
| } |