001 /** 002 * 003 * Copyright 2003-2004 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 // 019 // This source code implements specifications defined by the Java 020 // Community Process. In order to remain compliant with the specification 021 // DO NOT add / change / or delete method signatures! 022 // 023 024 package javax.servlet.jsp.tagext; 025 026 import java.io.Serializable; 027 import java.util.Enumeration; 028 import java.util.Hashtable; 029 030 import javax.servlet.jsp.JspException; 031 import javax.servlet.jsp.PageContext; 032 033 /** 034 * A base class for defining new tag handlers implementing Tag. 035 * 036 * <p> The TagSupport class is a utility class intended to be used as 037 * the base class for new tag handlers. The TagSupport class 038 * implements the Tag and IterationTag interfaces and adds additional 039 * convenience methods including getter methods for the properties in 040 * Tag. TagSupport has one static method that is included to 041 * facilitate coordination among cooperating tags. 042 * 043 * <p> Many tag handlers will extend TagSupport and only redefine a 044 * few methods. 045 */ 046 047 public class TagSupport implements IterationTag, Serializable { 048 049 /** 050 * Find the instance of a given class type that is closest to a given 051 * instance. 052 * This method uses the getParent method from the Tag 053 * interface. 054 * This method is used for coordination among cooperating tags. 055 * 056 * <p> 057 * The current version of the specification only provides one formal 058 * way of indicating the observable type of a tag handler: its 059 * tag handler implementation class, described in the tag-class 060 * subelement of the tag element. This is extended in an 061 * informal manner by allowing the tag library author to 062 * indicate in the description subelement an observable type. 063 * The type should be a subtype of the tag handler implementation 064 * class or void. 065 * This addititional constraint can be exploited by a 066 * specialized container that knows about that specific tag library, 067 * as in the case of the JSP standard tag library. 068 * 069 * <p> 070 * When a tag library author provides information on the 071 * observable type of a tag handler, client programmatic code 072 * should adhere to that constraint. Specifically, the Class 073 * passed to findAncestorWithClass should be a subtype of the 074 * observable type. 075 * 076 * 077 * @param from The instance from where to start looking. 078 * @param klass The subclass of Tag or interface to be matched 079 * @return the nearest ancestor that implements the interface 080 * or is an instance of the class specified 081 */ 082 083 public static final Tag findAncestorWithClass(Tag from, Class klass) { 084 boolean isInterface = false; 085 086 if (from == null || 087 klass == null || 088 (!Tag.class.isAssignableFrom(klass) && 089 !(isInterface = klass.isInterface()))) { 090 return null; 091 } 092 093 for (;;) { 094 Tag tag = from.getParent(); 095 096 if (tag == null) { 097 return null; 098 } 099 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