Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/taglibs/standard/tlv/JstlBaseTLV.java


1   /*
2    * Copyright 1999-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  
17  package org.apache.taglibs.standard.tlv;
18  
19  import java.io.IOException;
20  import java.util.HashMap;
21  import java.util.HashSet;
22  import java.util.Map;
23  import java.util.NoSuchElementException;
24  import java.util.Set;
25  import java.util.StringTokenizer;
26  import java.util.Vector;
27  
28  import javax.servlet.jsp.JspException;
29  import javax.servlet.jsp.tagext.PageData;
30  import javax.servlet.jsp.tagext.TagData;
31  import javax.servlet.jsp.tagext.TagLibraryValidator;
32  import javax.servlet.jsp.tagext.ValidationMessage;
33  import javax.xml.parsers.ParserConfigurationException;
34  import javax.xml.parsers.SAXParser;
35  import javax.xml.parsers.SAXParserFactory;
36  
37  import org.apache.taglibs.standard.lang.support.ExpressionEvaluator;
38  import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
39  import org.apache.taglibs.standard.resources.Resources;
40  import org.xml.sax.Attributes;
41  import org.xml.sax.SAXException;
42  import org.xml.sax.helpers.DefaultHandler;
43  
44  /**
45   * <p>A base class to support SAX-based validation in JSTL.</p>
46   * 
47   * @author Shawn Bayern
48   */
49  public abstract class JstlBaseTLV extends TagLibraryValidator {
50  
51      //*********************************************************************
52      // Implementation Overview
53  
54      /*
55       * We essentially just run the page through a SAX parser, handling
56       * the callbacks that interest us.  The SAX parser is supplied by
57       * subclasses using the protected getHandler() method.
58       */
59  
60      protected abstract DefaultHandler getHandler();
61  
62  
63      //*********************************************************************
64      // Constants
65  
66      // parameter names
67      private final String EXP_ATT_PARAM = "expressionAttributes";
68  
69      // attributes
70      protected static final String VAR = "var";
71      protected static final String SCOPE = "scope";  
72  
73      //scopes
74      protected static final String PAGE_SCOPE = "page";        
75      protected static final String REQUEST_SCOPE = "request";  
76      protected static final String SESSION_SCOPE = "session";  
77      protected static final String APPLICATION_SCOPE = "application";
78  
79      // Relevant URIs
80      protected final String JSP = "http://java.sun.com/JSP/Page"; 
81      
82      // types of sub-classes - used on method validate()
83      private   static final int TYPE_UNDEFINED = 0;
84      protected static final int TYPE_CORE = 1;
85      protected static final int TYPE_FMT = 2;
86      protected static final int TYPE_SQL = 3;
87      protected static final int TYPE_XML = 4;
88  
89      // which tlv is being validated
90      private int tlvType = TYPE_UNDEFINED;
91  
92      //*********************************************************************
93      // Validation and configuration state (protected)
94  
95      protected String uri;      // our taglib's uri (as passed by JSP container on XML View)
96      protected String prefix;      // our taglib's prefix
97      protected Vector messageVector;    // temporary error messages
98      protected Map config;      // configuration (Map of Sets)
99      protected boolean failed;      // have we failed >0 times?
100     protected String lastElementId;    // the last element we've seen
101 
102     //*********************************************************************
103     // Constructor and lifecycle management
104 
105     public JstlBaseTLV() {
106   super();
107   init();
108     }
109 
110     private void init() {
111   messageVector = null;
112   prefix = null;
113   config = null;
114     }
115 
116     public void release() {
117   super.release();
118   init();
119     }
120     
121 
122     //*********************************************************************
123     // Validation entry point - this method is called by the sub-classes to 
124     // do the validation.
125 
126     public synchronized ValidationMessage[] validate(
127       int type, String prefix, String uri, PageData page) {
128   try {
129       this.tlvType = type;
130       this.uri = uri;
131       // initialize
132       messageVector = new Vector();
133 
134       // save the prefix
135       this.prefix = prefix;
136 
137       // parse parameters if necessary
138       try {
139     if (config == null)
140         configure((String) getInitParameters().get(EXP_ATT_PARAM));
141       } catch (NoSuchElementException ex) {
142     // parsing error
143           return vmFromString(
144         Resources.getMessage("TLV_PARAMETER_ERROR",
145       EXP_ATT_PARAM));
146       }
147 
148       // get a handler
149       DefaultHandler h = getHandler();
150 
151       // parse the page
152       SAXParserFactory f = SAXParserFactory.newInstance();
153       f.setValidating(false);
154       f.setNamespaceAware(true);
155       SAXParser p = f.newSAXParser();
156       p.parse(page.getInputStream(), h);
157 
158       if (messageVector.size() == 0)
159     return null;
160       else
161     return vmFromVector(messageVector);
162 
163   } catch (SAXException ex) {
164       return vmFromString(ex.toString());
165   } catch (ParserConfigurationException ex) {
166       return vmFromString(ex.toString());
167   } catch (IOException ex) {
168       return vmFromString(ex.toString());
169   }
170     }
171 
172     //*********************************************************************
173     // Protected utility functions
174 
175     // delegate validation to the appropriate expression language
176     protected String validateExpression(
177       String elem, String att, String expr) {
178 
179   // let's just use the cache kept by the ExpressionEvaluatorManager
180   ExpressionEvaluator current;
181   try {
182       current =
183           ExpressionEvaluatorManager.getEvaluatorByName(
184                   ExpressionEvaluatorManager.EVALUATOR_CLASS);
185   } catch (JspException ex) {
186       // (using JspException here feels ugly, but it's what EEM uses)
187       return ex.getMessage();
188   }
189   
190   String response = current.validate(att, expr);
191   if (response == null)
192       return response;
193   else
194       return "tag = '" + elem + "' / attribute = '" + att + "': "
195     + response;
196     }
197 
198     // utility methods to help us match elements in our tagset
199     protected boolean isTag(String tagUri,
200           String tagLn,
201           String matchUri,
202           String matchLn) {
203   if (tagUri == null
204           || tagLn == null
205     || matchUri == null
206     || matchLn == null)
207       return false;
208         // match beginning of URI since some suffix *_rt tags can
209         // be nested in EL enabled tags as defined by the spec
210         if (tagUri.length() > matchUri.length()) {
211             return (tagUri.startsWith(matchUri) && tagLn.equals(matchLn));
212         } else {
213             return (matchUri.startsWith(tagUri) && tagLn.equals(matchLn));
214         }
215     }
216 
217     protected boolean isJspTag(String tagUri, String tagLn, String target) {
218         return isTag(tagUri, tagLn, JSP, target);
219     }
220 
221     private boolean isTag( int type, String tagUri, String tagLn, String target) {
222         return ( this.tlvType == type && isTag(tagUri, tagLn, this.uri, target) );
223     }
224 
225     protected boolean isCoreTag(String tagUri, String tagLn, String target) {
226   return isTag( TYPE_CORE, tagUri, tagLn, target );
227     }
228 
229     protected boolean isFmtTag(String tagUri, String tagLn, String target) {
230   return isTag( TYPE_FMT, tagUri, tagLn, target );
231     }
232 
233     protected boolean isSqlTag(String tagUri, String tagLn, String target) {
234   return isTag( TYPE_SQL, tagUri, tagLn, target );
235     }
236 
237     protected boolean isXmlTag(String tagUri, String tagLn, String target) {
238   return isTag( TYPE_XML, tagUri, tagLn, target );
239     }
240 
241     // utility method to determine if an attribute exists
242     protected boolean hasAttribute(Attributes a, String att) {
243         return (a.getValue(att) != null);
244     }
245 
246     /*
247      * method to assist with failure [ as if it's not easy enough
248      * already :-) ]
249      */
250     protected void fail(String message) {
251         failed = true;
252         messageVector.add(new ValidationMessage(lastElementId, message));
253     }
254 
255     // returns true if the given attribute name is specified, false otherwise
256     protected boolean isSpecified(TagData data, String attributeName) {
257         return (data.getAttribute(attributeName) != null);
258     }
259 
260     // returns true if the 'scope' attribute is valid
261     protected boolean hasNoInvalidScope(Attributes a) {
262         String scope = a.getValue(SCOPE);
263 
264   if ((scope != null)
265       && !scope.equals(PAGE_SCOPE)
266       && !scope.equals(REQUEST_SCOPE)
267       && !scope.equals(SESSION_SCOPE)
268       && !scope.equals(APPLICATION_SCOPE))
269       return false;
270 
271         return true;
272     }
273 
274     // returns true if the 'var' attribute is empty
275     protected boolean hasEmptyVar(Attributes a) {
276   if ("".equals(a.getValue(VAR)))
277       return true;
278   return false;
279     }
280 
281     // returns true if the 'scope' attribute is present without 'var'
282     protected boolean hasDanglingScope(Attributes a) {
283   return (a.getValue(SCOPE) != null && a.getValue(VAR) == null);
284     }
285 
286     // retrieves the local part of a QName
287     protected String getLocalPart(String qname) {
288   int colon = qname.indexOf(":");
289   if (colon == -1)
290       return qname;
291   else
292       return qname.substring(colon + 1);
293     }
294 
295     //*********************************************************************
296     // Miscellaneous utility functions
297 
298     // parses our configuration parameter for element:attribute pairs
299     private void configure(String info) {
300         // construct our configuration map
301   config = new HashMap();
302 
303   // leave the map empty if we have nothing to configure
304   if (info == null)
305       return;
306 
307   // separate parameter into space-separated tokens and store them
308   StringTokenizer st = new StringTokenizer(info);
309   while (st.hasMoreTokens()) {
310       String pair = st.nextToken();
311       StringTokenizer pairTokens = new StringTokenizer(pair, ":");
312       String element = pairTokens.nextToken();
313       String attribute = pairTokens.nextToken();
314       Object atts = config.get(element);
315       if (atts == null) {
316           atts = new HashSet();
317           config.put(element, atts);
318       }
319       ((Set) atts).add(attribute);
320   }
321     }
322 
323     // constructs a ValidationMessage[] from a single String and no ID
324     static ValidationMessage[] vmFromString(String message) {
325   return new ValidationMessage[] {
326       new ValidationMessage(null, message)
327   };
328     }
329 
330     // constructs a ValidationMessage[] from a ValidationMessage Vector
331     static ValidationMessage[] vmFromVector(Vector v) {
332   ValidationMessage[] vm = new ValidationMessage[v.size()];
333   for (int i = 0; i < vm.length; i++)
334      vm[i] = (ValidationMessage) v.get(i);
335   return vm;
336     }
337 }