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