You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by cr...@apache.org on 2001/02/09 20:33:12 UTC

cvs commit: jakarta-struts/src/share/org/apache/struts/taglib/logic LocalStrings.properties RedirectTag.java

craigmcc    01/02/09 11:33:11

  Modified:    src/doc  struts-html.xml struts-logic.xml
               src/share/org/apache/struts/taglib/logic
                        LocalStrings.properties RedirectTag.java
  Log:
  Enhance the <logic:redirect> tag so that it has the same three options for
  choosing the destination URL that the <html:link> tag has:
  - "href" attribute, used unchanged
  - "forward" attribute, picks context-relative path by logical name
  - "page" attribute, specifies context-relative path starting with "/"
  
  Revision  Changes    Path
  1.7       +3 -2      jakarta-struts/src/doc/struts-html.xml
  
  Index: struts-html.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-struts/src/doc/struts-html.xml,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- struts-html.xml	2001/02/07 23:10:42	1.6
  +++ struts-html.xml	2001/02/09 19:33:10	1.7
  @@ -1409,8 +1409,8 @@
                   image will be taken from the attributes of this tag.</p>
   
                   <p>The base URL for this image is calculated based on
  -                the value specified in <code>src</code> or <code>page</code>.
  -                You <strong>must</strong> specify exactly one of these
  +                the value specified in <code>src</code> or <code>page</code>.
  +                You <strong>must</strong> specify exactly one of these
                   attributes.</p>
   
                   <p>Normally, the <code>src</code> or <code>page</code> that
  @@ -2956,6 +2956,7 @@
   
   	</tag>
   	
  +
   	<tag>
   		
   		<name>reset</name>
  
  
  
  1.6       +216 -22   jakarta-struts/src/doc/struts-logic.xml
  
  Index: struts-logic.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-struts/src/doc/struts-logic.xml,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- struts-logic.xml	2000/12/29 20:36:54	1.5
  +++ struts-logic.xml	2001/02/09 19:33:10	1.6
  @@ -1189,30 +1189,224 @@
     </tag>
   
   
  -  <tag>
  +        <tag>
   
  -    <name>redirect</name>
  -    <summary>
  -    Perform an HTTP redirect to the specified URL.
  -    </summary>
  -    <tagclass>org.apache.struts.taglib.logic.RedirectTag</tagclass>
  -    <bodycontent>empty</bodycontent>
  -    <info>
  -    <p>Performs a <code>HttpServletResponse.sendRedirect()</code> to the
  -    specified URL, after applying URL rewriting as needed.</p>
  -    </info>
  -
  -    <attribute>
  -      <name>href</name>
  -      <required>true</required>
  -      <rtexprvalue>true</rtexprvalue>
  -      <info>
  -      <p>The relative or absolute URL to which the client should be
  -      redirected.</p>
  -      </info>
  -    </attribute>
  +                <name>redirect</name>
  +                <summary>Render an HTTP Redirect</summary>
  +                <tagclass>org.apache.struts.taglib.logic.RedirectTag</tagclass>
  +                <body-content>empty</body-content>
  +                <info>
   
  -  </tag>
  +                <p>Performs an <code>HttpServletResponse.sendRedirect()</code>
  +                call to the hyperlink specified by the attributes to this
  +                tag.  URL rewriting will be applied automatically, to
  +                maintain session state in the absence of cookies.</p>
  +
  +                <p>The base URL for this redirect is calculated based on
  +                which of the following attributes you specify (you must
  +                specify exactly one of them):</p>
  +                <ul>
  +                <li><em>forward</em> - Use the value of this attribute as the
  +                    name of a global <code>ActionForward</code> to be looked
  +                    up, and use the context-relative URI found there.</li>
  +                <li><em>href</em> - Use the value of this attribute unchanged.
  +                    </li>
  +                <li><em>page</em> - Use the value of this attribute as a
  +                    context-relative URI, and generate a server-relative URI
  +                    by including the context path.</li>
  +                </ul>
  +
  +                <p>Normally, the redirect you specify with one of the
  +                attributes described in the previous paragraph will be left
  +                unchanged (other than URL rewriting if necessary).  However,
  +                there are two ways you can append one or more dynamically
  +                defined query parameters to the hyperlink -- specify a single
  +                parameter with the <code>paramId</code> attribute (and its
  +                associated attributes to select the value), or specify the
  +                <code>name</code> (and optional <code>property</code>)
  +                attributes to select a <code>java.util.Map</code> bean that
  +                contains one or more parameter ids and corresponding values.
  +                </p>
  +
  +                <p>To specify a single parameter, use the <code>paramId</code>
  +                attribute to define the name of the request parameter to be
  +                submitted.  To specify the corresponding value, use one of the
  +                following approaches:</p>
  +                <ul>
  +                <li><em>Specify only the <code>paramName</code> attribute</em>
  +                    - The named JSP bean (optionally scoped by the value of the
  +                    <code>paramScope</code> attribute) must identify a value
  +                    that can be converted to a String.</li>
  +                <li><em>Specify both the <code>paramName</code> and
  +                    <code>paramProperty</code> attributes</em> - The specified
  +                    property getter method will be called on the JSP bean
  +                    identified by the <code>paramName</code> (and optional
  +                    <code>paramScope</code>) attributes, in order to select
  +                    a value that can be converted to a String.</li>
  +                </ul>
  +
  +                <p>If you prefer to specify a <code>java.util.Map</code> that
  +                contains all of the request parameters to be added to the
  +                hyperlink, use one of the following techniques:</p>
  +                <ul>
  +                <li><em>Specify only the <code>name</code> attribute</em> -
  +                    The named JSP bean (optionally scoped by the value of
  +                    the <code>scope</code> attribute) must identify a
  +                    <code>java.util.Map</code> containing the parameters.</li>
  +                <li><em>Specify both <code>name</code> and
  +                    <code>property</code> attributes</em> - The specified
  +                    property getter method will be called on the bean
  +                    identified by the <code>name</code> (and optional
  +                    <code>scope</code>) attributes, in order to return the
  +                    <code>java.util.Map</code> containing the parameters.</li>
  +                </ul>
  +
  +                <p>As the <code>Map</code> is processed, the keys are assumed
  +                to be the names of query parameters to be appended to the
  +                hyperlink.  The value associated with each key must be either
  +                a String or a String array representing the parameter value(s).
  +                If a String array is specified, more than one value for the
  +                same query parameter name will be created.</p>
  +                </info>
  +
  +                <attribute>
  +                  <name>forward</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>Logical name of a global <code>ActionForward</code> that
  +                  contains the actual content-relative URI of the destination
  +                  of this redirect.  This URI may be dynamically
  +                  modified by the inclusion of query parameters, as described
  +                  in the tag description.  You <strong>must</strong> specify
  +                  exactly one of the <code>forward</code> attribute, the
  +                  <code>href</code> attribute, the <code>linkName</code>
  +                  attribute, or the <code>page</code> attribute.</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>href</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The URL to which this redirect will transfer control.
  +                  This URL may be dynamically modified
  +                  by the inclusion of query parameters, as described in the
  +                  tag description.  You <strong>must</strong> specify
  +                  exactly one of the <code>forward</code> attribute, the
  +                  <code>href</code> attribute, the <code>linkName</code>
  +                  attribute, or the <code>page</code> attribute.</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>name</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The name of a JSP bean that contains a <code>Map</code>
  +                  representing the query parameters (if <code>property</code>
  +                  is not specified), or a JSP bean whose property getter is
  +                  called to return a <code>Map</code> (if <code>property</code>
  +                  is specified).</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>page</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The context-relative path (beginning with a "/"
  +                  character) to which this hyperlink will transfer control
  +                  if activated.  This hyperlink may be dynamically modified
  +                  by the inclusion of query parameters, as described in the
  +                  tag description.  You <strong>must</strong> specify exactly
  +                  one of the <code>forward</code> attribute, the
  +                  <code>href</code> attribute, the <code>linkName</code>
  +                  attribute, or the <code>page</code> attribute.</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>paramId</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The name of the request parameter that will be dynamically
  +                  added to the generated hyperlink.  The corresponding value is
  +                  defined by the <code>paramName</code> and (optional)
  +                  <code>paramProperty</code> attributes, optionally scoped by
  +                  the <code>paramScope</code> attributel</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>paramName</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The name of a JSP bean that is a String containing the
  +                  value for the request parameter named by <code>paramId</code>
  +                  (if <code>paramProperty</code> is not specified), or a JSP
  +                  bean whose property getter is called to return a String
  +                  (if <code>paramProperty</code> is specified).  The JSP bean
  +                  is constrained to the bean scope specified by the
  +                  <code>paramScope</code> property, if it is specified.</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>paramProperty</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The name of a property of the bean specified by the
  +                  <code>paramName</code> attribute, whose return value must
  +                  be a String containing the value of the request parameter
  +                  (named by the <code>paramId</code> attribute) that will be
  +                  dynamically added to this hyperlink.</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>paramScope</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The scope within which to search for the bean specified
  +                  by the <code>paramName</code> attribute.  If not specified,
  +                  all scopes are searched.</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>property</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The name of a property of the bean specified by the
  +                  <code>name</code> attribute, whose return value must be
  +                  a <code>java.util.Map</code> containing the query parameters
  +                  to be added to the hyperlink.  You <strong>must</strong>
  +                  specify the <code>name</code> attribute if you specify
  +                  this attribute.</p>
  +                  </info>
  +                </attribute>
  +
  +                <attribute>
  +                  <name>scope</name>
  +                  <required>false</required>
  +                  <rtexprvalue>true</rtexprvalue>
  +                  <info>
  +                  <p>The scope within which to search for the bean specified
  +                  by the <code>name</code> attribute.  If not specified, all
  +                  scopes are searched.</p>
  +                  </info>
  +                </attribute>
  +
  +        </tag>
   
   
   </taglib>
  
  
  
  1.3       +1 -0      jakarta-struts/src/share/org/apache/struts/taglib/logic/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/logic/LocalStrings.properties,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LocalStrings.properties	2001/01/16 01:08:18	1.2
  +++ LocalStrings.properties	2001/02/09 19:33:11	1.3
  @@ -13,4 +13,5 @@
   logic.property=Exception accessing property {1} for bean {0}: {2}
   logic.selector=No selector attribute (cookie/header/name/parameter) was specified
   logic.variable=Cannot compare null variable to value {0}
  +redirect.destination=You must specify exactly one of 'forward', 'href', or 'page'
   redirect.redirect=Exception redirecting to {0}: {1}
  
  
  
  1.5       +388 -29   jakarta-struts/src/share/org/apache/struts/taglib/logic/RedirectTag.java
  
  Index: RedirectTag.java
  ===================================================================
  RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/logic/RedirectTag.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- RedirectTag.java	2000/10/30 06:02:23	1.4
  +++ RedirectTag.java	2001/02/09 19:33:11	1.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/logic/RedirectTag.java,v 1.4 2000/10/30 06:02:23 craigmcc Exp $
  - * $Revision: 1.4 $
  - * $Date: 2000/10/30 06:02:23 $
  + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/logic/RedirectTag.java,v 1.5 2001/02/09 19:33:11 craigmcc Exp $
  + * $Revision: 1.5 $
  + * $Date: 2001/02/09 19:33:11 $
    *
    * ====================================================================
    *
  @@ -64,22 +64,30 @@
   
   
   import java.io.IOException;
  +import java.lang.reflect.InvocationTargetException;
  +import java.net.URLEncoder;
  +import java.util.Iterator;
  +import java.util.Map;
  +import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
   import javax.servlet.jsp.JspException;
   import javax.servlet.jsp.JspWriter;
   import javax.servlet.jsp.PageContext;
   import javax.servlet.jsp.tagext.TagSupport;
   import org.apache.struts.action.Action;
  +import org.apache.struts.action.ActionForward;
  +import org.apache.struts.action.ActionForwards;
   import org.apache.struts.util.BeanUtils;
   import org.apache.struts.util.MessageResources;
  +import org.apache.struts.util.PropertyUtils;
  +import org.apache.struts.util.RequestUtils;
   
   
   /**
  - * Perform a sendRedirect() to the specified URL, and skip evaluating
  - * the remainder of the current page.
  + * Generate a URL-encoded redirect to the specified URI.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.4 $ $Date: 2000/10/30 06:02:23 $
  + * @version $Revision: 1.5 $ $Date: 2001/02/09 19:33:11 $
    */
   
   public class RedirectTag extends TagSupport {
  @@ -89,16 +97,30 @@
   
   
       /**
  -     * The relative or absolute URL to which the client should be redirected.
  +     * The logical forward name from which to retrieve the redirect URI.
        */
  +    protected String forward = null;
  +
  +    public String getForward() {
  +	return (this.forward);
  +    }
  +
  +    public void setForward(String forward) {
  +	this.forward = forward;
  +    }
  +
  +
  +    /**
  +     * The redirect URI.
  +     */
       protected String href = null;
   
       public String getHref() {
  -        return (this.href);
  +	return (this.href);
       }
   
       public void setHref(String href) {
  -        this.href = href;
  +	this.href = href;
       }
   
   
  @@ -106,58 +128,395 @@
        * The message resources for this package.
        */
       protected static MessageResources messages =
  -	MessageResources.getMessageResources
  -	("org.apache.struts.taglib.logic.LocalStrings");
  +     MessageResources.getMessageResources
  +        ("org.apache.struts.taglib.logic.LocalStrings");
  +
  +
  +    /**
  +     * The JSP bean name for query parameters.
  +     */
  +    protected String name = null;
  +
  +    public String getName() {
  +	return (this.name);
  +    }
  +
  +    public void setName(String name) {
  +	this.name = name;
  +    }
  +
  +
  +    /**
  +     * The context-relative page URL (beginning with a slash) to which
  +     * this redirect will be rendered.
  +     */
  +    protected String page = null;
  +
  +    public String getPage() {
  +        return (this.page);
  +    }
  +
  +    public void setPage(String page) {
  +        this.page = page;
  +    }
  +
   
  +    /**
  +     * The single-parameter request parameter name to generate.
  +     */
  +    protected String paramId = null;
  +
  +    public String getParamId() {
  +        return (this.paramId);
  +    }
  +
  +    public void setParamId(String paramId) {
  +        this.paramId = paramId;
  +    }
  +
   
  +    /**
  +     * The single-parameter JSP bean name.
  +     */
  +    protected String paramName = null;
  +
  +    public String getParamName() {
  +        return (this.paramName);
  +    }
  +
  +    public void setParamName(String paramName) {
  +        this.paramName = paramName;
  +    }
  +
  +
  +    /**
  +     * The single-parameter JSP bean property.
  +     */
  +    protected String paramProperty = null;
  +
  +    public String getParamProperty() {
  +        return (this.paramProperty);
  +    }
  +
  +    public void setParamProperty(String paramProperty) {
  +        this.paramProperty = paramProperty;
  +    }
  +
  +
  +    /**
  +     * The single-parameter JSP bean scope.
  +     */
  +    protected String paramScope = null;
  +
  +    public String getParamScope() {
  +        return (this.paramScope);
  +    }
  +
  +    public void setParamScope(String paramScope) {
  +        this.paramScope = paramScope;
  +    }
  +
  +
  +    /**
  +     * The JSP bean property name for query parameters.
  +     */
  +    protected String property = null;
  +
  +    public String getProperty() {
  +	return (this.property);
  +    }
  +
  +    public void setProperty(String property) {
  +	this.property = property;
  +    }
  +
  +
  +    /**
  +     * The scope of the bean specified by the name property, if any.
  +     */
  +    protected String scope = null;
  +
  +    public String getScope() {
  +        return (this.scope);
  +    }
  +
  +    public void setScope(String scope) {
  +        this.scope = scope;
  +    }
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
       /**
  -     * Defer processing until the end of this tag is encountered.
  +     * Defer generation until the end of this tag is encountered.
        *
        * @exception JspException if a JSP exception has occurred
        */
       public int doStartTag() throws JspException {
   
  -	return (SKIP_BODY);
  +        return (SKIP_BODY);
   
       }
   
   
       /**
  -     * Render a redirect to the specified hyperlink, and skip the
  -     * remainder of the current page.
  +     * Render the redirect and skip the remainder of this page.
        *
        * @exception JspException if a JSP exception has occurred
        */
       public int doEndTag() throws JspException {
   
  -	// Perform the requested redirect
  +        // Perform the redirection
   	HttpServletResponse response =
   	  (HttpServletResponse) pageContext.getResponse();
  -	try {
  -	    response.sendRedirect(response.encodeRedirectURL(href));
  -	} catch (IOException e) {
  -            pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  -                                     PageContext.REQUEST_SCOPE);
  -	    throw new JspException
  -		(messages.getMessage("redirect.redirect", href, e.toString()));
  -	}
  +        String hyperlink = BeanUtils.filter(hyperlink());
  +        try {
  +            response.sendRedirect(response.encodeRedirectURL(hyperlink));
  +        } catch (IOException e) {
  +            throw new JspException
  +                (messages.getMessage("common.io"));
  +        }
   
  -	// Skip the remainder of the current page
  -	return (SKIP_PAGE);
  +        // Skip the remainder of this apge
  +        return (SKIP_PAGE);
   
       }
   
   
       /**
  -     * Release all allocated resources.
  +     * Release any acquired resources.
        */
       public void release() {
  +
  +	super.release();
  +	forward = null;
  +	href = null;
  +	name = null;
  +        page = null;
  +	paramId = null;
  +	paramName = null;
  +	paramProperty = null;
  +	paramScope = null;
  +	property = null;
  +        scope = null;
  +
  +    }
  +
  +
  +    // ------------------------------------------------------ Protected Methods
  +
  +
  +    /**
  +     * Return the specified hyperlink, modified as necessary with optional
  +     * request parameters.  Return <code>null</code> if we are generating
  +     * a name anchor rather than a hyperlink.
  +     *
  +     * @exception JspException if an error occurs preparing the hyperlink
  +     */
  +    protected String hyperlink() throws JspException {
  +
  +        // Validate the number of href specifiers that were specified
  +        int n = 0;
  +        if (forward != null)
  +            n++;
  +        if (href != null)
  +            n++;
  +        if (page != null)
  +            n++;
  +        if (n != 1) {
  +            JspException e = new JspException
  +                (messages.getMessage("redirect.destination"));
  +            pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                     PageContext.REQUEST_SCOPE);
  +            throw e;
  +        }
  +
  +        // Start with an unadorned "href"
  +	String href = null;
  +
  +        // If "href" was specified, use it as is
  +        if (this.href != null) {
  +            href = this.href;
  +        }
  +
  +	// If "forward" was specified, compute the "href" to forward to
  +	else if (forward != null) {
  +	    ActionForwards forwards = (ActionForwards)
  +		pageContext.getAttribute(Action.FORWARDS_KEY,
  +					 PageContext.APPLICATION_SCOPE);
  +	    if (forwards == null)
  +		throw new JspException
  +		    (messages.getMessage("linkTag.forwards"));
  +	    ActionForward forward = forwards.findForward(this.forward);
  +	    if (forward == null)
  +		throw new JspException
  +		    (messages.getMessage("linkTag.forward"));
  +	    HttpServletRequest request =
  +		(HttpServletRequest) pageContext.getRequest();
  +            href = RequestUtils.absoluteURL(request, forward.getPath());
  +	}
  +
  +        // If "page" was specified, compute the "href" to forward to
  +        else if (page != null) {
  +            HttpServletRequest request =
  +                (HttpServletRequest) pageContext.getRequest();
  +            href = RequestUtils.absoluteURL(request, page);
  +        }
  +
  +        // Append a single-parameter name and value, if requested
  +        if ((paramId != null) && (paramName != null)) {
  +            if (href.indexOf('?') < 0)
  +                href += '?';
  +            else
  +                href += '&';
  +            href += paramId;
  +            href += '=';
  +            Object bean = RequestUtils.lookup(pageContext,
  +                                              paramName, paramScope);
  +            if (bean != null) {
  +                if (paramProperty == null)
  +                    href += bean.toString();
  +                else {
  +                    try {
  +                        Object value =
  +                            PropertyUtils.getProperty(bean, paramProperty);
  +                        if (value != null)
  +                            href += value.toString();
  +                    } catch (IllegalAccessException e) {
  +                        pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                                 PageContext.REQUEST_SCOPE);
  +                        throw new JspException
  +                            (messages.getMessage("getter.access",
  +                                                 paramProperty, paramName));
  +                    } catch (InvocationTargetException e) {
  +                        Throwable t = e.getTargetException();
  +                        pageContext.setAttribute(Action.EXCEPTION_KEY, t,
  +                                                 PageContext.REQUEST_SCOPE);
  +                        throw new JspException
  +                            (messages.getMessage("getter.result",
  +                                                 paramProperty, t.toString()));
  +                    } catch (NoSuchMethodException e) {
  +                        pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                                 PageContext.REQUEST_SCOPE);
  +                        throw new JspException
  +                            (messages.getMessage("getter.method",
  +                                                 paramProperty, paramName));
  +                    }
  +                }
  +            }
  +        }
  +
  +	// Just return the "href" attribute if there is no bean to look up
  +	if ((property != null) && (name == null)) {
  +	    JspException e = new JspException
  +		(messages.getMessage("getter.name"));
  +            pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                     PageContext.REQUEST_SCOPE);
  +            throw e;
  +        }
  +	if (name == null)
  +	    return (href);
  +
  +	// Look up the map we will be using
  +	Object bean = RequestUtils.lookup(pageContext, name, scope);
  +        if (bean == null) {
  +	    JspException e = new JspException
  +		(messages.getMessage("getter.bean", name));
  +            pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                     PageContext.REQUEST_SCOPE);
  +            throw e;
  +        }
  +	Map map = null;
  +	if (property == null) {
  +	    try {
  +		map = (Map) bean;
  +	    } catch (ClassCastException e) {
  +                pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                         PageContext.REQUEST_SCOPE);
  +		throw new JspException
  +		    (messages.getMessage("linkTag.type"));
  +	    }
  +	} else {
  +	    try {
  +		map = (Map) PropertyUtils.getProperty(bean, property);
  +		if (map == null) {
  +		    JspException e = new JspException
  +			(messages.getMessage("getter.property", property));
  +                    pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                             PageContext.REQUEST_SCOPE);
  +                    throw e;
  +                }
  +	    } catch (IllegalAccessException e) {
  +                pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                         PageContext.REQUEST_SCOPE);
  +		throw new JspException
  +		    (messages.getMessage("getter.access", property, name));
  +	    } catch (InvocationTargetException e) {
  +		Throwable t = e.getTargetException();
  +                pageContext.setAttribute(Action.EXCEPTION_KEY, t,
  +                                         PageContext.REQUEST_SCOPE);
  +		throw new JspException
  +		    (messages.getMessage("getter.result",
  +					 property, t.toString()));
  +	    } catch (ClassCastException e) {
  +                pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                         PageContext.REQUEST_SCOPE);
  +		throw new JspException
  +		    (messages.getMessage("linkTag.type"));
  +	    } catch (NoSuchMethodException e) {
  +                pageContext.setAttribute(Action.EXCEPTION_KEY, e,
  +                                         PageContext.REQUEST_SCOPE);
  +		throw new JspException
  +		    (messages.getMessage("getter.method", property, name));
  +	    }
  +	}
  +
  +	// Append the required query parameters
  +	StringBuffer sb = new StringBuffer(href);
  +	boolean question = (href.indexOf("?") >= 0);
  +	Iterator keys = map.keySet().iterator();
  +	while (keys.hasNext()) {
  +	    String key = (String) keys.next();
  +	    Object value = map.get(key);
  +            if (value == null) {
  +                if (question)
  +                    sb.append('&');
  +                else {
  +                    sb.append('?');
  +                    question = true;
  +                }
  +                sb.append(key);
  +                sb.append('=');
  +                // Interpret null as "no value specified"
  +	    } else if (value instanceof String[]) {
  +		String values[] = (String[]) value;
  +		for (int i = 0; i < values.length; i++) {
  +		    if (question)
  +			sb.append('&');
  +		    else {
  +			sb.append('?');
  +			question = true;
  +		    }
  +		    sb.append(key);
  +		    sb.append('=');
  +		    sb.append(URLEncoder.encode(values[i]));
  +		}
  +	    } else {
  +		if (question)
  +		    sb.append('&');
  +		else {
  +		    sb.append('?');
  +		    question = true;
  +		}
  +		sb.append(key);
  +		sb.append('=');
  +		sb.append(URLEncoder.encode(value.toString()));
  +	    }
  +	}
   
  -        super.release();
  -        href = null;
  +	// Return the final result
  +	return (sb.toString());
   
       }