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