Author: knopp
Date: Sat Jul 28 06:21:24 2007
New Revision: 560540
URL: http://svn.apache.org/viewvc?view=rev&rev=560540
Log:
WICKET-30 - Javadoc, remember amount of trailing slashes, change separator from
( ) to |
Modified:
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java
Modified:
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java?view=diff&rev=560540&r1=560539&r2=560540
==============================================================================
---
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java
(original)
+++
wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java
Sat Jul 28 06:21:24 2007
@@ -36,6 +36,23 @@
/**
+ * An URL coding strategy that encodes the mount point, page parameters and
page
+ * instance information into the URL. The benefits compared to mounting page
+ * with [EMAIL PROTECTED] BookmarkablePageRequestTargetUrlCodingStrategy} are
that the
+ * mount point is preserved even after invoking listener interfaces (thus you
+ * don't lose bookmarkability after clicking links) and that for ajax only
pages
+ * the state is preserved on refresh.
+ * <p>
+ * The url with [EMAIL PROTECTED] HybridUrlCodingStrategy} looks like
+ * /mount/path/param1/value1(3) or /mount/path/param1/value1(3:2) where 3 is
+ * page Id and 2 is version number.
+ * <p>
+ * Also to preserve state on refresh with ajax-only pages the
+ * [EMAIL PROTECTED] HybridUrlCodingStrategy} does an immediate redirect after
hitting
+ * bookmarkable URL, e.g. it immediately redirects from /mount/path to
+ * /mount/path(3) where 3 is the next page id. This preserves the page instance
+ * on subsequent page refresh.
+ *
* @author Matej Knopp
*/
public class HybridUrlCodingStrategy extends
AbstractRequestTargetUrlCodingStrategy
@@ -56,11 +73,37 @@
pageClassRef = new WeakReference(pageClass);
}
+ /**
+ * Returns the amount of trailing slashes in the given string
+ *
+ * @param seq
+ * @return
+ */
+ private int getTrailingSlashesCount(CharSequence seq)
+ {
+ int count = 0;
+ for (int i = seq.length() - 1; i >= 0; --i)
+ {
+ if (seq.charAt(i) == '/')
+ {
+ ++count;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return count;
+ }
+ /**
+ * @see
org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy#decode(org.apache.wicket.request.RequestParameters)
+ */
public IRequestTarget decode(RequestParameters requestParameters)
{
String parametersFragment =
requestParameters.getPath().substring(getMountPath().length());
+ // try to extract page info
PageInfoExtraction extraction =
extractPageInfo(parametersFragment);
PageInfo pageInfo = extraction.getPageInfo();
@@ -68,6 +111,7 @@
Integer pageVersion = pageInfo != null ?
pageInfo.getVersionNumber() : null;
Integer pageId = pageInfo != null ? pageInfo.getPageId() : null;
+ // decode parameters
PageParameters parameters = new
PageParameters(decodeParameters(extraction
.getUrlAfterExtraction(),
requestParameters.getParameters()));
@@ -86,6 +130,11 @@
final String interfaceParameter = (String)parameters
.remove(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME);
+ // we need to remember the amount of trailing slashes after the
redirect
+ // (otherwise we'll break relative urls)
+ int originalUrlTrailingSlashesCount =
getTrailingSlashesCount(extraction
+ .getUrlAfterExtraction());
+
if (interfaceParameter != null)
{
// stateless listener interface
@@ -98,7 +147,7 @@
{
// bookmarkable page request
return new
HybridBookmarkablePageRequestTarget(pageMapName, (Class)pageClassRef.get(),
- parameters);
+ parameters,
originalUrlTrailingSlashesCount);
}
else
// hybrid url
@@ -115,14 +164,39 @@
}
else
{
+ // we didn't find the page, act as bookmarkable
page request -
+ // create new instance
return new
HybridBookmarkablePageRequestTarget(pageMapName, (Class)pageClassRef
- .get(), parameters);
+ .get(), parameters,
originalUrlTrailingSlashesCount);
}
}
}
+ /**
+ * Returns the number of traling slashes in the url when the page in
request
+ * target was created or null if the number can't be determined.
+ *
+ * @param requestTarget
+ * @return
+ */
+ private Integer getOriginalOriginalTrailingSlashesCount(IRequestTarget
requestTarget)
+ {
+ if (requestTarget instanceof ListenerInterfaceRequestTarget)
+ {
+ ListenerInterfaceRequestTarget target =
(ListenerInterfaceRequestTarget)requestTarget;
+ Page page = target.getPage();
+ return
(Integer)page.getMetaData(ORIGINAL_TRAILING_SLASHES_COUNT_METADATA_KEY);
+ }
+ return null;
+ }
+ /**
+ * Extracts the PageParameters from given request target
+ *
+ * @param requestTarget
+ * @return
+ */
private PageParameters getPageParameters(IRequestTarget requestTarget)
{
if (requestTarget instanceof BookmarkablePageRequestTarget)
@@ -142,6 +216,12 @@
}
}
+ /**
+ * Extracts the PageInfo from given request target
+ *
+ * @param requestTarget
+ * @return
+ */
private PageInfo getPageInfo(IRequestTarget requestTarget)
{
if (requestTarget instanceof BookmarkablePageRequestTarget)
@@ -170,22 +250,73 @@
}
- private static final PageParametersMetadataKey
PAGE_PARAMETERS_META_DATA_KEY = new PageParametersMetadataKey();
+ // meta data key to store PageParameters in page instance. This is used
to
+ // save the PageParameters that were
+ // used to create the page instance so that later we can used them when
+ // generating page URL
+ private static final PageParametersMetaDataKey
PAGE_PARAMETERS_META_DATA_KEY = new PageParametersMetaDataKey();
- private static class PageParametersMetadataKey extends MetaDataKey
+ private static class PageParametersMetaDataKey extends MetaDataKey
{
+ private static final long serialVersionUID = 1L;
+
/**
* Construct.
*/
- public PageParametersMetadataKey()
+ public PageParametersMetaDataKey()
{
super(PageParameters.class);
}
+ };
+
+ // used to store number of traling slashes in page url (prior the
PageInfo)
+ // part. This is necessary to maintain
+ // the exact number of slashes after page redirect, so that we don't
break
+ // things that rely on URL depth
+ // (other mounted URLs)
+ private static final OriginalUrlTrailingSlashesCountMetaDataKey
ORIGINAL_TRAILING_SLASHES_COUNT_METADATA_KEY = new
OriginalUrlTrailingSlashesCountMetaDataKey();
+ private static class OriginalUrlTrailingSlashesCountMetaDataKey extends
MetaDataKey
+ {
private static final long serialVersionUID = 1L;
- };
+ /**
+ * Construct.
+ */
+ public OriginalUrlTrailingSlashesCountMetaDataKey()
+ {
+ super(Integer.class);
+ }
+
+ }
+
+ /**
+ * Fix the amount of traling slashes in the speciffied buffer.
+ *
+ * @param buffer
+ * @param desiredCount
+ */
+ private void fixTrailingSlashes(AppendingStringBuffer buffer, int
desiredCount)
+ {
+ int current = getTrailingSlashesCount(buffer);
+ if (current > desiredCount)
+ {
+ buffer.setLength(buffer.length() - (current -
desiredCount));
+ }
+ else if (desiredCount > current)
+ {
+ int toAdd = desiredCount - current;
+ while (toAdd > 0)
+ {
+ buffer.append("/");
+ --toAdd;
+ }
+ }
+ }
+ /**
+ * @see
org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy#encode(org.apache.wicket.IRequestTarget)
+ */
public CharSequence encode(IRequestTarget requestTarget)
{
if (matches(requestTarget) == false)
@@ -200,9 +331,19 @@
url.append(getMountPath());
appendParameters(url, parameters);
+ // check whether we know if the initial URL ended with slash
+ Integer trailingSlashesCount =
getOriginalOriginalTrailingSlashesCount(requestTarget);
+ if (trailingSlashesCount != null)
+ {
+ fixTrailingSlashes(url,
trailingSlashesCount.intValue());
+ }
+
return addPageInfo(url.toString(), pageInfo);
}
+ /**
+ * @see
org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy#matches(org.apache.wicket.IRequestTarget)
+ */
public boolean matches(IRequestTarget requestTarget)
{
if (requestTarget instanceof BookmarkablePageRequestTarget)
@@ -219,6 +360,12 @@
return false;
}
+ /**
+ * Class that encapsulates [EMAIL PROTECTED] PageInfo} instance and the
URL part prior
+ * the PageInfo part
+ *
+ * @author Matej Knopp
+ */
protected static class PageInfoExtraction
{
private final String urlAfterExtraction;
@@ -262,9 +409,9 @@
*/
protected PageInfoExtraction extractPageInfo(String url)
{
- int lastIndexLeft = url.lastIndexOf(getBeginSeparator());
int lastIndexRight = url.lastIndexOf(getEndSeparator());
- if (lastIndexLeft != -1 && lastIndexRight != -1 &&
lastIndexLeft < lastIndexRight &&
+ int lastIndexLeft = url.lastIndexOf(getBeginSeparator(),
lastIndexRight - 1);
+ if (lastIndexLeft != -1 && lastIndexRight != -1 &&
lastIndexRight - lastIndexLeft > 0 &&
lastIndexRight == url.length() - 1)
{
String infoSubstring = url.substring(lastIndexLeft + 1,
lastIndexRight);
@@ -279,14 +426,20 @@
protected char getBeginSeparator()
{
- return '(';
+ return '|';
}
protected char getEndSeparator()
{
- return ')';
+ return '|';
}
+ /**
+ * Encodes the PageInfo part to the URL
+ * @param url
+ * @param pageInfo
+ * @return
+ */
protected String addPageInfo(String url, PageInfo pageInfo)
{
if (pageInfo != null)
@@ -449,7 +602,7 @@
// :pageMapName
return new PageInfo(null, null, segments[1]);
}
- else
+ else if (segments.length == 3)
{
if (segments[2].length() == 0 &&
isNumber(segments[1]))
{
@@ -469,25 +622,36 @@
};
+ /**
+ * BookmarkablePage request target that does a redirect after
bookmarkable page was rendered
+ * (only if the bookmarkable page is stateful though)
+ * @author Matej Knopp
+ */
private static class HybridBookmarkablePageRequestTarget extends
BookmarkablePageRequestTarget
{
+ private final int originalUrlTrailingSlashesCount;
+
/**
* Construct.
*
* @param pageMapName
* @param pageClass
* @param pageParameters
+ * @param originalUrlTrailingSlashesCount
*/
public HybridBookmarkablePageRequestTarget(String pageMapName,
Class pageClass,
- PageParameters pageParameters)
+ PageParameters pageParameters, int
originalUrlTrailingSlashesCount)
{
super(pageMapName, pageClass, pageParameters);
+ this.originalUrlTrailingSlashesCount =
originalUrlTrailingSlashesCount;
}
protected Page newPage(Class pageClass, RequestCycle
requestCycle)
{
Page page = super.newPage(pageClass, requestCycle);
page.setMetaData(PAGE_PARAMETERS_META_DATA_KEY,
getPageParameters());
+
page.setMetaData(ORIGINAL_TRAILING_SLASHES_COUNT_METADATA_KEY, new Integer(
+ originalUrlTrailingSlashesCount));
return page;
}