I agree that I'm a bit unhappy with the current API, but we now have a
larger issue: backwards compatibility (from 5.1 to 5.2).  We may
eventually deprecate the current approach and create an improved
approach and maintain both for one release.

On Mon, Feb 8, 2010 at 12:31 PM, Josh Canfield <joshcanfi...@gmail.com> wrote:
> Hi, I spent some time recently digging around in the URLRewrite code
> to track down the bug with forms. I had used this interface previously
> but didn't stop to think about it until I was knee deep in the code.
>
> I'm curious about the inspiration for implementation and interface. It
> really makes no sense to me that we are editing a Request for outgoing
> links, or that we need a context for incoming requests. The incoming
> requests can't have the Page/ComponentEvent Parameters because
> rewritten urls are often not going to match a page/component event.
> The URLRewriteContext seems like an unnecessary crutch.
>
> The interface can be significantly simplified to just:
>
> public interface URIRewriteWorker {
>    /**
>     * Incoming request. Does not contain the servlet context.
>     **/
>    String rewrite(String uri);
>
>    /**
>     * Outgoing page render link. Contains the servlet context, if not
> deployed as the root context
>     **/
>    String rewrite(String uri, PageRenderRequestParameters params);
>
>    /**
>     * Outgoing component event render link. Contains the servlet
> context, if not deployed as the root context
>     **/
>    String rewrite(String uri, ComponentEventRequestParameters params);
> }
>
> Although, if Link had set methods for the the URI, and remove methods
> for the parameters we could just use the LinkCreationListener for the
> outgoing half of the API.
>
> I've included the code below with an example. If you find a defect
> please let me know. I'm using this in my own projects.
>
> // From AppModule, add a simple rewrite.
> public static void
> contributeURIRewriteInvoker(OrderedConfiguration<URIRewriteWorker>
> config) {
>        config.add("SimpleRewrite",
>                new URIRewriteWorker() {
>                    public String rewrite(String uri) {
>                        final String s = "request=yes";
>                        return addParam(uri, s);
>                    }
>
>                    public String rewrite(String uri,
> PageRenderRequestParameters params) {
>                        return addParam(uri, "page=yes");
>                    }
>
>                    public String rewrite(String uri,
> ComponentEventRequestParameters params) {
>                        return addParam(uri, "event=yes");
>                    }
>
>                    private String addParam(String uri, String s) {
>                        String sep = uri.indexOf("?") != -1 ? "&" : "?";
>                        return uri + sep + s;
>                    }
>                }
>        );
>    }
>
> /**
>  * Implements the hooks to catch incoming and outgoing URIs.
>  **/
> public class URIRewriteInvokerImpl implements URIRewriteInvoker {
>    private final List<URIRewriteWorker> _workers;
>    private final HttpServletRequest _servletRequest;
>    private final Response _response;
>
>    public URIRewriteInvokerImpl(List<URIRewriteWorker> workers,
>                                 HttpServletRequest servletRequest,
>                                 Response response
>    ) {
>        _workers = workers;
>        _servletRequest = servletRequest;
>        _response = response;
>    }
>
>    public boolean service(Request request, Response response,
> RequestHandler handler) throws IOException {
>        // Support rewriting query params
>        final String startURI = request.getPath() + '?' +
> _servletRequest.getQueryString();
>        String uri = startURI;
>        for (URIRewriteWorker worker : _workers) {
>            uri = worker.rewrite(uri);
>            if (uri == null) {
>                throw new NullPointerException("URIRewriteInvoker:
> worker returned null uri for " + startURI);
>            }
>        }
>        if (!startURI.equals(uri)) {
>            // build modified request
>            request = new RewriteRequest(uri, request);
>        }
>
>        return handler.service(request, response);
>    }
>
>    public void advise(Invocation invocation) {
>        // let the method create the link.
>        invocation.proceed();
>
>        // give the workers a chance to change it
>        final Link link = (Link) invocation.getResult();
>        String startURI, uri;
>        startURI = uri = link.toAbsoluteURI();
>
>        boolean forForm = false; // hold this for later.
>        if (invocation.getMethodName().equals("createPageRenderLink")) {
>            for (URIRewriteWorker worker : _workers) {
>                uri = worker.rewrite(uri,
> (PageRenderRequestParameters) invocation.getParameter(0));
>            }
>        } else {
>            forForm = (Boolean) invocation.getParameter(1);
>            for (URIRewriteWorker worker : _workers) {
>                uri = worker.rewrite(uri,
> (ComponentEventRequestParameters) invocation.getParameter(0));
>            }
>        }
>
>        if (!startURI.equals(uri)) {
>            final int q = uri.indexOf("?");
>            final String query = q == -1 ? null : uri.substring(q + 1);
>            // The link doesn't need query params in the uri
>            if (q != -1) {
>                uri = uri.substring(0, q);
>            }
>            // LinkImpl is internal, but I don't want to write a new one...
>            final Link newLink = new LinkImpl(uri, false, forForm,
> _response, null);
>
>            // Extract params from the uri and stuff them back into the link
>            if (query != null) {
>                String[] params = query.split("&");
>                for (String param : params) {
>                    final String[] parts = param.split("=");
>                    newLink.addParameter(parts[0], parts[1]);
>                }
>            }
>
>            invocation.overrideResult(newLink);
>        }
>    }
>
>    /**
>     * We override the uri, so take over the request parameters and path.
>     */
>    private class RewriteRequest extends DelegatingRequest {
>        private URI _overrideURI;
>        private Map<String, Object> _parameters;
>
>        public RewriteRequest(String uri, Request request) {
>            super(request);
>            try {
>                _overrideURI = new URI(uri);
>            } catch (URISyntaxException e) {
>                throw new RuntimeException("Failed parsing uri: " + uri, e);
>            }
>        }
>
>       �...@override
>        public String getParameter(String name) {
>            if (_parameters == null) parseParameters();
>            final Object o = _parameters.get(name);
>            if (o == null) return null;
>            if (o instanceof ArrayList) {
>               �...@suppresswarnings("unchecked")
>                final ArrayList<String> strings = (ArrayList<String>) o;
>                return strings.get(0);
>            }
>            return (String) o;
>        }
>
>       �...@override
>        public List<String> getParameterNames() {
>            if (_parameters == null) parseParameters();
>            return new ArrayList<String>(_parameters.keySet());
>        }
>
>       �...@override
>        public String[] getParameters(String name) {
>            if (_parameters == null) parseParameters();
>            final Object o = _parameters.get(name);
>            if (o == null) return null;
>
>            if (o instanceof ArrayList) {
>               �...@suppresswarnings("unchecked")
>                ArrayList<String> list = ((ArrayList<String>) o);
>                return list.toArray(new String[list.size()]);
>            }
>            return new String[]{(String) o};
>        }
>
>       �...@override
>        public String getPath() {
>            return _overrideURI.getPath();
>        }
>
>        private void parseParameters() {
>            final String query = _overrideURI.getQuery();
>            _parameters = new HashMap<String, Object>();
>            if (query != null && !query.equals("")) {
>                String[] params = query.split("&");
>                for (String param : params) {
>                    final String[] parts = param.split("=");
>                    Object o = _parameters.get(parts[0]);
>
>                    if (o instanceof String) {
>                        final ArrayList<String> list = new ArrayList<String>();
>                        list.add((String) o);
>                        list.add(parts[0]);
>                        o = list;
>                    } else if (o instanceof ArrayList) {
>                       �...@suppresswarnings("unchecked")
>                        final ArrayList<String> strings = (ArrayList<String>) 
> o;
>                        strings.add(parts[0]);
>                    } else {
>                        // for example ?x=1&y&z=2 y has no value
>                        if (parts.length > 1) {
>                            o = parts[1];
>                        } else {
>                            o = null;
>                        }
>                    }
>
>                    _parameters.put(parts[0], o);
>                }
>            }
>        }
>    }
> }
>
> // Add the hook for request handler and advise the
> CompentEventLinkEncoder (goes in the LibModule, or AppModule)
>
>    public void
> contributeRequestHandler(OrderedConfiguration<RequestFilter>
> configuration,
>                                         URIRewriteInvoker urlRewrite
>    ) {
>        configuration.add("URIRewriteInvoker", urlRewrite);
>    }
>
>   �...@match("ComponentEventLinkEncoder")
>    public static void adviseURIRewriteService(
>            MethodAdviceReceiver receiver,
>            URIRewriteInvoker urlRewrite) throws Exception {
>
>        Class<ComponentEventLinkEncoder> clasz =
> ComponentEventLinkEncoder.class;
>
>        Method createPageRenderLink =
>                clasz.getMethod("createPageRenderLink",
> PageRenderRequestParameters.class);
>        Method createComponentEventLink =
>                clasz.getMethod("createComponentEventLink",
> ComponentEventRequestParameters.class, boolean.class);
>        receiver.adviseMethod(createComponentEventLink, urlRewrite);
>        receiver.adviseMethod(createPageRenderLink, urlRewrite);
>    }
>
>
> Josh
>
> --
> --
> http://www.bodylabgym.com - a private, by appointment only, one-on-one
> health and fitness facility.
> --
> http://www.ectransition.com - Quality Electronic Cigarettes at a
> reasonable price!
> --
> TheDailyTube.com. Sign up and get the best new videos on the internet
> delivered fresh to your inbox.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
> For additional commands, e-mail: users-h...@tapestry.apache.org
>
>



-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to