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 */
019package org.apache.wiki.tags;
020
021import jakarta.servlet.jsp.tagext.BodyContent;
022import jakarta.servlet.jsp.tagext.BodyTagSupport;
023import jakarta.servlet.jsp.tagext.Tag;
024import java.util.HashSet;
025import java.util.Set;
026
027/**
028 * ParamTag submits name-value pairs to the first enclosing 
029 * ParamHandler instance. Name and value are strings, and can
030 * be given as tag attributes, or alternatively the value can be 
031 * given as the body contents of this tag. 
032 * <p>
033 * The name-value pair is passed to the closest containing 
034 * ancestor tag that implements ParamHandler. 
035 */
036public class ParamTag 
037    extends BodyTagSupport
038{
039
040    private static final long serialVersionUID = -4671059568218551633L;
041    private String m_name;
042    private String m_value;
043    
044    /**
045     *  {@inheritDoc}
046     */
047    @Override
048    public void release() 
049    {
050        m_name = m_value = null;
051    }
052    
053    /**
054     *  Set the name of the parameter to transfer.
055     *  
056     *  @param s The name.
057     */
058    public void setName(final String s )
059    {
060        m_name = s;
061    }
062    
063    /**
064     *  Set the value of the parameter to transfer.
065     *  
066     *  @param s The value.
067     */
068    public void setValue(final String s )
069    {
070        m_value = s;
071    }
072    
073    /**
074     *  {@inheritDoc}
075     */
076    @Override
077    public int doEndTag()
078    {
079        // Start with the direct parent of this tag
080        Tag t = getParent();
081        final Set<Tag> visited = new HashSet<>();
082
083        // Keep moving up the tree until we find a parent that is a ParamHandler,
084        // or until we run out of parents. This prevents an infinite loop in case
085        // the parent of this tag is not a ParamHandler.
086        while (t != null && !(t instanceof ParamHandler)) {
087            if (!visited.add(t)) {
088                break; // We've seen this tag before, so break out of the loop
089            }
090            t = t.getParent();
091        }
092
093        if( t != null )
094        {
095            String val = m_value;
096            if( val == null )
097            {
098                final BodyContent bc = getBodyContent();
099                if( bc != null )
100                {
101                    val = bc.getString();
102                }
103            }
104            if( val != null )
105            {
106                ((ParamHandler)t).setContainedParameter( m_name, val );
107            }
108        }
109        return EVAL_PAGE;
110    }
111}