Hi Senthil,
Thanks for clarifying what you were trying to do. Can you also change
the name of this handler to "encodeActionURL" to be consistent with JSF
api's then?
Thanks for doing this!
Ken
Senthil Chidambaram wrote:
> Ken,
> My response inline...
> Ken Paulsen wrote:
>
>>
>> Hi Senthil,
>>
>> I think there may be a couple issues with this.
>>
>> First I'm not sure this does what you expect. If you want to
>> urlencode QUERY_STRING parameters, this does not do that. If you
>> want to add the "jsessionid" to the url when cookies are disabled...
>> then it does do what you expected. In either case, can you please
>> document the handler explaining more specifically what it does?
>
> I meant jsessionid when cookies are enabled. I'll change the document
> clearly explaining about this.
>
>>
>> Second, I would like all JSFTemplating handlers to be compatible with
>> a Portlet environment. This means you should use the
>> ExternalContext's methods, or be very careful to write Portlet
>> compatible code. Casting to ServletResponse will not work in a
>> Portlet environment. You can use the encodeActionURL to do the same
>> thing you are doing. While this does not technically call the same
>> method (encodeURL vs. encodeRedirectURL) the container's
>> implementation is the same (at least for GlassFish).
>
> I didn't think about it portlet compatible, Thanks for letting me know
> about this. I'll make this change as well.
>
>>
>> If you meant to urlencode the QUERY_STRING parameters, you will have
>> a lot more work to do b/c you'll have to do each parameter
>> individually. I'm not sure a method that takes a String version of a
>> URL should attempt this because you will not be able to easily
>> distinguish between an '&' that is part of a value, and an '&' that
>> seperates a value. Same with '='. Instead the developer
>> constructing the URL should take the responsibility of calling the
>> existing "urlencode" handler on each "value" of a QUERY_STRING
>> parameter they add (or call the URLEncoder.encode() method directly
>> from Java code).
>
> I think we can use urlencode for now for this. If there is a strong
> need for this then I'll add this as RFE.
>
>>
>> I hope this makes sense... let me know if you need more clarification.
>
> I'll send you the changes soon as per your comments/review.
>
> thx
> Senthil
>
>>
>> Thanks!!
>>
>> Ken
>>
>> Senthil Chidambaram wrote:
>>
>>> Ken,
>>> Could you please review this, and let me know. I've added
>>> encoderedirect() in NavigationHandlers. The diffs are attached with
>>> the src as well.
>>>
>>> thx
>>> Senthil
>>>
>>> ------------------------------------------------------------------------
>>>
>>>
>>> /*
>>> * The contents of this file are subject to the terms * of the Common
>>> Development and Distribution License * (the License). You may not
>>> use this file except in
>>> * compliance with the License.
>>> * * You can obtain a copy of the license at *
>>> https://jsftemplating.dev.java.net/cddl1.html or
>>> * jsftemplating/cddl1.txt.
>>> * See the License for the specific language governing * permissions
>>> and limitations under the License.
>>> * * When distributing Covered Code, include this CDDL * Header
>>> Notice in each file and include the License file * at
>>> jsftemplating/cddl1.txt. * If applicable, add the following below
>>> the CDDL Header, * with the fields enclosed by brackets [] replaced by
>>> * you own identifying information: * "Portions Copyrighted [year]
>>> [name of copyright owner]"
>>> * * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
>>> */
>>> /*
>>> * NavigationHandlers.java
>>> *
>>> * Created on December 6, 2004, 11:06 PM
>>> */
>>> package com.sun.jsftemplating.handlers;
>>>
>>> import com.sun.jsftemplating.annotation.Handler;
>>> import com.sun.jsftemplating.annotation.HandlerInput;
>>> import com.sun.jsftemplating.annotation.HandlerOutput;
>>> import com.sun.jsftemplating.layout.descriptors.handler.HandlerContext;
>>>
>>> import java.io.IOException;
>>>
>>> import javax.faces.component.UIViewRoot;
>>> import javax.faces.context.FacesContext;
>>> import javax.faces.context.ExternalContext;
>>>
>>> import javax.servlet.http.HttpServletResponse;
>>>
>>>
>>> /**
>>> * <p> This class contains
>>> * {_at_link com.sun.jsftemplating.layout.descriptors.handler.Handler}
>>> * methods that perform navigation oriented actions.</p>
>>> *
>>> * @author Ken Paulsen (ken.paulsen_at_sun.com)
>>> */
>>> public class NavigationHandlers {
>>>
>>> /**
>>> * <p> Default Constructor.</p>
>>> */
>>> public NavigationHandlers() {
>>> }
>>>
>>> /**
>>> * <p> This handler returns a <code>UIViewRoot</code>. If the
>>> * <code>id</code> parameter is supplied it will return
>>> the requested
>>> * <code>UIViewRoot</code> (this may fail and cause an
>>> exception). If
>>> * the <code>id</code> is <em>not</em> supplied, it will
>>> return the
>>> * current <code>UIViewRoot</code>. The result will be
>>> returned in
>>> * an output parameter named <code>viewRoot</code>.</p>
>>> */
>>> @Handler(id="getUIViewRoot",
>>> input={
>>> @HandlerInput(name="id", type=String.class)
>>> },
>>> output={
>>> @HandlerOutput(name="viewRoot", type=UIViewRoot.class)
>>> })
>>> public void getUIViewRoot(HandlerContext context) {
>>> String pageName = (String) context.getInputValue("id");
>>> FacesContext ctx = context.getFacesContext();
>>> UIViewRoot root = null;
>>> if (pageName == null) {
>>> root = ctx.getViewRoot();
>>> } else {
>>> if (pageName.charAt(0) != '/') {
>>> // Ensure we start w/ a '/'
>>> pageName = "/" + pageName;
>>> }
>>> root = ctx.getApplication().getViewHandler().
>>> createView(ctx, pageName);
>>> }
>>> context.setOutputValue("viewRoot", root);
>>> }
>>>
>>> /**
>>> * <p> This method gives you a "resource URL" as defined by the
>>> * <code>ViewHandler</code>'s <code>getActionURL(String
>>> * url)</code> method.</p>
>>> *
>>> * @param handlerCtx The {_at_link HandlerContext}.
>>> */
>>> @Handler(id="getActionURL",
>>> input={
>>> @HandlerInput(name="url", type=String.class, required=true)
>>> },
>>> output={
>>> @HandlerOutput(name="url", type=String.class)
>>> })
>>> public static void getActionURL(HandlerContext handlerCtx) {
>>> String url = (String) handlerCtx.getInputValue("url");
>>> FacesContext ctx = handlerCtx.getFacesContext();
>>> handlerCtx.setOutputValue("url",
>>> ctx.getApplication().getViewHandler().
>>> getActionURL(ctx, url));
>>> }
>>> /**
>>> * <p> This method gives you a "resource URL" as defined by the
>>> * <code>ViewHandler</code>'s <code>getResourceURL(String
>>> * url)</code> method.</p>
>>> *
>>> * @param handlerCtx The {_at_link HandlerContext}.
>>> */
>>> @Handler(id="getResourceURL",
>>> input={
>>> @HandlerInput(name="url", type=String.class, required=true)
>>> },
>>> output={
>>> @HandlerOutput(name="url", type=String.class)
>>> })
>>> public static void getResourceURL(HandlerContext handlerCtx) {
>>> String url = (String) handlerCtx.getInputValue("url");
>>> FacesContext ctx = handlerCtx.getFacesContext();
>>> handlerCtx.setOutputValue("url",
>>> ctx.getApplication().getViewHandler().
>>> getResourceURL(ctx, url));
>>> }
>>> /**
>>> * <p> This handler navigates to the given page.
>>> <code>page</code> may
>>> * either be a <code>UIViewRoot</code> or a
>>> <code>String</code>
>>> * representing a <code>UIViewRoot</code>. Passing in a
>>> * <code>String</code> name of a <code>UIViewRoot</code>
>>> will always
>>> * create a new <code>UIViewRoot</code>. Passing in the
>>> * <code>UIViewRoot</code> provides an opportunity to
>>> customize the
>>> * <code>UIComponent</code> tree that will be displayed.</p>
>>> *
>>> * <p> The {_at_link #getUIViewRoot(HandlerContext)} handler
>>> provides a way
>>> * to obtain a <code>UIViewRoot</code>.</p>
>>> *
>>> * <p> Input value: "page" -- Type: <code>Object</code>
>>> (should be a
>>> * <code>String</code> or a <code>UIViewRoot</code>).</p>
>>> *
>>> * @param context The {_at_link HandlerContext}.
>>> */
>>> @Handler(id="navigate",
>>> input={
>>> @HandlerInput(name="page", type=Object.class, required=true)
>>> })
>>> public static void navigate(HandlerContext context) {
>>> Object page = context.getInputValue("page");
>>> UIViewRoot root = null;
>>> FacesContext ctx = context.getFacesContext();
>>> if (page instanceof String) {
>>> // Create a new UIViewRoot with the given id
>>> String strPage = (String) page;
>>> if (strPage.charAt(0) != '/') {
>>> // Ensure we start w/ a '/'
>>> strPage = "/" + strPage;
>>> }
>>> root = ctx.getApplication().getViewHandler().
>>> createView(ctx, strPage);
>>> } else if (page instanceof UIViewRoot) {
>>> // We recieved a UIViewRoot, use it...
>>> root = (UIViewRoot) page;
>>> } else {
>>> throw new IllegalArgumentException("Type '"
>>> + page.getClass().getName()
>>> + "' is not valid. It must be a String or UIViewRoot.");
>>> }
>>>
>>> // Set the UIViewRoot so that it will be displayed
>>> ctx.setViewRoot(root);
>>> }
>>>
>>> /**
>>> * <p> This handler redirects to the given page.</p>
>>> *
>>> * <p> Input value: "page" -- Type: <code>String</code></p>
>>> *
>>> * @param context The {_at_link HandlerContext}.
>>> */
>>> @Handler(id="redirect",
>>> input={
>>> @HandlerInput(name="page", type=String.class, required=true)
>>> })
>>> public static void redirect(HandlerContext context) {
>>> String page = (String) context.getInputValue("page");
>>> FacesContext ctx = context.getFacesContext();
>>> try {
>>> ctx.getExternalContext().redirect(page);
>>> ctx.responseComplete();
>>> } catch (IOException ex) {
>>> throw new RuntimeException(
>>> "Unable to navigate to page '" + page + "'!", ex);
>>> }
>>> }
>>>
>>> /**
>>> * <p> This handler encodes URL, and redirects to the given
>>> page.</p>
>>> *
>>> * <p> Input value: "page" -- Type: <code>String</code></p>
>>> *
>>> * @param context The {_at_link HandlerContext}.
>>> */
>>> @Handler(id="encoderedirect",
>>> input={
>>> @HandlerInput(name="page", type=String.class, required=true)
>>> })
>>> public static void encoderedirect(HandlerContext context) {
>>> String page = (String) context.getInputValue("page");
>>> ExternalContext ctx =
>>> context.getFacesContext().getExternalContext();
>>> HttpServletResponse response =
>>> (HttpServletResponse)ctx.getResponse();
>>> page = response.encodeRedirectURL(page);
>>> try {
>>> ctx.redirect(page);
>>> context.getFacesContext().responseComplete();
>>> } catch (IOException ex) {
>>> throw new RuntimeException(
>>> "Unable to navigate to page '" + page + "'!", ex);
>>> }
>>> }
>>>
>>> /**
>>> * <p> This handler forwards to the given page. Normally you
>>> will want
>>> * to do {_at_link #navigate} as that follows JSF patterns.
>>> This uses
>>> * the raw dispatcher forward mechanism (via the
>>> ExternalContext).</p>
>>> *
>>> * <p> Input value: "url" -- Type: <code>String</code></p>
>>> *
>>> * @param context The {_at_link HandlerContext}.
>>> */
>>> @Handler(id="dispatch",
>>> input={
>>> @HandlerInput(name="path", type=String.class, required=true)
>>> })
>>> public static void dispatch(HandlerContext context) {
>>> String path = (String) context.getInputValue("path");
>>> FacesContext ctx = context.getFacesContext();
>>> try {
>>> ctx.getExternalContext().dispatch(path);
>>> ctx.responseComplete();
>>> } catch (IOException ex) {
>>> throw new RuntimeException(
>>> "Unable to navigate to path '" + path + "'!", ex);
>>> }
>>> }
>>> }
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>>
>>> Index: NavigationHandlers.java
>>> ===================================================================
>>> RCS file:
>>> /cvs/jsftemplating/src/java/com/sun/jsftemplating/handlers/NavigationHandlers.java,v
>>>
>>> retrieving revision 1.5
>>> diff -c -r1.5 NavigationHandlers.java
>>> *** NavigationHandlers.java 16 Feb 2007 10:31:10 -0000 1.5
>>> --- NavigationHandlers.java 24 Feb 2007 15:46:09 -0000
>>> ***************
>>> *** 36,41 ****
>>> --- 36,44 ----
>>>
>>> import javax.faces.component.UIViewRoot;
>>> import javax.faces.context.FacesContext;
>>> + import javax.faces.context.ExternalContext;
>>> + + import javax.servlet.http.HttpServletResponse;
>>>
>>>
>>> /**
>>> ***************
>>> *** 191,196 ****
>>> --- 194,225 ----
>>> try {
>>> ctx.getExternalContext().redirect(page);
>>> ctx.responseComplete();
>>> + } catch (IOException ex) {
>>> + throw new RuntimeException(
>>> + "Unable to navigate to page '" + page + "'!", ex);
>>> + }
>>> + }
>>> + + /**
>>> + * <p> This handler encodes URL, and redirects to the given
>>> page.</p>
>>> + *
>>> + * <p> Input value: "page" -- Type: <code>String</code></p>
>>> + *
>>> + * @param context The {_at_link HandlerContext}.
>>> + */
>>> + @Handler(id="encoderedirect",
>>> + input={
>>> + @HandlerInput(name="page", type=String.class, required=true)
>>> + })
>>> + public static void encoderedirect(HandlerContext context) {
>>> + String page = (String) context.getInputValue("page");
>>> + ExternalContext ctx =
>>> context.getFacesContext().getExternalContext();
>>> + HttpServletResponse response =
>>> (HttpServletResponse)ctx.getResponse();
>>> + page = response.encodeRedirectURL(page);
>>> + context.setOutputValue("page", page);
>>> + try {
>>> + ctx.redirect(page);
>>> + context.getFacesContext().responseComplete();
>>> } catch (IOException ex) {
>>> throw new RuntimeException(
>>> "Unable to navigate to page '" + page + "'!", ex);
>>>
>>>