| /* |
| * Copyright 2004 The Apache Software Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package javax.servlet.jsp.tagext; |
| |
| import javax.servlet.jsp.JspContext; |
| import javax.servlet.jsp.JspException; |
| import java.io.IOException; |
| |
| /** |
| * A base class for defining tag handlers implementing SimpleTag. |
| * <p> |
| * The SimpleTagSupport class is a utility class intended to be used |
| * as the base class for new simple tag handlers. The SimpleTagSupport |
| * class implements the SimpleTag interface and adds additional |
| * convenience methods including getter methods for the properties in |
| * SimpleTag. |
| * |
| * @since 2.0 |
| */ |
| public class SimpleTagSupport |
| implements SimpleTag |
| { |
| /** Reference to the enclosing tag. */ |
| private JspTag parentTag; |
| |
| /** The JSP context for the upcoming tag invocation. */ |
| private JspContext jspContext; |
| |
| /** The body of the tag. */ |
| private JspFragment jspBody; |
| |
| /** |
| * Sole constructor. (For invocation by subclass constructors, |
| * typically implicit.) |
| */ |
| public SimpleTagSupport() { |
| } |
| |
| /** |
| * Default processing of the tag does nothing. |
| * |
| * @throws JspException Subclasses can throw JspException to indicate |
| * an error occurred while processing this tag. |
| * @throws javax.servlet.jsp.SkipPageException If the page that |
| * (either directly or indirectly) invoked this tag is to |
| * cease evaluation. A Simple Tag Handler generated from a |
| * tag file must throw this exception if an invoked Classic |
| * Tag Handler returned SKIP_PAGE or if an invoked Simple |
| * Tag Handler threw SkipPageException or if an invoked Jsp Fragment |
| * threw a SkipPageException. |
| * @throws IOException Subclasses can throw IOException if there was |
| * an error writing to the output stream |
| * @see SimpleTag#doTag() |
| */ |
| public void doTag() |
| throws JspException, IOException |
| { |
| } |
| |
| /** |
| * Sets the parent of this tag, for collaboration purposes. |
| * <p> |
| * The container invokes this method only if this tag invocation is |
| * nested within another tag invocation. |
| * |
| * @param parent the tag that encloses this tag |
| */ |
| public void setParent( JspTag parent ) { |
| this.parentTag = parent; |
| } |
| |
| /** |
| * Returns the parent of this tag, for collaboration purposes. |
| * |
| * @return the parent of this tag |
| */ |
| public JspTag getParent() { |
| return this.parentTag; |
| } |
| |
| /** |
| * Stores the provided JSP context in the private jspContext field. |
| * Subclasses can access the <code>JspContext</code> via |
| * <code>getJspContext()</code>. |
| * |
| * @param pc the page context for this invocation |
| * @see SimpleTag#setJspContext |
| */ |
| public void setJspContext( JspContext pc ) { |
| this.jspContext = pc; |
| } |
| |
| /** |
| * Returns the page context passed in by the container via |
| * setJspContext. |
| * |
| * @return the page context for this invocation |
| */ |
| protected JspContext getJspContext() { |
| return this.jspContext; |
| } |
| |
| /** |
| * Stores the provided JspFragment. |
| * |
| * @param jspBody The fragment encapsulating the body of this tag. |
| * If the action element is empty in the page, this method is |
| * not called at all. |
| * @see SimpleTag#setJspBody |
| */ |
| public void setJspBody( JspFragment jspBody ) { |
| this.jspBody = jspBody; |
| } |
| |
| /** |
| * Returns the body passed in by the container via setJspBody. |
| * |
| * @return the fragment encapsulating the body of this tag, or |
| * null if the action element is empty in the page. |
| */ |
| protected JspFragment getJspBody() { |
| return this.jspBody; |
| } |
| |
| /** |
| * Find the instance of a given class type that is closest to a given |
| * instance. |
| * This method uses the getParent method from the Tag and/or SimpleTag |
| * interfaces. This method is used for coordination among |
| * cooperating tags. |
| * |
| * <p> For every instance of TagAdapter |
| * encountered while traversing the ancestors, the tag handler returned by |
| * <tt>TagAdapter.getAdaptee()</tt> - instead of the TagAdpater itself - |
| * is compared to <tt>klass</tt>. If the tag handler matches, it - and |
| * not its TagAdapter - is returned. |
| * |
| * <p> |
| * The current version of the specification only provides one formal |
| * way of indicating the observable type of a tag handler: its |
| * tag handler implementation class, described in the tag-class |
| * subelement of the tag element. This is extended in an |
| * informal manner by allowing the tag library author to |
| * indicate in the description subelement an observable type. |
| * The type should be a subtype of the tag handler implementation |
| * class or void. |
| * This addititional constraint can be exploited by a |
| * specialized container that knows about that specific tag library, |
| * as in the case of the JSP standard tag library. |
| * |
| * <p> |
| * When a tag library author provides information on the |
| * observable type of a tag handler, client programmatic code |
| * should adhere to that constraint. Specifically, the Class |
| * passed to findAncestorWithClass should be a subtype of the |
| * observable type. |
| * |
| * |
| * @param from The instance from where to start looking. |
| * @param klass The subclass of JspTag or interface to be matched |
| * @return the nearest ancestor that implements the interface |
| * or is an instance of the class specified |
| */ |
| public static final JspTag findAncestorWithClass( |
| JspTag from, Class klass) |
| { |
| boolean isInterface = false; |
| |
| if (from == null || klass == null |
| || (!JspTag.class.isAssignableFrom(klass) |
| && !(isInterface = klass.isInterface()))) { |
| return null; |
| } |
| |
| for (;;) { |
| JspTag parent = null; |
| if( from instanceof SimpleTag ) { |
| parent = ((SimpleTag)from).getParent(); |
| } |
| else if( from instanceof Tag ) { |
| parent = ((Tag)from).getParent(); |
| } |
| if (parent == null) { |
| return null; |
| } |
| |
| if (parent instanceof TagAdapter) { |
| parent = ((TagAdapter) parent).getAdaptee(); |
| } |
| |
| if ((isInterface && klass.isInstance(parent)) |
| || klass.isAssignableFrom(parent.getClass())) { |
| return parent; |
| } |
| |
| from = parent; |
| } |
| } |
| } |