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.IOException; 27 28 import javax.servlet.jsp.JspContext; 29 import javax.servlet.jsp.JspException; 30 31 /** 32 * A base class for defining tag handlers implementing SimpleTag. 33 * <p> 34 * The SimpleTagSupport class is a utility class intended to be used 35 * as the base class for new simple tag handlers. The SimpleTagSupport 36 * class implements the SimpleTag interface and adds additional 37 * convenience methods including getter methods for the properties in 38 * SimpleTag. 39 * 40 * @since 2.0 41 */ 42 public class SimpleTagSupport 43 implements SimpleTag 44 { 45 /** Reference to the enclosing tag. */ 46 private JspTag parentTag; 47 48 /** The JSP context for the upcoming tag invocation. */ 49 private JspContext jspContext; 50 51 /** The body of the tag. */ 52 private JspFragment jspBody; 53 54 /** 55 * Sole constructor. (For invocation by subclass constructors, 56 * typically implicit.) 57 */ 58 public SimpleTagSupport() { 59 } 60 61 /** 62 * Default processing of the tag does nothing. 63 * 64 * @throws JspException Subclasses can throw JspException to indicate 65 * an error occurred while processing this tag. 66 * @throws javax.servlet.jsp.SkipPageException If the page that 67 * (either directly or indirectly) invoked this tag is to 68 * cease evaluation. A Simple Tag EventHandler generated from a 69 * tag file must throw this exception if an invoked Classic 70 * Tag EventHandler returned SKIP_PAGE or if an invoked Simple 71 * Tag EventHandler threw SkipPageException or if an invoked Jsp Fragment 72 * threw a SkipPageException. 73 * @throws IOException Subclasses can throw IOException if there was 74 * an error writing to the output stream 75 * @see SimpleTag#doTag() 76 */ 77 public void doTag() 78 throws JspException, IOException 79 { 80 } 81 82 /** 83 * Sets the parent of this tag, for collaboration purposes. 84 * <p> 85 * The container invokes this method only if this tag invocation is 86 * nested within another tag invocation. 87 * 88 * @param parent the tag that encloses this tag 89 */ 90 public void setParent( JspTag parent ) { 91 this.parentTag = parent; 92 } 93 94 /** 95 * Returns the parent of this tag, for collaboration purposes. 96 * 97 * @return the parent of this tag 98 */ 99 public JspTag getParent() { 100 return this.parentTag; 101 } 102 103 /** 104 * Stores the provided JSP context in the private jspContext field. 105 * Subclasses can access the <code>JspContext</code> via 106 * <code>getJspContext()</code>. 107 * 108 * @param pc the page context for this invocation 109 * @see SimpleTag#setJspContext 110 */ 111 public void setJspContext( JspContext pc ) { 112 this.jspContext = pc; 113 } 114 115 /** 116 * Returns the page context passed in by the container via 117 * setJspContext. 118 * 119 * @return the page context for this invocation 120 */ 121 protected JspContext getJspContext() { 122 return this.jspContext; 123 } 124 125 /** 126 * Stores the provided JspFragment. 127 * 128 * @param jspBody The fragment encapsulating the body of this tag. 129 * If the action element is empty in the page, this method is 130 * not called at all. 131 * @see SimpleTag#setJspBody 132 */ 133 public void setJspBody( JspFragment jspBody ) { 134 this.jspBody = jspBody; 135 } 136 137 /** 138 * Returns the body passed in by the container via setJspBody. 139 * 140 * @return the fragment encapsulating the body of this tag, or 141 * null if the action element is empty in the page. 142 */ 143 protected JspFragment getJspBody() { 144 return this.jspBody; 145 } 146 147 /** 148 * Find the instance of a given class type that is closest to a given 149 * instance. 150 * This method uses the getParent method from the Tag and/or SimpleTag 151 * interfaces. This method is used for coordination among 152 * cooperating tags. 153 * 154 * <p> For every instance of TagAdapter 155 * encountered while traversing the ancestors, the tag handler returned by 156 * <tt>TagAdapter.getAdaptee()</tt> - instead of the TagAdpater itself - 157 * is compared to <tt>klass</tt>. If the tag handler matches, it - and 158 * not its TagAdapter - is returned. 159 * 160 * <p> 161 * The current version of the specification only provides one formal 162 * way of indicating the observable type of a tag handler: its 163 * tag handler implementation class, described in the tag-class 164 * subelement of the tag element. This is extended in an 165 * informal manner by allowing the tag library author to 166 * indicate in the description subelement an observable type. 167 * The type should be a subtype of the tag handler implementation 168 * class or void. 169 * This addititional constraint can be exploited by a 170 * specialized container that knows about that specific tag library, 171 * as in the case of the JSP standard tag library. 172 * 173 * <p> 174 * When a tag library author provides information on the 175 * observable type of a tag handler, client programmatic code 176 * should adhere to that constraint. Specifically, the Class 177 * passed to findAncestorWithClass should be a subtype of the 178 * observable type. 179 * 180 * 181 * @param from The instance from where to start looking. 182 * @param klass The subclass of JspTag or interface to be matched 183 * @return the nearest ancestor that implements the interface 184 * or is an instance of the class specified 185 */ 186 public static final JspTag findAncestorWithClass( 187 JspTag from, Class klass) 188 { 189 boolean isInterface = false; 190 191 if (from == null || klass == null 192 || (!JspTag.class.isAssignableFrom(klass) 193 && !(isInterface = klass.isInterface()))) { 194 return null; 195 } 196 197 for (;;) { 198 JspTag parent = null; 199 if( from instanceof SimpleTag ) { 200 parent = ((SimpleTag)from).getParent(); 201 } 202 else if( from instanceof Tag ) { 203 parent = ((Tag)from).getParent(); 204 } 205 if (parent == null) { 206 return null; 207 } 208 209 if (parent instanceof TagAdapter) { 210 parent = ((TagAdapter) parent).getAdaptee(); 211 } 212 213 if ((isInterface && klass.isInstance(parent)) 214 || klass.isAssignableFrom(parent.getClass())) { 215 return parent; 216 } 217 218 from = parent; 219 } 220 } 221 }