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