    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}