View Javadoc

1   /**
2    *
3    * Copyright 2003-2004 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  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  //
19  // This source code implements specifications defined by the Java
20  // Community Process. In order to remain compliant with the specification
21  // DO NOT add / change / or delete method signatures!
22  //
23  
24  package javax.servlet.jsp.tagext;
25  
26  import java.io.Serializable;
27  import java.util.Enumeration;
28  import java.util.Hashtable;
29  
30  import javax.servlet.jsp.JspException;
31  import javax.servlet.jsp.PageContext;
32  
33  /**
34   * A base class for defining new tag handlers implementing Tag.
35   *
36   * <p> The TagSupport class is a utility class intended to be used as
37   * the base class for new tag handlers.  The TagSupport class
38   * implements the Tag and IterationTag interfaces and adds additional
39   * convenience methods including getter methods for the properties in
40   * Tag.  TagSupport has one static method that is included to
41   * facilitate coordination among cooperating tags.
42   *
43   * <p> Many tag handlers will extend TagSupport and only redefine a
44   * few methods. 
45   */
46  
47  public class TagSupport implements IterationTag, Serializable {
48  
49      /**
50       * Find the instance of a given class type that is closest to a given
51       * instance.
52       * This method uses the getParent method from the Tag
53       * interface.
54       * This method is used for coordination among cooperating tags.
55       *
56       * <p>
57       * The current version of the specification only provides one formal
58       * way of indicating the observable type of a tag handler: its
59       * tag handler implementation class, described in the tag-class
60       * subelement of the tag element.  This is extended in an
61       * informal manner by allowing the tag library author to
62       * indicate in the description subelement an observable type.
63       * The type should be a subtype of the tag handler implementation
64       * class or void.
65       * This addititional constraint can be exploited by a
66       * specialized container that knows about that specific tag library,
67       * as in the case of the JSP standard tag library.
68       *
69       * <p>
70       * When a tag library author provides information on the
71       * observable type of a tag handler, client programmatic code
72       * should adhere to that constraint.  Specifically, the Class
73       * passed to findAncestorWithClass should be a subtype of the
74       * observable type.
75       * 
76       *
77       * @param from The instance from where to start looking.
78       * @param klass The subclass of Tag or interface to be matched
79       * @return the nearest ancestor that implements the interface
80       * or is an instance of the class specified
81       */
82  
83      public static final Tag findAncestorWithClass(Tag from, Class klass) {
84  	boolean isInterface = false;
85  
86  	if (from == null ||
87  	    klass == null ||
88  	    (!Tag.class.isAssignableFrom(klass) &&
89  	     !(isInterface = klass.isInterface()))) {
90  	    return null;
91  	}
92  
93  	for (;;) {
94  	    Tag tag = from.getParent();
95  
96  	    if (tag == null) {
97  		return null;
98  	    }
99  
100 	    if ((isInterface && klass.isInstance(tag)) ||
101 	        klass.isAssignableFrom(tag.getClass()))
102 		return tag;
103 	    else
104 		from = tag;
105 	}
106     }
107 
108     /**
109      * Default constructor, all subclasses are required to define only
110      * a public constructor with the same signature, and to call the
111      * superclass constructor.
112      *
113      * This constructor is called by the code generated by the JSP
114      * translator.
115      */
116 
117     public TagSupport() { }
118 
119     /**
120      * Default processing of the start tag, returning SKIP_BODY.
121      *
122      * @return SKIP_BODY
123      * @throws JspException if an error occurs while processing this tag
124      *
125      * @see Tag#doStartTag()
126      */
127  
128     public int doStartTag() throws JspException {
129         return SKIP_BODY;
130     }
131 
132     /**
133      * Default processing of the end tag returning EVAL_PAGE.
134      *
135      * @return EVAL_PAGE
136      * @throws JspException if an error occurs while processing this tag
137      *
138      * @see Tag#doEndTag()
139      */
140 
141     public int doEndTag() throws JspException {
142 	return EVAL_PAGE;
143     }
144 
145 
146     /**
147      * Default processing for a body.
148      *
149      * @return SKIP_BODY
150      * @throws JspException if an error occurs while processing this tag
151      *
152      * @see IterationTag#doAfterBody()
153      */
154     
155     public int doAfterBody() throws JspException {
156 	return SKIP_BODY;
157     }
158 
159     // Actions related to body evaluation
160 
161 
162     /**
163      * Release state.
164      *
165      * @see Tag#release()
166      */
167 
168     public void release() {
169 	parent = null;
170 	id = null;
171 	if( values != null ) {
172 	    values.clear();
173 	}
174 	values = null;
175     }
176 
177     /**
178      * Set the nesting tag of this tag.
179      *
180      * @param t The parent Tag.
181      * @see Tag#setParent(Tag)
182      */
183 
184     public void setParent(Tag t) {
185 	parent = t;
186     }
187 
188     /**
189      * The Tag instance most closely enclosing this tag instance.
190      * @see Tag#getParent()
191      *
192      * @return the parent tag instance or null
193      */
194 
195     public Tag getParent() {
196 	return parent;
197     }
198 
199     /**
200      * Set the id attribute for this tag.
201      *
202      * @param id The String for the id.
203      */
204 
205     public void setId(String id) {
206 	this.id = id;
207     }
208 
209     /**
210      * The value of the id attribute of this tag; or null.
211      *
212      * @return the value of the id attribute, or null
213      */
214     
215     public String getId() {
216 	return id;
217     }
218 
219     /**
220      * Set the page context.
221      *
222      * @param pageContext The PageContext.
223      * @see Tag#setPageContext
224      */
225 
226     public void setPageContext(PageContext pageContext) {
227 	this.pageContext = pageContext;
228     }
229 
230     /**
231      * Associate a value with a String key.
232      *
233      * @param k The key String.
234      * @param o The value to associate.
235      */
236 
237     public void setValue(String k, Object o) {
238 	if (values == null) {
239 	    values = new Hashtable();
240 	}
241 	values.put(k, o);
242     }
243 
244     /**
245      * Get a the value associated with a key.
246      *
247      * @param k The string key.
248      * @return The value associated with the key, or null.
249      */
250 
251     public Object getValue(String k) {
252 	if (values == null) {
253 	    return null;
254 	} else {
255 	    return values.get(k);
256 	}
257     }
258 
259     /**
260      * Remove a value associated with a key.
261      *
262      * @param k The string key.
263      */
264 
265     public void removeValue(String k) {
266 	if (values != null) {
267 	    values.remove(k);
268 	}
269     }
270 
271     /**
272      * Enumerate the keys for the values kept by this tag handler.
273      *
274      * @return An enumeration of all the keys for the values set,
275      *     or null or an empty Enumeration if no values have been set.
276      */
277 
278     public Enumeration getValues() {
279 	if (values == null) {
280 	    return null;
281 	}
282 	return values.keys();
283     }
284 
285     // private fields
286 
287     private   Tag         parent;
288     private   Hashtable   values;
289     /**
290      * The value of the id attribute of this tag; or null.
291      */
292     protected String	  id;
293 
294     // protected fields
295 
296     /**
297      * The PageContext.
298      */
299     protected PageContext pageContext;
300 }
301