View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.struts2.jasper.compiler;
19  
20  import org.apache.struts2.jasper.JasperException;
21  import org.apache.struts2.jasper.JspCompilationContext;
22  
23  import javax.servlet.jsp.tagext.FunctionInfo;
24  import javax.servlet.jsp.tagext.TagFileInfo;
25  import javax.servlet.jsp.tagext.TagInfo;
26  import javax.servlet.jsp.tagext.TagLibraryInfo;
27  import java.util.Hashtable;
28  import java.util.Iterator;
29  import java.util.Set;
30  import java.util.Vector;
31  
32  /***
33   * Class responsible for generating an implicit tag library containing tag
34   * handlers corresponding to the tag files in "/WEB-INF/tags/" or a
35   * subdirectory of it.
36   *
37   * @author Jan Luehe
38   */
39  class ImplicitTagLibraryInfo extends TagLibraryInfo {
40  
41      private static final String WEB_INF_TAGS = "/WEB-INF/tags";
42      private static final String TAG_FILE_SUFFIX = ".tag";
43      private static final String TAGX_FILE_SUFFIX = ".tagx";
44      private static final String TAGS_SHORTNAME = "tags";
45      private static final String TLIB_VERSION = "1.0";
46      private static final String JSP_VERSION = "2.0";
47  
48      // Maps tag names to tag file paths
49      private Hashtable tagFileMap;
50  
51      private ParserController pc;
52      private Vector vec;
53  
54      /***
55       * Constructor.
56       */
57      public ImplicitTagLibraryInfo(JspCompilationContext ctxt,
58                                    ParserController pc,
59                                    String prefix,
60                                    String tagdir,
61                                    ErrorDispatcher err) throws JasperException {
62          super(prefix, null);
63          this.pc = pc;
64          this.tagFileMap = new Hashtable();
65          this.vec = new Vector();
66  
67          // Implicit tag libraries have no functions:
68          this.functions = new FunctionInfo[0];
69  
70          tlibversion = TLIB_VERSION;
71          jspversion = JSP_VERSION;
72  
73          if (!tagdir.startsWith(WEB_INF_TAGS)) {
74              err.jspError("jsp.error.invalid.tagdir", tagdir);
75          }
76  
77          // Determine the value of the <short-name> subelement of the
78          // "imaginary" <taglib> element
79          if (tagdir.equals(WEB_INF_TAGS)
80                  || tagdir.equals(WEB_INF_TAGS + "/")) {
81              shortname = TAGS_SHORTNAME;
82          } else {
83              shortname = tagdir.substring(WEB_INF_TAGS.length());
84              shortname = shortname.replace('/', '-');
85          }
86  
87          // Populate mapping of tag names to tag file paths
88          Set dirList = ctxt.getResourcePaths(tagdir);
89          if (dirList != null) {
90              Iterator it = dirList.iterator();
91              while (it.hasNext()) {
92                  String path = (String) it.next();
93                  if (path.endsWith(TAG_FILE_SUFFIX)
94                          || path.endsWith(TAGX_FILE_SUFFIX)) {
95                      /*
96                    * Use the filename of the tag file, without the .tag or
97                    * .tagx extension, respectively, as the <name> subelement
98                    * of the "imaginary" <tag-file> element
99                    */
100                     String suffix = path.endsWith(TAG_FILE_SUFFIX) ?
101                             TAG_FILE_SUFFIX : TAGX_FILE_SUFFIX;
102                     String tagName = path.substring(path.lastIndexOf("/") + 1);
103                     tagName = tagName.substring(0,
104                             tagName.lastIndexOf(suffix));
105                     tagFileMap.put(tagName, path);
106                 }
107             }
108         }
109     }
110 
111     /***
112      * Checks to see if the given tag name maps to a tag file path,
113      * and if so, parses the corresponding tag file.
114      *
115      * @return The TagFileInfo corresponding to the given tag name, or null if
116      *         the given tag name is not implemented as a tag file
117      */
118     public TagFileInfo getTagFile(String shortName) {
119 
120         TagFileInfo tagFile = super.getTagFile(shortName);
121         if (tagFile == null) {
122             String path = (String) tagFileMap.get(shortName);
123             if (path == null) {
124                 return null;
125             }
126 
127             TagInfo tagInfo = null;
128             try {
129                 tagInfo = TagFileProcessor.parseTagFileDirectives(pc,
130                         shortName,
131                         path,
132                         this);
133             } catch (JasperException je) {
134                 throw new RuntimeException(je.toString());
135             }
136 
137             tagFile = new TagFileInfo(shortName, path, tagInfo);
138             vec.addElement(tagFile);
139 
140             this.tagFiles = new TagFileInfo[vec.size()];
141             vec.copyInto(this.tagFiles);
142         }
143 
144         return tagFile;
145     }
146 }