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