View Javadoc

    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 }