Author: knopp Date: Thu Sep 18 08:09:06 2008 New Revision: 696670 URL: http://svn.apache.org/viewvc?rev=696670&view=rev Log: mounted pages
Added: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/MountedEncoder.java (with props) wicket/sandbox/knopp/experimental/wicket/src/test/java/org/apache/_wicket/request/encoder/MountedEncoderTest.java (with props) Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/BookmarkableEncoder.java Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/BookmarkableEncoder.java URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/BookmarkableEncoder.java?rev=696670&r1=696669&r2=696670&view=diff ============================================================================== --- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/BookmarkableEncoder.java (original) +++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/BookmarkableEncoder.java Thu Sep 18 08:09:06 2008 @@ -68,6 +68,10 @@ */ public BookmarkableEncoder(PageParametersEncoder pageParametersEncoder) { + if (pageParametersEncoder == null) + { + throw new IllegalArgumentException("Argument 'pageParametersEncoder' may not be null."); + } this.pageParametersEncoder = pageParametersEncoder; } Added: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/MountedEncoder.java URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/MountedEncoder.java?rev=696670&view=auto ============================================================================== --- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/MountedEncoder.java (added) +++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/MountedEncoder.java Thu Sep 18 08:09:06 2008 @@ -0,0 +1,267 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache._wicket.request.encoder; + +import java.lang.ref.WeakReference; + +import org.apache._wicket.IComponent; +import org.apache._wicket.IPage; +import org.apache._wicket.PageParameters; +import org.apache._wicket.request.RequestHandler; +import org.apache._wicket.request.Url; +import org.apache._wicket.request.encoder.info.ComponentInfo; +import org.apache._wicket.request.encoder.info.PageComponentInfo; +import org.apache._wicket.request.encoder.info.PageInfo; +import org.apache._wicket.request.encoder.parameters.PageParametersEncoder; +import org.apache._wicket.request.encoder.parameters.SimplePageParametersEncoder; +import org.apache._wicket.request.handler.impl.BookmarkableListenerInterfaceRequestHandler; +import org.apache._wicket.request.handler.impl.BookmarkablePageRequestHandler; +import org.apache._wicket.request.handler.impl.ListenerInterfaceRequestHandler; +import org.apache._wicket.request.handler.impl.RenderPageRequestHandler; +import org.apache._wicket.request.request.Request; +import org.apache.wicket.RequestListenerInterface; + +/** + * Decodes and encodes the following URLs: + * + * <pre> + * Page Class - Render (BookmarkablePageRequestHandler for mounted pages) + * /mount/point + * /mount/point?pageMap + * (these will redirect to hybrid alternative if page is not stateless) + * + * IPage Instance - Render Hybrid (RenderPageRequestHandler for mounted pages) + * /mount/point?2 + * /mount/point?2.4 + * /mount/point?pageMap.2.4 + * + * IPage Instance - Bookmarkable Listener (BookmarkableListenerInterfaceRequestHandler for mounted pages) + * /mount/point?2-click-foo-bar-baz + * /mount/point?2.4-click-foo-bar-baz + * /mount/point?pageMap.2.4-click-foo-bar-baz + * /mount/point?2.4-click.1-foo-bar-baz (1 is behavior index) + * (these will redirect to hybrid if page is not stateless) + * </pre> + * + * @author Matej Knopp + */ +public class MountedEncoder extends AbstractEncoder +{ + private final PageParametersEncoder pageParametersEncoder; + private final String[] mountSegments; + + /** bookmarkable page class. */ + protected final WeakReference<Class<? extends IPage>> pageClass; + + + /** + * Construct. + * + * @param mountPath + * @param pageClass + * @param pageParametersEncoder + */ + public MountedEncoder(String mountPath, Class<? extends IPage> pageClass, + PageParametersEncoder pageParametersEncoder) + { + if (pageParametersEncoder == null) + { + throw new IllegalArgumentException("Argument 'pageParametersEncoder' may not be null."); + } + if (pageClass == null) + { + throw new IllegalArgumentException("Argument 'pageClass' may not be null."); + } + if (mountPath == null) + { + throw new IllegalArgumentException("Argument 'mountPath' may not be null."); + } + this.pageParametersEncoder = pageParametersEncoder; + this.pageClass = new WeakReference<Class<? extends IPage>>(pageClass); + this.mountSegments = getMountSegments(mountPath); + } + + private String[] getMountSegments(String mountPath) + { + if (mountPath.startsWith("/")) + { + mountPath = mountPath.substring(1); + } + Url url = Url.parse(mountPath); + + if (url.getSegments().isEmpty()) + { + throw new IllegalArgumentException("Mount path must have at least one segment."); + } + + String[] res = new String[url.getSegments().size()]; + for (int i = 0; i < res.length; ++i) + { + res[i] = url.getSegments().get(i); + } + return res; + } + + /** + * Construct. + * + * @param mountPath + * @param pageClass + */ + public MountedEncoder(String mountPath, Class<? extends IPage> pageClass) + { + this(mountPath, pageClass, new SimplePageParametersEncoder()); + } + + private RequestHandler processBookmarkable(String pageMapName, + Class<? extends IPage> pageClass, PageParameters pageParameters) + { + IPage page = newPageInstance(pageMapName, pageClass, pageParameters); + return new RenderPageRequestHandler(page); + } + + private RequestHandler processHybrid(PageInfo pageInfo, Class<? extends IPage> pageClass, + PageParameters pageParameters) + { + IPage page = getPageInstance(pageInfo, pageClass, pageParameters); + return new RenderPageRequestHandler(page); + } + + private RequestHandler processListener(PageComponentInfo pageComponentInfo, + Class<? extends IPage> pageClass, PageParameters pageParameters) + { + PageInfo pageInfo = pageComponentInfo.getPageInfo(); + ComponentInfo componentInfo = pageComponentInfo.getComponentInfo(); + + IPage page = getPageInstance(pageInfo, pageClass, pageParameters, true); + IComponent component = getComponent(page, componentInfo.getComponentPath()); + RequestListenerInterface listenerInterface = requestListenerInterfaceFromString(componentInfo.getListenerInterface()); + + return new ListenerInterfaceRequestHandler(page, component, listenerInterface, + componentInfo.getBehaviorIndex()); + } + + public RequestHandler decode(Request request) + { + Url url = request.getUrl(); + + // check if the URL is long enough and starts with the proper segments + if (url.getSegments().size() >= mountSegments.length && urlStartsWith(url, mountSegments)) + { + // try to extract page and component information from URL + PageComponentInfo info = getPageComponentInfo(url); + + Class<? extends IPage> pageClass = this.pageClass.get(); + + // extract the PageParameters from URL if there are any + PageParameters pageParameters = extractPageParameters(url, + request.getRequestParameters(), 3, pageParametersEncoder); + + if (info == null || info.getPageInfo().getPageId() == null) + { + // if there are is no page instance information (only page map name - optionally) + // then this is a simple bookmarkable URL + String pageMap = info != null ? info.getPageInfo().getPageMapName() : null; + return processBookmarkable(pageMap, pageClass, pageParameters); + } + else if (info.getPageInfo().getPageId() != null && info.getComponentInfo() == null) + { + // if there is page instance ifnromation in the URL but no component and listener + // interface then this is a hybrid URL - we need to try to reuse existing cpage + // instance + return processHybrid(info.getPageInfo(), pageClass, pageParameters); + } + else if (info.getComponentInfo() != null) + { + // with both page instance and component+listener this is a listener interface URL + return processListener(info, pageClass, pageParameters); + } + } + return null; + } + + private Url newUrl(Class<? extends IPage> pageClass) + { + Url url = new Url(); + + for (String s : mountSegments) + { + url.getSegments().add(s); + } + + return url; + } + + public Url encode(RequestHandler requestHandler) + { + if (requestHandler instanceof BookmarkablePageRequestHandler) + { + // simple bookmarkable URL with no page instance information + BookmarkablePageRequestHandler handler = (BookmarkablePageRequestHandler)requestHandler; + Url url = newUrl(handler.getPageClass()); + + PageInfo info = new PageInfo(null, null, handler.getPageMapName()); + encodePageComponentInfo(url, new PageComponentInfo(info, null)); + return encodePageParameters(url, handler.getPageParameters(), pageParametersEncoder); + } + else if (requestHandler instanceof RenderPageRequestHandler) + { + // possibly hybrid URL - bookmarkable URL with page instance information + // but only allowed if the page was created by bookamarkable URL + + IPage page = ((RenderPageRequestHandler)requestHandler).getPage(); + + Url url = newUrl(page.getClass()); + PageInfo info = null; + if (!page.isPageStateless()) + { + info = new PageInfo(page); + encodePageComponentInfo(url, new PageComponentInfo(info, null)); + } + return encodePageParameters(url, page.getPageParameters(), pageParametersEncoder); + + } + else if (requestHandler instanceof BookmarkableListenerInterfaceRequestHandler) + { + // listener interface URL with page class information + BookmarkableListenerInterfaceRequestHandler handler = (BookmarkableListenerInterfaceRequestHandler)requestHandler; + IPage page = handler.getPage(); + PageInfo pageInfo = new PageInfo(page); + ComponentInfo componentInfo = new ComponentInfo( + requestListenerInterfaceToString(handler.getListenerInterface()), + handler.getComponent().getPath(), handler.getBehaviorIndex()); + Url url = newUrl(page.getClass()); + encodePageComponentInfo(url, new PageComponentInfo(pageInfo, componentInfo)); + return encodePageParameters(url, page.getPageParameters(), pageParametersEncoder); + } + + return null; + } + + public int getMachingSegmentsCount(Request request) + { + if (urlStartsWith(request.getUrl(), mountSegments)) + { + return mountSegments.length; + } + else + { + return 0; + } + } + +} Propchange: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/_wicket/request/encoder/MountedEncoder.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: wicket/sandbox/knopp/experimental/wicket/src/test/java/org/apache/_wicket/request/encoder/MountedEncoderTest.java URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/test/java/org/apache/_wicket/request/encoder/MountedEncoderTest.java?rev=696670&view=auto ============================================================================== --- wicket/sandbox/knopp/experimental/wicket/src/test/java/org/apache/_wicket/request/encoder/MountedEncoderTest.java (added) +++ wicket/sandbox/knopp/experimental/wicket/src/test/java/org/apache/_wicket/request/encoder/MountedEncoderTest.java Thu Sep 18 08:09:06 2008 @@ -0,0 +1,378 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache._wicket.request.encoder; + +import org.apache._wicket.IComponent; +import org.apache._wicket.IPage; +import org.apache._wicket.MockPage; +import org.apache._wicket.PageParameters; +import org.apache._wicket.request.RequestHandler; +import org.apache._wicket.request.RequestHandlerEncoder; +import org.apache._wicket.request.Url; +import org.apache._wicket.request.handler.impl.BookmarkableListenerInterfaceRequestHandler; +import org.apache._wicket.request.handler.impl.BookmarkablePageRequestHandler; +import org.apache._wicket.request.handler.impl.ListenerInterfaceRequestHandler; +import org.apache._wicket.request.handler.impl.RenderPageRequestHandler; +import org.apache.wicket.markup.html.link.ILinkListener; + + +/** + * @author Matej Knopp + */ +public class MountedEncoderTest extends AbstractEncoderTest +{ + + /** + * Construct. + */ + public MountedEncoderTest() + { + } + + private MountedEncoder encoder = new MountedEncoder("/some/mount/path", MockPage.class) + { + @Override + protected EncoderContext getContext() + { + return context; + } + }; + + /** + * + */ + public void testDecode1() + { + Url url = Url.parse("some/mount/path"); + RequestHandler handler = encoder.decode(getRequest(url)); + + assertTrue(handler instanceof RenderPageRequestHandler); + IPage page = ((RenderPageRequestHandler)handler).getPage(); + + assertEquals(0, page.getPageParameters().getIndexedParamsCount()); + assertTrue(page.getPageParameters().getNamedParameterKeys().isEmpty()); + } + + /** + * + */ + public void testDecode2() + { + Url url = Url.parse("some/mount/path/indexed1?a=b&b=c"); + RequestHandler handler = encoder.decode(getRequest(url)); + + assertTrue(handler instanceof RenderPageRequestHandler); + IPage page = ((RenderPageRequestHandler)handler).getPage(); + + PageParameters p = page.getPageParameters(); + assertEquals(1, p.getIndexedParamsCount()); + assertEquals("indexed1", p.getIndexedParameter(0).toString()); + + assertEquals(2, p.getNamedParameterKeys().size()); + assertEquals("b", p.getNamedParameter("a").toString()); + assertEquals("c", p.getNamedParameter("b").toString()); + } + + /** + * + */ + public void testDecode3() + { + Url url = Url.parse("some/mount/path?15"); + RequestHandler handler = encoder.decode(getRequest(url)); + + assertTrue(handler instanceof RenderPageRequestHandler); + IPage page = ((RenderPageRequestHandler)handler).getPage(); + checkPage(page, 15, 0, null); + } + + /** + * + */ + public void testDecode4() + { + Url url = Url.parse("some/mount/path/i1/i2?abc.15.5&a=b&b=c"); + RequestHandler handler = encoder.decode(getRequest(url)); + + assertTrue(handler instanceof RenderPageRequestHandler); + IPage page = ((RenderPageRequestHandler)handler).getPage(); + checkPage(page, 15, 5, "abc"); + + PageParameters p = page.getPageParameters(); + assertEquals(2, p.getIndexedParamsCount()); + assertEquals("i1", p.getIndexedParameter(0).toString()); + assertEquals("i2", p.getIndexedParameter(1).toString()); + + assertEquals(2, p.getNamedParameterKeys().size()); + assertEquals("b", p.getNamedParameter("a").toString()); + assertEquals("c", p.getNamedParameter("b").toString()); + } + + /** + * + */ + public void testDecode5() + { + Url url = Url.parse("some/mount/path?15-ILinkListener-foo-bar"); + RequestHandler handler = encoder.decode(getRequest(url)); + + assertTrue(handler instanceof ListenerInterfaceRequestHandler); + + ListenerInterfaceRequestHandler h = (ListenerInterfaceRequestHandler)handler; + + IPage page = h.getPage(); + checkPage(page, 15, 0, null); + + assertEquals(ILinkListener.INTERFACE, h.getListenerInterface()); + assertEquals("foo:bar", h.getComponent().getPath()); + assertNull(h.getBehaviorIndex()); + } + + /** + * + */ + public void testDecode6() + { + Url url = Url.parse("some/mount/path/i1/i2?abc.15.5-ILinkListener-foo-bar&a=b&b=c"); + RequestHandler handler = encoder.decode(getRequest(url)); + + assertTrue(handler instanceof ListenerInterfaceRequestHandler); + ListenerInterfaceRequestHandler h = (ListenerInterfaceRequestHandler)handler; + + IPage page = h.getPage(); + checkPage(page, 15, 5, "abc"); + + assertEquals(ILinkListener.INTERFACE, h.getListenerInterface()); + assertEquals("foo:bar", h.getComponent().getPath()); + + PageParameters p = page.getPageParameters(); + assertEquals(2, p.getIndexedParamsCount()); + assertEquals("i1", p.getIndexedParameter(0).toString()); + assertEquals("i2", p.getIndexedParameter(1).toString()); + + assertEquals(2, p.getNamedParameterKeys().size()); + assertEquals("b", p.getNamedParameter("a").toString()); + assertEquals("c", p.getNamedParameter("b").toString()); + } + + /** + * + */ + public void testDecode7() + { + Url url = Url.parse("some/mount/path?15-ILinkListener.4-foo-bar"); + RequestHandler handler = encoder.decode(getRequest(url)); + + assertTrue(handler instanceof ListenerInterfaceRequestHandler); + + ListenerInterfaceRequestHandler h = (ListenerInterfaceRequestHandler)handler; + + IPage page = h.getPage(); + checkPage(page, 15, 0, null); + + assertEquals(ILinkListener.INTERFACE, h.getListenerInterface()); + assertEquals("foo:bar", h.getComponent().getPath()); + assertEquals((Object)4, h.getBehaviorIndex()); + } + + /** + * + */ + public void testEncode1() + { + RequestHandler handler = new BookmarkablePageRequestHandler(MockPage.class, null, + new PageParameters()); + Url url = encoder.encode(handler); + assertEquals("some/mount/path", url.toString()); + } + + /** + * + */ + public void testEncode2() + { + PageParameters parameters = new PageParameters(); + parameters.setIndexedParameter(0, "i1"); + parameters.setIndexedParameter(1, "i2"); + parameters.setNamedParameter("a", "b"); + parameters.setNamedParameter("b", "c"); + RequestHandler handler = new BookmarkablePageRequestHandler(MockPage.class, null, + parameters); + Url url = encoder.encode(handler); + assertEquals("some/mount/path/i1/i2?a=b&b=c", url.toString()); + } + + /** + * + */ + public void testEncode3() + { + PageParameters parameters = new PageParameters(); + parameters.setIndexedParameter(0, "i1"); + parameters.setIndexedParameter(1, "i2"); + parameters.setNamedParameter("a", "b"); + parameters.setNamedParameter("b", "c"); + + RequestHandler handler = new BookmarkablePageRequestHandler(MockPage.class, "abc", + parameters); + Url url = encoder.encode(handler); + + assertEquals("some/mount/path/i1/i2?abc&a=b&b=c", url.toString()); + } + + /** + * + */ + public void testEncode4() + { + MockPage page = new MockPage(15, 5, "abc"); + page.getPageParameters().setIndexedParameter(0, "i1"); + page.getPageParameters().setIndexedParameter(1, "i2"); + page.getPageParameters().setNamedParameter("a", "b"); + page.getPageParameters().setNamedParameter("b", "c"); + page.setCreatedBookmarkable(true); + + RequestHandler handler = new RenderPageRequestHandler(page); + Url url = encoder.encode(handler); + + assertEquals("some/mount/path/i1/i2?abc.15.5&a=b&b=c", url.toString()); + } + + /** + * + */ + public void testEncode5() + { + MockPage page = new MockPage(15, 5, "abc"); + page.getPageParameters().setIndexedParameter(0, "i1"); + page.getPageParameters().setIndexedParameter(1, "i2"); + page.getPageParameters().setNamedParameter("a", "b"); + page.getPageParameters().setNamedParameter("b", "c"); + + page.setCreatedBookmarkable(false); + + RequestHandler handler = new RenderPageRequestHandler(page); + Url url = encoder.encode(handler); + + // mounted pages must render mounted url even for page that has not been created by + // bookmarkable + // URL + + assertEquals("some/mount/path/i1/i2?abc.15.5&a=b&b=c", url.toString()); + } + + /** + * + */ + public void testEncode6() + { + MockPage page = new MockPage(15, 5, "abc"); + page.getPageParameters().setIndexedParameter(0, "i1"); + page.getPageParameters().setIndexedParameter(1, "i2"); + page.getPageParameters().setNamedParameter("a", "b"); + page.getPageParameters().setNamedParameter("b", "c"); + + // shouldn't make any difference for BookmarkableListenerInterfaceRequestHandler, + // as this explicitely says the url must be bookmarkable + page.setCreatedBookmarkable(false); + + IComponent c = page.get("foo:bar"); + + RequestHandler handler = new BookmarkableListenerInterfaceRequestHandler(page, c, + ILinkListener.INTERFACE); + + Url url = encoder.encode(handler); + + assertEquals("some/mount/path/i1/i2?abc.15.5-ILinkListener-foo-bar&a=b&b=c", url.toString()); + } + + /** + * + */ + public void testEncode7() + { + MockPage page = new MockPage(15, 5, "abc"); + page.getPageParameters().setIndexedParameter(0, "i1"); + page.getPageParameters().setIndexedParameter(1, "i2"); + page.getPageParameters().setNamedParameter("a", "b"); + page.getPageParameters().setNamedParameter("b", "c"); + + // shouldn't make any difference for BookmarkableListenerInterfaceRequestHandler, + // as this explicitely says the url must be bookmarkable + page.setCreatedBookmarkable(false); + + IComponent c = page.get("foo:bar"); + + RequestHandler handler = new BookmarkableListenerInterfaceRequestHandler(page, c, + ILinkListener.INTERFACE, 4); + + Url url = encoder.encode(handler); + + assertEquals("some/mount/path/i1/i2?abc.15.5-ILinkListener.4-foo-bar&a=b&b=c", + url.toString()); + } + + + /** + * + */ + public void testEncode8() + { + MockPage page = new MockPage(15, 5, "abc"); + page.setBookmarkable(true); + page.setCreatedBookmarkable(true); + page.setPageStateless(true); + + RequestHandler handler = new RenderPageRequestHandler(page); + + Url url = encoder.encode(handler); + + assertEquals("some/mount/path", url.toString()); + } + + /** + * + */ + public void testConstruct1() + { + try + { + RequestHandlerEncoder e = new MountedEncoder("", MockPage.class); + assertFalse(true); + } + catch (IllegalArgumentException e) + { + // ok + } + } + + /** + * + */ + public void testConstruct2() + { + try + { + RequestHandlerEncoder e = new MountedEncoder("/", MockPage.class); + assertFalse(true); + } + catch (IllegalArgumentException e) + { + // ok + } + } +} Propchange: wicket/sandbox/knopp/experimental/wicket/src/test/java/org/apache/_wicket/request/encoder/MountedEncoderTest.java ------------------------------------------------------------------------------ svn:mime-type = text/plain