1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5 *
6 * Portions Copyright Apache Software Foundation.
7 *
8 * The contents of this file are subject to the terms of either the GNU
9 * General Public License Version 2 only ("GPL") or the Common Development
10 * and Distribution License("CDDL") (collectively, the "License"). You
11 * may not use this file except in compliance with the License. You can obtain
12 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
13 * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
14 * language governing permissions and limitations under the License.
15 *
16 * When distributing the software, include this License Header Notice in each
17 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
18 * Sun designates this particular file as subject to the "Classpath" exception
19 * as provided by Sun in the GPL Version 2 section of the License file that
20 * accompanied this code. If applicable, add the following below the License
21 * Header, with the fields enclosed by brackets [] replaced by your own
22 * identifying information: "Portions Copyrighted [year]
23 * [name of copyright owner]"
24 *
25 * Contributor(s):
26 *
27 * If you wish your version of this file to be governed by only the CDDL or
28 * only the GPL Version 2, indicate your decision by adding "[Contributor]
29 * elects to include this software in this distribution under the [CDDL or GPL
30 * Version 2] license." If you don't indicate a single choice of license, a
31 * recipient has the option to distribute your version of this file under
32 * either the CDDL, the GPL Version 2 or to extend the choice of license to
33 * its licensees as provided above. However, if you add GPL Version 2 code
34 * and therefore, elected the GPL Version 2 license, then the option applies
35 * only if the new code is made subject to such option by the copyright
36 * holder.
37 */
38 package javax.servlet.jsp.tagext;
39
40 import javax.servlet.jsp.JspContext;
41 import javax.servlet.jsp.JspException;
42 import java.io.IOException;
43
44 /**
45 * A base class for defining tag handlers implementing SimpleTag.
46 * <p>
47 * The SimpleTagSupport class is a utility class intended to be used
48 * as the base class for new simple tag handlers. The SimpleTagSupport
49 * class implements the SimpleTag interface and adds additional
50 * convenience methods including getter methods for the properties in
51 * SimpleTag.
52 *
53 * @since 2.0
54 */
55 public class SimpleTagSupport
56 implements SimpleTag
57 {
58 /** Reference to the enclosing tag. */
59 private JspTag parentTag;
60
61 /** The JSP context for the upcoming tag invocation. */
62 private JspContext jspContext;
63
64 /** The body of the tag. */
65 private JspFragment jspBody;
66
67 /**
68 * Sole constructor. (For invocation by subclass constructors,
69 * typically implicit.)
70 */
71 public SimpleTagSupport() {
72 }
73
74 /**
75 * Default processing of the tag does nothing.
76 *
77 * @throws JspException Subclasses can throw JspException to indicate
78 * an error occurred while processing this tag.
79 * @throws javax.servlet.jsp.SkipPageException If the page that
80 * (either directly or indirectly) invoked this tag is to
81 * cease evaluation. A Simple Tag Handler generated from a
82 * tag file must throw this exception if an invoked Classic
83 * Tag Handler returned SKIP_PAGE or if an invoked Simple
84 * Tag Handler threw SkipPageException or if an invoked Jsp Fragment
85 * threw a SkipPageException.
86 * @throws IOException Subclasses can throw IOException if there was
87 * an error writing to the output stream
88 * @see SimpleTag#doTag()
89 */
90 public void doTag()
91 throws JspException, IOException
92 {
93 }
94
95 /**
96 * Sets the parent of this tag, for collaboration purposes.
97 * <p>
98 * The container invokes this method only if this tag invocation is
99 * nested within another tag invocation.
100 *
101 * @param parent the tag that encloses this tag
102 */
103 public void setParent( JspTag parent ) {
104 this.parentTag = parent;
105 }
106
107 /**
108 * Returns the parent of this tag, for collaboration purposes.
109 *
110 * @return the parent of this tag
111 */
112 public JspTag getParent() {
113 return this.parentTag;
114 }
115
116 /**
117 * Stores the provided JSP context in the private jspContext field.
118 * Subclasses can access the <code>JspContext</code> via
119 * <code>getJspContext()</code>.
120 *
121 * @param pc the page context for this invocation
122 * @see SimpleTag#setJspContext
123 */
124 public void setJspContext( JspContext pc ) {
125 this.jspContext = pc;
126 }
127
128 /**
129 * Returns the page context passed in by the container via
130 * setJspContext.
131 *
132 * @return the page context for this invocation
133 */
134 protected JspContext getJspContext() {
135 return this.jspContext;
136 }
137
138 /**
139 * Stores the provided JspFragment.
140 *
141 * @param jspBody The fragment encapsulating the body of this tag.
142 * If the action element is empty in the page, this method is
143 * not called at all.
144 * @see SimpleTag#setJspBody
145 */
146 public void setJspBody( JspFragment jspBody ) {
147 this.jspBody = jspBody;
148 }
149
150 /**
151 * Returns the body passed in by the container via setJspBody.
152 *
153 * @return the fragment encapsulating the body of this tag, or
154 * null if the action element is empty in the page.
155 */
156 protected JspFragment getJspBody() {
157 return this.jspBody;
158 }
159
160 /**
161 * Find the instance of a given class type that is closest to a given
162 * instance.
163 * This method uses the getParent method from the Tag and/or SimpleTag
164 * interfaces. This method is used for coordination among
165 * cooperating tags.
166 *
167 * <p> For every instance of TagAdapter
168 * encountered while traversing the ancestors, the tag handler returned by
169 * <tt>TagAdapter.getAdaptee()</tt> - instead of the TagAdpater itself -
170 * is compared to <tt>klass</tt>. If the tag handler matches, it - and
171 * not its TagAdapter - is returned.
172 *
173 * <p>
174 * The current version of the specification only provides one formal
175 * way of indicating the observable type of a tag handler: its
176 * tag handler implementation class, described in the tag-class
177 * subelement of the tag element. This is extended in an
178 * informal manner by allowing the tag library author to
179 * indicate in the description subelement an observable type.
180 * The type should be a subtype of the tag handler implementation
181 * class or void.
182 * This addititional constraint can be exploited by a
183 * specialized container that knows about that specific tag library,
184 * as in the case of the JSP standard tag library.
185 *
186 * <p>
187 * When a tag library author provides information on the
188 * observable type of a tag handler, client programmatic code
189 * should adhere to that constraint. Specifically, the Class
190 * passed to findAncestorWithClass should be a subtype of the
191 * observable type.
192 *
193 *
194 * @param from The instance from where to start looking.
195 * @param klass The subclass of JspTag or interface to be matched
196 * @return the nearest ancestor that implements the interface
197 * or is an instance of the class specified
198 */
199 public static final JspTag findAncestorWithClass(
200 JspTag from, Class klass)
201 {
202 boolean isInterface = false;
203
204 if (from == null || klass == null
205 || (!JspTag.class.isAssignableFrom(klass)
206 && !(isInterface = klass.isInterface()))) {
207 return null;
208 }
209
210 for (;;) {
211 JspTag parent = null;
212 if( from instanceof SimpleTag ) {
213 parent = ((SimpleTag)from).getParent();
214 }
215 else if( from instanceof Tag ) {
216 parent = ((Tag)from).getParent();
217 }
218 if (parent == null) {
219 return null;
220 }
221
222 if (parent instanceof TagAdapter) {
223 parent = ((TagAdapter) parent).getAdaptee();
224 }
225
226 if ((isInterface && klass.isInstance(parent))
227 || klass.isAssignableFrom(parent.getClass())) {
228 return parent;
229 }
230
231 from = parent;
232 }
233 }
234 }