craigmcc 01/05/09 12:31:33 Modified: doc struts-bean.xml struts-html.xml struts-logic.xml src/share/org/apache/struts/taglib/bean IncludeTag.java LocalStrings.properties src/share/org/apache/struts/taglib/html LinkTag.java LocalStrings.properties RewriteTag.java src/share/org/apache/struts/taglib/logic LocalStrings.properties RedirectTag.java src/share/org/apache/struts/util LocalStrings.properties RequestUtils.java Log: Refactor the hyperlink-generation code used in the <bean:include>, <html:link>, <html:rewrite>, and <logic:redirect> tags to use common utility methods based on URLs rather than Strings. This will ensure consistency in implementation, and make it easy to provide full URL-processing functionality to other tags as necessary. Revision Changes Path 1.4 +22 -0 jakarta-struts/doc/struts-bean.xml Index: struts-bean.xml =================================================================== RCS file: /home/cvs/jakarta-struts/doc/struts-bean.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- struts-bean.xml 2001/04/22 00:46:19 1.3 +++ struts-bean.xml 2001/05/09 19:31:00 1.4 @@ -353,6 +353,17 @@ </info> <attribute> + <name>anchor</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + <p>Optional anchor tag ("#xxx") to be added to the generated + hyperlink. Specify this value <strong>without</strong> any + "#" character.</p> + </info> + </attribute> + + <attribute> <name>forward</name> <required>false</required> <rtexprvalue>true</rtexprvalue> @@ -404,6 +415,17 @@ <info> <p>Context-relative URI (starting with a '/') of the web application resource to be included.</p> + </info> + </attribute> + + <attribute> + <name>transaction</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + <p>Set to <code>true</code> if you want the current + transaction control token included in the generated + URL for this include.</p> </info> </attribute> 1.9 +81 -6 jakarta-struts/doc/struts-html.xml Index: struts-html.xml =================================================================== RCS file: /home/cvs/jakarta-struts/doc/struts-html.xml,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- struts-html.xml 2001/05/05 00:59:50 1.8 +++ struts-html.xml 2001/05/09 19:31:01 1.9 @@ -3704,6 +3704,17 @@ </info> <attribute> + <name>anchor</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + <p>Optional anchor tag ("#xxx") to be added to the generated + hyperlink. Specify this value <strong>without</strong> any + "#" character.</p> + </info> + </attribute> + + <attribute> <name>forward</name> <required>false</required> <rtexprvalue>true</rtexprvalue> @@ -3735,6 +3746,19 @@ </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> @@ -3751,15 +3775,54 @@ </attribute> <attribute> - <name>name</name> + <name>paramId</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> + <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> @@ -3785,6 +3848,18 @@ <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> + + <attribute> + <name>transaction</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + <p>If set to <code>true</code>, any current transaction + control token will be included in the generated hyperlink, + so that it will pass an <code>isTokenValid()</code> test + in the receiving Action.</p> </info> </attribute> 1.6 +22 -0 jakarta-struts/doc/struts-logic.xml Index: struts-logic.xml =================================================================== RCS file: /home/cvs/jakarta-struts/doc/struts-logic.xml,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- struts-logic.xml 2001/04/19 21:25:04 1.5 +++ struts-logic.xml 2001/05/09 19:31:02 1.6 @@ -1318,6 +1318,17 @@ </info> <attribute> + <name>anchor</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + <p>Optional anchor tag ("#xxx") to be added to the generated + hyperlink. Specify this value <strong>without</strong> any + "#" character.</p> + </info> + </attribute> + + <attribute> <name>forward</name> <required>false</required> <rtexprvalue>true</rtexprvalue> @@ -1451,6 +1462,17 @@ <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> + + <attribute> + <name>transaction</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + <p>Set to <code>true</code> if you want the current + transaction control token included in the generated + URL for this redirect.</p> </info> </attribute> 1.13 +46 -117 jakarta-struts/src/share/org/apache/struts/taglib/bean/IncludeTag.java Index: IncludeTag.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/bean/IncludeTag.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- IncludeTag.java 2001/05/09 04:42:10 1.12 +++ IncludeTag.java 2001/05/09 19:31:10 1.13 @@ -1,5 +1,5 @@ /* - * $Id: IncludeTag.java,v 1.12 2001/05/09 04:42:10 craigmcc Exp $ + * $Id: IncludeTag.java,v 1.13 2001/05/09 19:31:10 craigmcc Exp $ * ==================================================================== * * The Apache Software License, Version 1.1 @@ -66,6 +66,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -91,7 +92,7 @@ * wrapped response passed to RequestDispatcher.include(). * * @author Craig R. McClanahan - * @version $Revision: 1.12 $ $Date: 2001/05/09 04:42:10 $ + * @version $Revision: 1.13 $ $Date: 2001/05/09 19:31:10 $ */ public class IncludeTag extends TagSupport { @@ -107,6 +108,20 @@ /** + * The anchor to be added to the end of the generated hyperlink. + */ + protected String anchor = null; + + public String getAnchor() { + return (this.anchor); + } + + public void setAnchor(String anchor) { + this.anchor = anchor; + } + + + /** * The name of the global <code>ActionForward</code> that contains a * path to our requested resource. */ @@ -183,6 +198,20 @@ } + /** + * Include transaction token (if any) in the hyperlink? + */ + protected boolean transaction = false; + + public boolean getTransaction() { + return (this.transaction); + } + + public void setTransaction(boolean transaction) { + this.transaction = transaction; + } + + // --------------------------------------------------------- Public Methods @@ -195,7 +224,19 @@ public int doStartTag() throws JspException { // Set up a URLConnection to read the requested resource - URL url = hyperlink(); + Map params = RequestUtils.computeParameters + (pageContext, null, null, null, null, + null, null, null, transaction); // FIXME - <html:link> attributes + URL url = null; + try { + url = RequestUtils.computeURL(pageContext, forward, href, + page, params, anchor, false); + } catch (MalformedURLException e) { + RequestUtils.saveException(pageContext, e); + throw new JspException + (messages.getMessage("include.url", e.toString())); + } + URLConnection conn = null; try { conn = url.openConnection(); @@ -247,124 +288,12 @@ public void release() { super.release(); + anchor = null; forward = null; href = null; id = null; page = null; - - } - - - // ------------------------------------------------------ Protected Methods - - - /** - * Return a URL to the requested resource, modified to include the session - * identifier if necessary. - * - * @exception JspException if an error occurs preparing the hyperlink - */ - protected URL 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("include.destination")); - RequestUtils.saveException(pageContext, e); - throw e; - } - - // Calculate the appropriate hyperlink - String href = null; - boolean includeSession = true; - if (this.forward != null) { - ActionForwards forwards = (ActionForwards) - pageContext.getAttribute(Action.FORWARDS_KEY, - PageContext.APPLICATION_SCOPE); - if (forwards == null) { - JspException e = new JspException - (messages.getMessage("include.forwards")); - RequestUtils.saveException(pageContext, e); - throw e; - } - ActionForward forward = forwards.findForward(this.forward); - if (forward == null) { - JspException e = new JspException - (messages.getMessage("include.forward", this.forward)); - RequestUtils.saveException(pageContext, e); - throw e; - } - HttpServletRequest request = - (HttpServletRequest) pageContext.getRequest(); - try { - href = RequestUtils.absoluteURL(request, forward.getPath()); - } catch (MalformedURLException mue) { - RequestUtils.saveException(pageContext, mue); - ServletContext sc = pageContext.getServletContext(); - sc.log(messages.getMessage("include.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - forward.getPath()), - mue); - JspException e = new JspException - (messages.getMessage("include.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - forward.getPath())); - throw e; - } - } else if (this.href != null) { - href = this.href; - includeSession = false; - } else /* if (this.page != null) */ { - HttpServletRequest request = - (HttpServletRequest) pageContext.getRequest(); - try { - href = RequestUtils.absoluteURL(request, this.page); - } catch (MalformedURLException mue) { - RequestUtils.saveException(pageContext, mue); - ServletContext sc = pageContext.getServletContext(); - sc.log(messages.getMessage("include.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - this.page), - mue); - JspException e = new JspException - (messages.getMessage("include.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - this.page)); - throw e; - } - } - - // Append the session identifier if appropriate - if (includeSession) { - HttpServletResponse response = - (HttpServletResponse) pageContext.getResponse(); - href = response.encodeURL(href); - } - - // Convert the hyperlink to a URL - try { - return (new URL(href)); - } catch (MalformedURLException e) { - RequestUtils.saveException(pageContext, e); - JspException f = new JspException - (messages.getMessage("include.malformed", href)); - throw f; - } + transaction = false; } 1.12 +1 -1 jakarta-struts/src/share/org/apache/struts/taglib/bean/LocalStrings.properties Index: LocalStrings.properties =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/bean/LocalStrings.properties,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- LocalStrings.properties 2001/05/03 03:29:36 1.11 +++ LocalStrings.properties 2001/05/09 19:31:11 1.12 @@ -6,7 +6,7 @@ include.malformed=Cannot create URL for {0} include.open=Exception opening resource {0}: {1} include.read=Exception reading resource {0}: {1} -include.url=Cannot create URL with scheme={0} server={1} port={2} path={3} +include.url=Cannot create include URL: {0} message.message=Missing message for key {0} message.resources=Missing resources attribute {0} page.selector=Invalid page context selector {0} 1.13 +30 -127 jakarta-struts/src/share/org/apache/struts/taglib/html/LinkTag.java Index: LinkTag.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/LinkTag.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- LinkTag.java 2001/05/03 03:29:36 1.12 +++ LinkTag.java 2001/05/09 19:31:15 1.13 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/LinkTag.java,v 1.12 2001/05/03 03:29:36 craigmcc Exp $ - * $Revision: 1.12 $ - * $Date: 2001/05/03 03:29:36 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/LinkTag.java,v 1.13 2001/05/09 19:31:15 craigmcc Exp $ + * $Revision: 1.13 $ + * $Date: 2001/05/09 19:31:15 $ * * ==================================================================== * @@ -66,6 +66,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; +import java.net.URL; import java.net.URLEncoder; import java.util.Iterator; import java.util.Map; @@ -88,7 +89,7 @@ * Generate a URL-encoded hyperlink to the specified URI. * * @author Craig R. McClanahan - * @version $Revision: 1.12 $ $Date: 2001/05/03 03:29:36 $ + * @version $Revision: 1.13 $ $Date: 2001/05/09 19:31:15 $ */ public class LinkTag extends BaseHandlerTag { @@ -320,21 +321,32 @@ */ public int doStartTag() throws JspException { - // Generate the name definition or hyperlink element - HttpServletResponse response = - (HttpServletResponse) pageContext.getResponse(); - StringBuffer results = new StringBuffer("<a"); - String hyperlink = hyperlink(); - if (hyperlink != null) { - results.append(" href=\""); - results.append(response.encodeURL(hyperlink)); - results.append("\""); - } + // Special case for name anchors if (linkName != null) { - results.append(" name=\""); + StringBuffer results = new StringBuffer("<a name=\""); results.append(linkName); - results.append("\""); + results.append("\">"); + return (EVAL_BODY_TAG); + } + + // Generate the hyperlink URL + Map params = RequestUtils.computeParameters + (pageContext, paramId, paramName, paramProperty, paramScope, + name, property, scope, transaction); + URL url = null; + try { + url = RequestUtils.computeURL(pageContext, forward, href, + page, params, anchor, false); + } catch (MalformedURLException e) { + RequestUtils.saveException(pageContext, e); + throw new JspException + (messages.getMessage("rewrite.url", e.toString())); } + + // Generate the opening anchor element + StringBuffer results = new StringBuffer("<a href=\""); + results.append(url.toString()); + results.append("\""); if (target != null) { results.append(" target=\""); results.append(target); @@ -418,118 +430,9 @@ } - - // ------------------------------------------------------ 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 { - - if (linkName != null) - return (null); // We are not generating a hyperlink - - // Validate the number of href specifiers that were specified - int n = 0; - if (forward != null) - n++; - if (href != null) - n++; - if (linkName != null) - n++; - if (page != null) - n++; - if (n != 1) { - JspException e = new JspException - (messages.getMessage("linkTag.destination")); - RequestUtils.saveException(pageContext, e); - 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) { - JspException e = new JspException - (messages.getMessage("linkTag.forwards")); - RequestUtils.saveException(pageContext, e); - throw e; - } - ActionForward forward = forwards.findForward(this.forward); - if (forward == null) { - JspException e = new JspException - (messages.getMessage("linkTag.forward")); - RequestUtils.saveException(pageContext, e); - throw e; - } - HttpServletRequest request = - (HttpServletRequest) pageContext.getRequest(); - try { - href = RequestUtils.absoluteURL(request, forward.getPath()); - } catch (MalformedURLException mue) { - RequestUtils.saveException(pageContext, mue); - ServletContext sc = pageContext.getServletContext(); - sc.log(messages.getMessage("linkTag.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - forward.getPath()), - mue); - JspException e = new JspException - (messages.getMessage("linkTag.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - forward.getPath())); - throw e; - } - } - - // If "linkName" was specified, return null (not making an href) - else if (linkName != null) { - return (null); - } - - // If "page" was specified, compute the "href" to forward to - else if (page != null) { - HttpServletRequest request = - (HttpServletRequest) pageContext.getRequest(); - try { - href = RequestUtils.absoluteURL(request, page); - } catch (MalformedURLException mue) { - RequestUtils.saveException(pageContext, mue); - ServletContext sc = pageContext.getServletContext(); - sc.log(messages.getMessage("linkTag.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - page), - mue); - JspException e = new JspException - (messages.getMessage("linkTag.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - page)); - throw e; - } - } - // Save any currently specified anchor string String anchor = this.anchor; int hash = href.indexOf('#'); @@ -652,7 +555,7 @@ // Return the final result return (sb.toString()); - } + */ } 1.9 +2 -1 jakarta-struts/src/share/org/apache/struts/taglib/html/LocalStrings.properties Index: LocalStrings.properties =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/LocalStrings.properties,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- LocalStrings.properties 2001/05/03 03:29:37 1.8 +++ LocalStrings.properties 2001/05/09 19:31:17 1.9 @@ -27,7 +27,7 @@ linkTag.forwards=Cannot locate forwards mapping table linkTag.type=Object must be of type Map linkTag.type1=Object must be of type Dictionary -linkTag.url=Cannot create URL with scheme={0} server={1} port={2} path={3} +linkTag.url=Cannot create link URL: {0} messageTag.message=Missing message for key {0} messageTag.resources=Missing resources attribute {0} multiboxTag.value=You must specify the value attribute or nested tag content @@ -35,3 +35,4 @@ optionsTag.enumeration=Cannot create enumeration for {0} optionsTag.iterator=Cannot create iterator for {0} optionsTag.select=Options tag must be nested in a Select tag +rewrite.url=Cannot create rewrite URL: {0} 1.5 +21 -10 jakarta-struts/src/share/org/apache/struts/taglib/html/RewriteTag.java Index: RewriteTag.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/RewriteTag.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- RewriteTag.java 2001/04/29 00:38:04 1.4 +++ RewriteTag.java 2001/05/09 19:31:18 1.5 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/RewriteTag.java,v 1.4 2001/04/29 00:38:04 craigmcc Exp $ - * $Revision: 1.4 $ - * $Date: 2001/04/29 00:38:04 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/RewriteTag.java,v 1.5 2001/05/09 19:31:18 craigmcc Exp $ + * $Revision: 1.5 $ + * $Date: 2001/05/09 19:31:18 $ * * ==================================================================== * @@ -65,6 +65,8 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; import java.net.URLEncoder; import java.util.Iterator; import java.util.Map; @@ -78,6 +80,7 @@ import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionForwards; import org.apache.struts.util.MessageResources; +import org.apache.struts.util.RequestUtils; import org.apache.struts.util.ResponseUtils; @@ -85,7 +88,7 @@ * Generate a URL-encoded URI as a string. * * @author Craig R. McClanahan - * @version $Revision: 1.4 $ $Date: 2001/04/29 00:38:04 $ + * @version $Revision: 1.5 $ $Date: 2001/05/09 19:31:18 $ */ public class RewriteTag extends LinkTag { @@ -101,14 +104,22 @@ */ public int doStartTag() throws JspException { - // Generate the hyperlink start element - HttpServletResponse response = - (HttpServletResponse) pageContext.getResponse(); - StringBuffer results = new StringBuffer(); - results.append(response.encodeURL(hyperlink())); + // Generate the hyperlink URL + Map params = RequestUtils.computeParameters + (pageContext, paramId, paramName, paramProperty, paramScope, + name, property, scope, transaction); + URL url = null; + try { + url = RequestUtils.computeURL(pageContext, forward, href, + page, params, anchor, false); + } catch (MalformedURLException e) { + RequestUtils.saveException(pageContext, e); + throw new JspException + (messages.getMessage("rewrite.url", e.toString())); + } // Print this element to our output writer - ResponseUtils.write(pageContext, results.toString()); + ResponseUtils.write(pageContext, url.toString()); // Skip the body of this tag return (SKIP_BODY); 1.6 +1 -1 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.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- LocalStrings.properties 2001/05/03 03:29:37 1.5 +++ LocalStrings.properties 2001/05/09 19:31:22 1.6 @@ -11,4 +11,4 @@ redirect.forward=Missing ActionForward for {0} redirect.forwards=Missing ActionForwards collection redirect.map=Property {0} of bean {1} is not a Map -redirect.url=Cannot create URL with scheme={0} server={1} port={2} path={3} +redirect.url=Cannot create redirect URL: {0} 1.9 +49 -188 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.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- RedirectTag.java 2001/05/03 03:29:38 1.8 +++ RedirectTag.java 2001/05/09 19:31:23 1.9 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/logic/RedirectTag.java,v 1.8 2001/05/03 03:29:38 craigmcc Exp $ - * $Revision: 1.8 $ - * $Date: 2001/05/03 03:29:38 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/logic/RedirectTag.java,v 1.9 2001/05/09 19:31:23 craigmcc Exp $ + * $Revision: 1.9 $ + * $Date: 2001/05/09 19:31:23 $ * * ==================================================================== * @@ -65,6 +65,7 @@ import java.io.IOException; import java.net.MalformedURLException; +import java.net.URL; import java.net.URLEncoder; import java.util.Iterator; import java.util.Map; @@ -88,7 +89,7 @@ * Generate a URL-encoded redirect to the specified URI. * * @author Craig R. McClanahan - * @version $Revision: 1.8 $ $Date: 2001/05/03 03:29:38 $ + * @version $Revision: 1.9 $ $Date: 2001/05/09 19:31:23 $ */ public class RedirectTag extends TagSupport { @@ -98,6 +99,20 @@ /** + * The anchor to be added to the end of the generated hyperlink. + */ + protected String anchor = null; + + public String getAnchor() { + return (this.anchor); + } + + public void setAnchor(String anchor) { + this.anchor = anchor; + } + + + /** * The logical forward name from which to retrieve the redirect URI. */ protected String forward = null; @@ -246,6 +261,20 @@ } + /** + * Include our transaction control token? + */ + protected boolean transaction = false; + + public boolean getTransaction() { + return (this.transaction); + } + + public void setTransaction(boolean transaction) { + this.transaction = transaction; + } + + // --------------------------------------------------------- Public Methods @@ -268,12 +297,25 @@ */ public int doEndTag() throws JspException { + // Calculate the redirect URL + Map params = RequestUtils.computeParameters + (pageContext, paramId, paramName, paramProperty, paramScope, + name, property, scope, transaction); + URL url = null; + try { + url = RequestUtils.computeURL(pageContext, forward, href, + page, params, anchor, true); + } catch (MalformedURLException e) { + RequestUtils.saveException(pageContext, e); + throw new JspException + (messages.getMessage("redirect.url", e.toString())); + } + // Perform the redirection HttpServletResponse response = (HttpServletResponse) pageContext.getResponse(); - String hyperlink = hyperlink(); try { - response.sendRedirect(response.encodeRedirectURL(hyperlink)); + response.sendRedirect(url.toString()); } catch (IOException e) { RequestUtils.saveException(pageContext, e); throw new JspException(e.getMessage()); @@ -291,6 +333,7 @@ public void release() { super.release(); + anchor = null; forward = null; href = null; name = null; @@ -301,188 +344,6 @@ 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")); - RequestUtils.saveException(pageContext, e); - 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) { - JspException e = new JspException - (messages.getMessage("redirect.forwards")); - RequestUtils.saveException(pageContext, e); - throw e; - } - ActionForward forward = forwards.findForward(this.forward); - if (forward == null) { - JspException e = new JspException - (messages.getMessage("redirect.forward", this.forward)); - RequestUtils.saveException(pageContext, e); - throw e; - } - HttpServletRequest request = - (HttpServletRequest) pageContext.getRequest(); - try { - href = RequestUtils.absoluteURL(request, forward.getPath()); - } catch (MalformedURLException mue) { - RequestUtils.saveException(pageContext, mue); - ServletContext sc = pageContext.getServletContext(); - sc.log(messages.getMessage("redirect.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - forward.getPath()), - mue); - JspException e = new JspException - (messages.getMessage("redirect.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - forward.getPath())); - throw e; - } - } - - // If "page" was specified, compute the "href" to forward to - else if (page != null) { - HttpServletRequest request = - (HttpServletRequest) pageContext.getRequest(); - try { - href = RequestUtils.absoluteURL(request, page); - } catch (MalformedURLException mue) { - RequestUtils.saveException(pageContext, mue); - ServletContext sc = pageContext.getServletContext(); - sc.log(messages.getMessage("redirect.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - page), - mue); - JspException e = new JspException - (messages.getMessage("redirect.url", - request.getScheme(), - request.getServerName(), - "" + request.getServerPort(), - page)); - throw e; - } - } - - // 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 value = - RequestUtils.lookup(pageContext, paramName, paramProperty, - paramScope); - if (value != null) - href += value.toString(); - } - - // Just return the "href" attribute if there is no bean to look up - if (name == null) - return (href); - - // Look up the map we will be using - Object value = - RequestUtils.lookup(pageContext, name, property, scope); - if (value == null) - return (href); - if (!(value instanceof Map)) { - JspException e = new JspException - (messages.getMessage("redirect.map", property, name)); - RequestUtils.saveException(pageContext, e); - throw e; - } - Map map = (Map) value; - - // 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(); - 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())); - } - } - - // Return the final result - return (sb.toString()); } 1.3 +5 -0 jakarta-struts/src/share/org/apache/struts/util/LocalStrings.properties Index: LocalStrings.properties =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/LocalStrings.properties,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- LocalStrings.properties 2001/02/20 01:48:46 1.2 +++ LocalStrings.properties 2001/05/09 19:31:28 1.3 @@ -1,7 +1,12 @@ +computeURL.forward=Cannot retrive ActionForward named {0} +computeURL.forwards=Cannot retrieve ActionForwards collection +computeURL.specifier=You must specify exactly one of "forward", "href", or "page" lookup.access=Invalid access looking up property {0} of bean {1} lookup.bean=Cannot find bean {0} in scope {1} lookup.method=No getter method for property {0} of bean {1} lookup.scope=Invalid bean scope {0} lookup.target=Exception thrown by getter for property {0} of bean {1} message.bundle=Cannot find message resources under key {0} +parameters.multi=Cannot cast to Map for name={0} property={1e} scope={2} +parameters.single=Cannot cast to String for name={0} property={1} scope={2} write.io=Input/output error: {0} 1.11 +276 -11 jakarta-struts/src/share/org/apache/struts/util/RequestUtils.java Index: RequestUtils.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/RequestUtils.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- RequestUtils.java 2001/05/03 03:29:38 1.10 +++ RequestUtils.java 2001/05/09 19:31:29 1.11 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/RequestUtils.java,v 1.10 2001/05/03 03:29:38 craigmcc Exp $ - * $Revision: 1.10 $ - * $Date: 2001/05/03 03:29:38 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/RequestUtils.java,v 1.11 2001/05/09 19:31:29 craigmcc Exp $ + * $Revision: 1.11 $ + * $Date: 2001/05/09 19:31:29 $ * * ==================================================================== * @@ -66,6 +66,7 @@ import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLEncoder; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; @@ -74,12 +75,17 @@ import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionForwards; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionServlet; +import org.apache.struts.taglib.html.Constants; import org.apache.struts.upload.FormFile; import org.apache.struts.upload.MultipartRequestHandler; @@ -89,7 +95,7 @@ * in the Struts controller framework. * * @author Craig R. McClanahan - * @version $Revision: 1.10 $ $Date: 2001/05/03 03:29:38 $ + * @version $Revision: 1.11 $ $Date: 2001/05/09 19:31:29 $ */ public class RequestUtils { @@ -119,28 +125,287 @@ /** * Create and return an absolute URL for the specified context-relative * path, based on the server and context information in the specified - * request. If no valid URL can be created, returns <code>null</code>. + * request. * * @param request The servlet request we are processing * @param path The context-relative path (must start with '/') * * @exception MalformedURLException if we cannot create an absolute URL */ - public static String absoluteURL(HttpServletRequest request, String path) + public static URL absoluteURL(HttpServletRequest request, String path) throws MalformedURLException { - URL url = null; int port = request.getServerPort(); String scheme = request.getScheme(); String serverName = request.getServerName(); String uri = request.getContextPath() + path; if ("http".equals(scheme) && (80 == port)) - url = new URL(scheme, serverName, uri); + return (new URL(scheme, serverName, uri)); else if ("https".equals(scheme) && (443 == port)) - url = new URL(scheme, serverName, uri); + return (new URL(scheme, serverName, uri)); + else // Nonstandard port for the specified protocol + return (new URL(scheme, serverName, port, uri)); + + } + + + /** + * Compute a set of query parameters that will be dynamically added to + * a generated URL. The returned Map is keyed by parameter name, and the + * values are either null (no value specified), a String (single value + * specified), or a String[] array (multiple values specified). Parameter + * names correspond to the corresponding attributes of the + * <code><html:link></code> tag. If no query parameters are + * identified, return <code>null</code>. + * + * @param pageContext PageContext we are operating in + * + * @param paramId Single-value request parameter name (if any) + * @param paramName Bean containing single-value parameter value + * @param paramProperty Property (of bean named by <code>paramName</code> + * containing single-value parameter value + * @param paramScope Scope containing bean named by + * <code>paramScope</code> + * + * @param name Bean containing multi-value parameters Map (if any) + * @param property Property (of bean named by <code>name</code> + * containing multi-value parameters Map + * @param scope Scope containing bean named by + * <code>name</code> + * + * @param transaction Should we add our transaction control token? + * + * @exception JspException if we cannot look up the required beans + * @exception JspException if a class cast exception occurs on a + * looked-up bean or property + */ + public static Map computeParameters(PageContext pageContext, + String paramId, String paramName, + String paramProperty, + String paramScope, String name, + String property, String scope, + boolean transaction) + throws JspException { + + // Short circuit if no parameters are specified + if ((paramId == null) && (name == null)) + return (null); + + // Locate the Map containing our multi-value parameters map + Map map = null; + try { + map = (Map) lookup(pageContext, name, + property, scope); + } catch (ClassCastException e) { + saveException(pageContext, e); + throw new JspException + (messages.getMessage("parameters.multi", name, + property, scope)); + } catch (JspException e) { + saveException(pageContext, e); + throw e; + } + + // Create a Map to contain our results from the multi-value parameters + Map results = null; + if (map != null) + results = new HashMap(map); else - url = new URL(scheme, serverName, port, uri); - return (url.toString()); + results = new HashMap(); + + // Add the single-value parameter (if any) + if (paramId != null) { + String paramValue = null; + try { + paramValue =(String) lookup(pageContext, paramName, + paramProperty, paramScope); + } catch (ClassCastException e) { + saveException(pageContext, e); + throw new JspException + (messages.getMessage("parameters.single", paramName, + paramProperty, paramScope)); + } catch (JspException e) { + saveException(pageContext, e); + throw e; + } + Object mapValue = map.get(paramId); + if (mapValue == null) + map.put(paramId, paramValue); + else if (mapValue instanceof String) { + String newValues[] = new String[2]; + newValues[0] = (String) mapValue; + newValues[1] = paramValue; + map.put(paramId, newValues); + } else /* if (mapValue instanceof String[]) */ { + String oldValues[] = (String[]) mapValue; + String newValues[] = new String[oldValues.length + 1]; + System.arraycopy(oldValues, 0, newValues, 0, oldValues.length); + newValues[oldValues.length] = paramValue; + map.put(paramId, newValues); + } + } + + // Add our transaction control token (if requested) + if (transaction) { + HttpSession session = pageContext.getSession(); + String token = null; + if (session != null) + token = (String) + session.getAttribute(Action.TRANSACTION_TOKEN_KEY); + if (token != null) + map.put(Constants.TOKEN_KEY, token); + } + + // Return the completed Map + return (results); + + } + + + /** + * Compute an absolute URL based on the <code>forward</code>, + * <code>href</code>, or <code>page</code> parameter that is not null. + * The returned URL will have already been passed to + * <code>response.encodeURL()</code> for adding a session identifier. + * + * @param pageContext PageContext for the tag making this call + * @param forward Logical forward name for which to look up + * the context-relative URI (if specified) + * @param href URL to be utilized unmodified (if specified) + * @param page Context-relative page for which a URL should + * be created (if specified) + * @param params Map of parameters to be dynamically included (if any) + * @param anchor Anchor to be dynamically included (if any) + * @param redirect Is this URL for a <code>response.sendRedirect()</code>? + * + * @exception MalformedURLException if a URL cannot be created + * for the specified parameters + */ + public static URL computeURL(PageContext pageContext, String forward, + String href, String page, + Map params, String anchor, boolean redirect) + throws MalformedURLException { + + // Validate that exactly one specifier was included + int n = 0; + if (forward != null) + n++; + if (href != null) + n++; + if (page != null) + n++; + if (n != 1) + throw new MalformedURLException + (messages.getMessage("computeURL.specifier")); + + // Calculate the appropriate URL + URL url = null; + if (forward != null) { + ActionForwards forwards = (ActionForwards) + pageContext.getAttribute(Action.FORWARDS_KEY, + PageContext.APPLICATION_SCOPE); + if (forwards == null) + throw new MalformedURLException + (messages.getMessage("computeURL.forwards")); + ActionForward af = forwards.findForward(forward); + if (af == null) + throw new MalformedURLException + (messages.getMessage("computeURL.forward", forward)); + HttpServletRequest request = + (HttpServletRequest) pageContext.getRequest(); + url = absoluteURL(request, af.getPath()); + } else if (href != null) { + url = new URL(href); + } else /* if (page != null) */ { + HttpServletRequest request = + (HttpServletRequest) pageContext.getRequest(); + url = absoluteURL(request, page); + } + + // Add anchor if requested (replacing any existing anchor) + if (anchor != null) { + String temp = url.toString(); + int hash = temp.indexOf('#'); + if (hash >= 0) + temp = temp.substring(0, hash); + StringBuffer sb = new StringBuffer(temp); + sb.append('#'); + sb.append(URLEncoder.encode(anchor)); + url = new URL(sb.toString()); + } + + // Add dynamic parameters if requested + if ((params != null) && (params.size() > 0)) { + + // Save any existing anchor + String temp = url.toString(); + int hash = temp.indexOf('#'); + if (hash >= 0) { + anchor = temp.substring(hash + 1); + temp = temp.substring(0, hash); + } else + anchor = null; + + // Add the required request parameters + boolean question = temp.indexOf('?') >= 0; + StringBuffer sb = new StringBuffer(temp); + Iterator keys = params.keySet().iterator(); + while (keys.hasNext()) { + String key = (String) keys.next(); + Object value = params.get(key); + if (value == null) { + if (!question) { + sb.append('?'); + question = true; + } else + sb.append('&'); + sb.append(URLEncoder.encode(key)); + sb.append('='); // Interpret null as "no value" + } else if (value instanceof String) { + if (!question) { + sb.append('?'); + question = true; + } else + sb.append('&'); + sb.append(URLEncoder.encode(key)); + sb.append('='); + sb.append(URLEncoder.encode((String) value)); + } else /* if (value instanceof String[]) */ { + String values[] = (String[]) value; + for (int i = 0; i < values.length; i++) { + if (!question) { + sb.append('?'); + question = true; + } else + sb.append('&'); + sb.append(URLEncoder.encode(key)); + sb.append('='); + sb.append(URLEncoder.encode(values[i])); + } + } + } + + // Re-add the saved anchor (if any) + if (anchor != null) { + sb.append('#'); + sb.append(anchor); + } + + // Update to the completed URL + url = new URL(sb.toString()); + + } + + // Perform URL rewriting to include our session ID (if any) + if (pageContext.getSession() != null) { + HttpServletResponse response = + (HttpServletResponse) pageContext.getResponse(); + if (redirect) + url = new URL(response.encodeRedirectURL(url.toString())); + else + url = new URL(response.encodeURL(url.toString())); + } + return (url); }