001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 // 021 // This source code implements specifications defined by the Java 022 // Community Process. In order to remain compliant with the specification 023 // DO NOT add / change / or delete method signatures! 024 // 025 026 package javax.servlet.jsp.tagext; 027 028 import java.io.Serializable; 029 import java.util.Enumeration; 030 import java.util.Hashtable; 031 032 import javax.servlet.jsp.JspException; 033 import javax.servlet.jsp.PageContext; 034 035 /** 036 * A base class for defining new tag handlers implementing Tag. 037 * 038 * <p> The TagSupport class is a utility class intended to be used as 039 * the base class for new tag handlers. The TagSupport class 040 * implements the Tag and IterationTag interfaces and adds additional 041 * convenience methods including getter methods for the properties in 042 * Tag. TagSupport has one static method that is included to 043 * facilitate coordination among cooperating tags. 044 * 045 * <p> Many tag handlers will extend TagSupport and only redefine a 046 * few methods. 047 */ 048 049 public class TagSupport implements IterationTag, Serializable { 050 051 /** 052 * Find the instance of a given class type that is closest to a given 053 * instance. 054 * This method uses the getParent method from the Tag 055 * interface. 056 * This method is used for coordination among cooperating tags. 057 * 058 * <p> 059 * The current version of the specification only provides one formal 060 * way of indicating the observable type of a tag handler: its 061 * tag handler implementation class, described in the tag-class 062 * subelement of the tag element. This is extended in an 063 * informal manner by allowing the tag library author to 064 * indicate in the description subelement an observable type. 065 * The type should be a subtype of the tag handler implementation 066 * class or void. 067 * This addititional constraint can be exploited by a 068 * specialized container that knows about that specific tag library, 069 * as in the case of the JSP standard tag library. 070 * 071 * <p> 072 * When a tag library author provides information on the 073 * observable type of a tag handler, client programmatic code 074 * should adhere to that constraint. Specifically, the Class 075 * passed to findAncestorWithClass should be a subtype of the 076 * observable type. 077 * 078 * 079 * @param from The instance from where to start looking. 080 * @param klass The subclass of Tag or interface to be matched 081 * @return the nearest ancestor that implements the interface 082 * or is an instance of the class specified 083 */ 084 085 public static final Tag findAncestorWithClass(Tag from, Class klass) { 086 boolean isInterface = false; 087 088 if (from == null || 089 klass == null || 090 (!Tag.class.isAssignableFrom(klass) && 091 !(isInterface = klass.isInterface()))) { 092 return null; 093 } 094 095 for (;;) { 096 Tag tag = from.getParent(); 097 098 if (tag == null) { 099 return null; 100 } 101 102 if ((isInterface && klass.isInstance(tag)) || 103 klass.isAssignableFrom(tag.getClass())) 104 return tag; 105 else 106 from = tag; 107 } 108 } 109 110 /** 111 * Default constructor, all subclasses are required to define only 112 * a public constructor with the same signature, and to call the 113 * superclass constructor. 114 * 115 * This constructor is called by the code generated by the JSP 116 * translator. 117 */ 118 119 public TagSupport() { } 120 121 /** 122 * Default processing of the start tag, returning SKIP_BODY. 123 * 124 * @return SKIP_BODY 125 * @throws JspException if an error occurs while processing this tag 126 * 127 * @see Tag#doStartTag() 128 */ 129 130 public int doStartTag() throws JspException { 131 return SKIP_BODY; 132 } 133 134 /** 135 * Default processing of the end tag returning EVAL_PAGE. 136 * 137 * @return EVAL_PAGE 138 * @throws JspException if an error occurs while processing this tag 139 * 140 * @see Tag#doEndTag() 141 */ 142 143 public int doEndTag() throws JspException { 144 return EVAL_PAGE; 145 } 146 147 148 /** 149 * Default processing for a body. 150 * 151 * @return SKIP_BODY 152 * @throws JspException if an error occurs while processing this tag 153 * 154 * @see IterationTag#doAfterBody() 155 */ 156 157 public int doAfterBody() throws JspException { 158 return SKIP_BODY; 159 } 160 161 // Actions related to body evaluation 162 163 164 /** 165 * Release state. 166 * 167 * @see Tag#release() 168 */ 169 170 public void release() { 171 parent = null; 172 id = null; 173 if( values != null ) { 174 values.clear(); 175 } 176 values = null; 177 } 178 179 /** 180 * Set the nesting tag of this tag. 181 * 182 * @param t The parent Tag. 183 * @see Tag#setParent(Tag) 184 */ 185 186 public void setParent(Tag t) { 187 parent = t; 188 } 189 190 /** 191 * The Tag instance most closely enclosing this tag instance. 192 * @see Tag#getParent() 193 * 194 * @return the parent tag instance or null 195 */ 196 197 public Tag getParent() { 198 return parent; 199 } 200 201 /** 202 * Set the id attribute for this tag. 203 * 204 * @param id The String for the id. 205 */ 206 207 public void setId(String id) { 208 this.id = id; 209 } 210 211 /** 212 * The value of the id attribute of this tag; or null. 213 * 214 * @return the value of the id attribute, or null 215 */ 216 217 public String getId() { 218 return id; 219 } 220 221 /** 222 * Set the page context. 223 * 224 * @param pageContext The PageContext. 225 * @see Tag#setPageContext 226 */ 227 228 public void setPageContext(PageContext pageContext) { 229 this.pageContext = pageContext; 230 } 231 232 /** 233 * Associate a value with a String key. 234 * 235 * @param k The key String. 236 * @param o The value to associate. 237 */ 238 239 public void setValue(String k, Object o) { 240 if (values == null) { 241 values = new Hashtable(); 242 } 243 values.put(k, o); 244 } 245 246 /** 247 * Get a the value associated with a key. 248 * 249 * @param k The string key. 250 * @return The value associated with the key, or null. 251 */ 252 253 public Object getValue(String k) { 254 if (values == null) { 255 return null; 256 } else { 257 return values.get(k); 258 } 259 } 260 261 /** 262 * Remove a value associated with a key. 263 * 264 * @param k The string key. 265 */ 266 267 public void removeValue(String k) { 268 if (values != null) { 269 values.remove(k); 270 } 271 } 272 273 /** 274 * Enumerate the keys for the values kept by this tag handler. 275 * 276 * @return An enumeration of all the keys for the values set, 277 * or null or an empty Enumeration if no values have been set. 278 */ 279 280 public Enumeration getValues() { 281 if (values == null) { 282 return null; 283 } 284 return values.keys(); 285 } 286 287 // private fields 288 289 private Tag parent; 290 private Hashtable values; 291 /** 292 * The value of the id attribute of this tag; or null. 293 */ 294 protected String id; 295 296 // protected fields 297 298 /** 299 * The PageContext. 300 */ 301 protected PageContext pageContext; 302 } 303