001    /*
002    * Licensed to the Apache Software Foundation (ASF) under one or more
003    * contributor license agreements.  See the NOTICE file distributed with
004    * this work for additional information regarding copyright ownership.
005    * The ASF licenses this file to You under the Apache License, Version 2.0
006    * (the "License"); you may not use this file except in compliance with
007    * the License.  You may obtain a copy of the License at
008    *
009    *     http://www.apache.org/licenses/LICENSE-2.0
010    *
011    * Unless required by applicable law or agreed to in writing, software
012    * distributed under the License is distributed on an "AS IS" BASIS,
013    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014    * See the License for the specific language governing permissions and
015    * limitations under the License.
016    */
017     
018    package javax.servlet.jsp.tagext;
019    
020    import javax.servlet.jsp.*;
021    
022    
023    /**
024     * Wraps any SimpleTag and exposes it using a Tag interface.  This is used
025     * to allow collaboration between classic Tag handlers and SimpleTag
026     * handlers.
027     * <p>
028     * Because SimpleTag does not extend Tag, and because Tag.setParent()
029     * only accepts a Tag instance, a classic tag handler (one
030     * that implements Tag) cannot have a SimpleTag as its parent.  To remedy
031     * this, a TagAdapter is created to wrap the SimpleTag parent, and the
032     * adapter is passed to setParent() instead.  A classic Tag Handler can
033     * call getAdaptee() to retrieve the encapsulated SimpleTag instance.
034     *
035     * @since 2.0
036     */
037    public class TagAdapter 
038        implements Tag
039    {
040        /** The simple tag that's being adapted. */
041        private SimpleTag simpleTagAdaptee;
042    
043        /** The parent, of this tag, converted (if necessary) to be of type Tag. */
044        private Tag parent;
045    
046        // Flag indicating whether we have already determined the parent
047        private boolean parentDetermined;
048    
049        /**
050         * Creates a new TagAdapter that wraps the given SimpleTag and 
051         * returns the parent tag when getParent() is called.
052         *
053         * @param adaptee The SimpleTag being adapted as a Tag.
054         */
055        public TagAdapter( SimpleTag adaptee ) {
056            if( adaptee == null ) {
057                // Cannot wrap a null adaptee.
058                throw new IllegalArgumentException();
059            }
060            this.simpleTagAdaptee = adaptee;
061        }
062        
063        /**
064         * Must not be called.
065         *
066         * @param pc ignored.
067         * @throws UnsupportedOperationException Must not be called
068         */
069        public void setPageContext(PageContext pc) {
070            throw new UnsupportedOperationException( 
071                "Illegal to invoke setPageContext() on TagAdapter wrapper" );
072        }
073    
074    
075        /**
076         * Must not be called.  The parent of this tag is always 
077         * getAdaptee().getParent().
078         *
079         * @param parentTag ignored.
080         * @throws UnsupportedOperationException Must not be called.
081         */
082        public void setParent( Tag parentTag ) {
083            throw new UnsupportedOperationException( 
084                "Illegal to invoke setParent() on TagAdapter wrapper" );
085        }
086    
087    
088        /**
089         * Returns the parent of this tag, which is always
090         * getAdaptee().getParent().  
091         *
092         * This will either be the enclosing Tag (if getAdaptee().getParent()
093         * implements Tag), or an adapter to the enclosing Tag (if 
094         * getAdaptee().getParent() does not implement Tag).
095         *
096         * @return The parent of the tag being adapted.
097         */
098        public Tag getParent() {
099            if (!parentDetermined) {
100                JspTag adapteeParent = simpleTagAdaptee.getParent();
101                if (adapteeParent != null) {
102                    if (adapteeParent instanceof Tag) {
103                        this.parent = (Tag) adapteeParent;
104                    } else {
105                        // Must be SimpleTag - no other types defined.
106                        this.parent = new TagAdapter((SimpleTag) adapteeParent);
107                    }
108                }
109                parentDetermined = true;
110            }
111    
112            return this.parent;
113        }
114        
115        /**
116         * Gets the tag that is being adapted to the Tag interface.
117         * This should be an instance of SimpleTag in JSP 2.0, but room
118         * is left for other kinds of tags in future spec versions.
119         *
120         * @return the tag that is being adapted
121         */
122        public JspTag getAdaptee() {
123            return this.simpleTagAdaptee;
124        }
125    
126        /**
127         * Must not be called.
128         *
129         * @return always throws UnsupportedOperationException
130         * @throws UnsupportedOperationException Must not be called
131         * @throws JspException never thrown
132         */
133        public int doStartTag() throws JspException {
134            throw new UnsupportedOperationException( 
135                "Illegal to invoke doStartTag() on TagAdapter wrapper" );
136        }
137     
138        /**
139         * Must not be called.
140         *
141         * @return always throws UnsupportedOperationException
142         * @throws UnsupportedOperationException Must not be called
143         * @throws JspException never thrown
144         */
145        public int doEndTag() throws JspException {
146            throw new UnsupportedOperationException( 
147                "Illegal to invoke doEndTag() on TagAdapter wrapper" );
148        }
149    
150        /**
151         * Must not be called.
152         *
153         * @throws UnsupportedOperationException Must not be called
154         */
155        public void release() {
156            throw new UnsupportedOperationException( 
157                "Illegal to invoke release() on TagAdapter wrapper" );
158        }
159    }