You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by an...@apache.org on 2011/01/02 11:32:44 UTC

svn commit: r1054381 - in /lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java: src/org/apache/lenya/cms/linking/ test/org/apache/lenya/cms/linking/

Author: andreas
Date: Sun Jan  2 10:32:43 2011
New Revision: 1054381

URL: http://svn.apache.org/viewvc?rev=1054381&view=rev
Log:
Improve relative URI rewriting (code simplification, better correctness).

Added:
    lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/UriUtil.java
    lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/UriUtilTest.java
Modified:
    lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/OutgoingLinkRewriter.java
    lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/OutgoingLinkRewriterTest.java

Modified: lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/OutgoingLinkRewriter.java
URL: http://svn.apache.org/viewvc/lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/OutgoingLinkRewriter.java?rev=1054381&r1=1054380&r2=1054381&view=diff
==============================================================================
--- lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/OutgoingLinkRewriter.java (original)
+++ lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/OutgoingLinkRewriter.java Sun Jan  2 10:32:43 2011
@@ -19,7 +19,6 @@ package org.apache.lenya.cms.linking;
 
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -40,7 +39,6 @@ import org.apache.lenya.cms.publication.
 import org.apache.lenya.cms.publication.PublicationException;
 import org.apache.lenya.cms.publication.URLInformation;
 import org.apache.lenya.cms.repository.Session;
-import org.apache.lenya.util.StringUtil;
 
 /**
  * <p>
@@ -65,12 +63,12 @@ public class OutgoingLinkRewriter extend
     /**
      * @param manager The service manager to use.
      * @param session The current session.
-     * @param requestUrl The requested web application URL (without servlet context path) where
-     *        the links should be rewritten.
+     * @param requestUrl The requested web application URL (without servlet context path) where the
+     *            links should be rewritten.
      * @param ssl If the current page is SSL-encrypted.
      * @param considerSslPolicies If the SSL protection of policies should be considered when
-     *        resolving the corresponding proxy. Setting this to <code>true</code> leads to a
-     *        substantial performance overhead.
+     *            resolving the corresponding proxy. Setting this to <code>true</code> leads to a
+     *            substantial performance overhead.
      * @param relativeUrls If relative URLs should be created.
      */
     public OutgoingLinkRewriter(ServiceManager manager, Session session, String requestUrl,
@@ -129,43 +127,41 @@ public class OutgoingLinkRewriter extend
     }
 
     public boolean matches(String url) {
-        return url.startsWith("/");
+        return url.equals("") || url.startsWith("/");
     }
 
-    private Map publicationCache = new HashMap();
+    private Map<String, Publication> publicationCache = new HashMap<String, Publication>();
 
     protected Publication getPublication(String pubId) throws PublicationException {
-        return (Publication) this.publicationCache.get(pubId);
+        return this.publicationCache.get(pubId);
     }
 
     public String rewrite(final String url) {
 
         String rewrittenUrl = "";
-        
+
         String path;
         String suffix;
-        
+
         int numIndex = url.indexOf('#');
         if (numIndex > -1) {
             path = url.substring(0, numIndex);
             suffix = url.substring(numIndex);
-        }
-        else {
+        } else {
             int qmIndex = url.indexOf('?');
             if (qmIndex > -1) {
                 path = url.substring(0, qmIndex);
                 suffix = url.substring(qmIndex);
-            }
-            else {
+            } else {
                 path = url;
                 suffix = "";
             }
         }
-        
+
         try {
             String normalizedUrl = normalizeUrl(path);
             if (this.relativeUrls) {
-                rewrittenUrl = getRelativeUrlTo(normalizedUrl);
+                rewrittenUrl = UriUtil.getRelativeUri(this.requestUrl, normalizedUrl);
             } else {
                 boolean useSsl = this.ssl;
                 if (!useSsl && this.policyManager != null) {
@@ -200,18 +196,12 @@ public class OutgoingLinkRewriter extend
     }
 
     protected String normalizeUrl(final String url) throws URISyntaxException {
-        String normalizedUrl;
-        if (url.indexOf("..") > -1) {
-            normalizedUrl = new URI(url).normalize().toString();
-        } else {
-            normalizedUrl = url;
-        }
-        return normalizedUrl;
+        return url.indexOf("..") > -1 ? new URI(url).normalize().toString() : url;
     }
 
     private String requestUrl;
 
-    private Map pubId2areaList = new HashMap();
+    private Map<String, List<String>> pubId2areaList = new HashMap<String, List<String>>();
 
     /**
      * Checks if a publication has an area by using a cache for performance reasons.
@@ -221,7 +211,7 @@ public class OutgoingLinkRewriter extend
      */
     protected boolean hasArea(Publication pub, String area) {
         String pubId = pub.getId();
-        List areas = (List) this.pubId2areaList.get(pubId);
+        List<String> areas = this.pubId2areaList.get(pubId);
         if (areas == null) {
             areas = Arrays.asList(pub.getAreaNames());
             this.pubId2areaList.put(pubId, areas);
@@ -254,58 +244,4 @@ public class OutgoingLinkRewriter extend
         return rewrittenUrl;
     }
 
-    protected String getRelativeUrlTo(String webappUrl) {
-        String relativeUrl;
-        if (this.requestUrl.equals(webappUrl)) {
-            relativeUrl = getLastStep(webappUrl);
-        }
-        else {
-            List sourceSteps = toList(this.requestUrl);
-            List targetSteps = toList(webappUrl);
-            
-            String lastEqualStep = null;
-
-            while (!sourceSteps.isEmpty() && !targetSteps.isEmpty()
-                    && sourceSteps.get(0).equals(targetSteps.get(0))) {
-                lastEqualStep = (String) sourceSteps.remove(0);
-                targetSteps.remove(0);
-            }
-
-            String prefix = "";
-            if (targetSteps.isEmpty()) {
-                prefix = generateUpDots(sourceSteps.size());
-            }
-            else if (sourceSteps.isEmpty()) {
-                prefix = getLastStep(this.requestUrl) + "/";
-            }
-            else if (sourceSteps.size() > 1) {
-                prefix = generateUpDots(sourceSteps.size() - 1) + "/";
-            }
-            else if (sourceSteps.size() == 1 && targetSteps.get(0).equals("")) {
-                prefix = generateUpDots(1) + "/" + lastEqualStep + "/";
-            }
-
-            String[] targetArray = (String[]) targetSteps.toArray(new String[targetSteps.size()]);
-            String targetPath = StringUtil.join(targetArray, "/");
-            relativeUrl = prefix + targetPath;
-        }
-        return relativeUrl;
-    }
-
-    protected String getLastStep(String url) {
-        return url.substring(url.lastIndexOf("/") + 1);
-    }
-
-    protected String generateUpDots(int length) {
-        String upDots;
-        String[] upDotsArray = new String[length];
-        Arrays.fill(upDotsArray, "..");
-        upDots = StringUtil.join(upDotsArray, "/");
-        return upDots;
-    }
-
-    protected List toList(String url) {
-        return new ArrayList(Arrays.asList(url.substring(1).split("/", -1)));
-    }
-
 }

Added: lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/UriUtil.java
URL: http://svn.apache.org/viewvc/lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/UriUtil.java?rev=1054381&view=auto
==============================================================================
--- lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/UriUtil.java (added)
+++ lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/UriUtil.java Sun Jan  2 10:32:43 2011
@@ -0,0 +1,110 @@
+package org.apache.lenya.cms.linking;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.lenya.util.StringUtil;
+
+public class UriUtil {
+
+    public static String getRelativeUri(String sourceUri, String targetUri) {
+        final boolean empty = targetUri.equals("");
+        if (empty) {
+            targetUri = "/";
+        }
+
+        final String baseUri = sourceUri.substring(0, sourceUri.lastIndexOf('/') + 1);
+
+        final Path basePath = new Path(baseUri);
+        final Path targetPath = new Path(targetUri);
+
+        while (!basePath.isEmpty() && targetPath.size() > 1
+                && basePath.first().equals(targetPath.first())) {
+            targetPath.removeFirst();
+        }
+
+        String prefix = basePath.isEmpty() ? "" : generateUpDots(basePath.getSteps().size() - 1);
+
+        String targetString = prefix + targetPath;
+        if (empty) {
+            if (!targetString.endsWith("/")) {
+                throw new IllegalStateException("Target URI " + targetString
+                        + " doesn't end with a slash!");
+            }
+            targetString = targetString.substring(0, targetString.length() - 1);
+        }
+
+        try {
+            return new URI(targetString).normalize().toString();
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected static String getLastStep(String url) {
+        return url.substring(url.lastIndexOf("/") + 1);
+    }
+
+    protected static String generateUpDots(int length) {
+        if (length == 0) {
+            return "./";
+        }
+        final String[] upDotsArray = new String[length];
+        Arrays.fill(upDotsArray, "..");
+        return StringUtil.join(upDotsArray, "/") + (upDotsArray.length == 0 ? "" : "/");
+    }
+
+    protected static class Path {
+
+        private List<String> steps = new ArrayList<String>();
+
+        public Path(final String path) {
+            if (!path.startsWith("/")) {
+                throw new IllegalArgumentException("Path " + path + " must start with a slash.");
+            }
+            this.steps.addAll(Arrays.asList(path.substring(1).split("/", -1)));
+        }
+
+        public int size() {
+            return this.steps.size();
+        }
+
+        public String removeFirst() {
+            return this.steps.remove(0);
+        }
+
+        public String toString() {
+            return StringUtil.join(this.steps.toArray(new String[this.steps.size()]), "/");
+        }
+
+        public String debug() {
+            final StringBuffer buf = new StringBuffer();
+            for (final String step : this.steps) {
+                buf.append("[" + step + "]");
+            }
+            return buf.toString();
+        }
+
+        public List<String> getSteps() {
+            return Collections.unmodifiableList(this.steps);
+        }
+
+        public boolean isEmpty() {
+            return this.steps.isEmpty();
+        }
+
+        public String first() {
+            return this.steps.get(0);
+        }
+
+        public String last() {
+            return this.steps.get(this.steps.size() - 1);
+        }
+
+    }
+
+}

Modified: lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/OutgoingLinkRewriterTest.java
URL: http://svn.apache.org/viewvc/lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/OutgoingLinkRewriterTest.java?rev=1054381&r1=1054380&r2=1054381&view=diff
==============================================================================
--- lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/OutgoingLinkRewriterTest.java (original)
+++ lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/OutgoingLinkRewriterTest.java Sun Jan  2 10:32:43 2011
@@ -23,26 +23,32 @@ import org.apache.lenya.cms.repository.S
 public class OutgoingLinkRewriterTest extends AbstractAccessControlTest {
 
     public void testRelativeUrls() throws Exception {
-        Session session = login("lenya");
-        String url = "/aaa/bbb/ccc";
+        final Session session = login("lenya");
+        final String url = "/aaa/bbb/ccc";
 
         boolean ssl = false;
         boolean considerSslPolicies = false;
-        boolean relativeUrls = true;
 
-        OutgoingLinkRewriter rewriter = new OutgoingLinkRewriter(getManager(), session, url, ssl,
-                considerSslPolicies, relativeUrls);
+        final OutgoingLinkRewriter relativeRewriter = new OutgoingLinkRewriter(getManager(),
+                session, url, ssl, considerSslPolicies, true);
+
+        assertEquals(relativeRewriter.rewrite("") + "/index", "../../index");
+        assertEquals(relativeRewriter.rewrite("/aaa/bbb/foo"), "foo");
+        assertEquals(relativeRewriter.rewrite("/aaa/bbb"), "../bbb");
+        assertEquals(relativeRewriter.rewrite("/aaa/bbb/ccc/ddd"), "ccc/ddd");
+        assertEquals(relativeRewriter.rewrite("/aaa/foo"), "../foo");
+        assertEquals(relativeRewriter.rewrite("/aaa/foo/bar"), "../foo/bar");
+        assertEquals(relativeRewriter.rewrite("/foo/bar"), "../../foo/bar");
+        assertEquals(relativeRewriter.rewrite("/aaa/foo/bar/baz"), "../foo/bar/baz");
+        assertEquals(relativeRewriter.rewrite("/aaa/bbb/?hello"), "?hello");
+        assertEquals(relativeRewriter.rewrite("/aaa/?hello"), "../?hello");
+        assertEquals(relativeRewriter.rewrite("/?hello"), "../../?hello");
+
+        final OutgoingLinkRewriter absoluteRewriter = new OutgoingLinkRewriter(getManager(),
+                session, url, ssl, considerSslPolicies, false);
+
+        assertEquals(absoluteRewriter.rewrite("") + "/index", "/index");
 
-        assertEquals(rewriter.rewrite("/aaa/bbb/foo"), "foo");
-        assertEquals(rewriter.rewrite("/aaa/bbb"), "..");
-        assertEquals(rewriter.rewrite("/aaa/bbb/ccc/ddd"), "ccc/ddd");
-        assertEquals(rewriter.rewrite("/aaa/foo"), "../foo");
-        assertEquals(rewriter.rewrite("/aaa/foo/bar"), "../foo/bar");
-        assertEquals(rewriter.rewrite("/foo/bar"), "../../foo/bar");
-        assertEquals(rewriter.rewrite("/aaa/foo/bar/baz"), "../foo/bar/baz");
-        assertEquals(rewriter.rewrite("/aaa/bbb/?hello"), "../bbb/?hello");
-        assertEquals(rewriter.rewrite("/aaa/?hello"), "../?hello");
-        assertEquals(rewriter.rewrite("/?hello"), "../../?hello");
     }
 
 }

Added: lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/UriUtilTest.java
URL: http://svn.apache.org/viewvc/lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/UriUtilTest.java?rev=1054381&view=auto
==============================================================================
--- lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/UriUtilTest.java (added)
+++ lenya/branches/BRANCH_2_1_X/src/modules-core/linking/java/test/org/apache/lenya/cms/linking/UriUtilTest.java Sun Jan  2 10:32:43 2011
@@ -0,0 +1,43 @@
+package org.apache.lenya.cms.linking;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import junit.framework.TestCase;
+
+import org.apache.lenya.cms.linking.UriUtil;
+
+public class UriUtilTest extends TestCase {
+    
+    public void testRelativePath() throws URISyntaxException {
+        
+        final String baseUri = "/aaa/bbb/";
+        
+        verify(baseUri, "/aaa/bbb/ccc", "ccc");
+        verify(baseUri, "/aaa/bbb", "../bbb");
+        verify(baseUri, "/aaa/bbb/", "");
+        verify(baseUri, "/aaa", "../../aaa");
+        verify(baseUri, "/aaa/", "../");
+        verify(baseUri, "/", "../../");
+        verify(baseUri, "/aaa/bbb/foo", "foo");
+        verify(baseUri, "/aaa/bbb/ccc/ddd", "ccc/ddd");
+        verify(baseUri, "/aaa/foo", "../foo");
+        verify(baseUri, "/aaa/foo/bar", "../foo/bar");
+        verify(baseUri, "/foo/bar", "../../foo/bar");
+        verify(baseUri, "/aaa/foo/bar/baz", "../foo/bar/baz");
+        verify(baseUri, "/aaa/bbb/?hello", "?hello");
+        verify(baseUri, "/aaa/?hello", "../?hello");
+        verify(baseUri, "/?hello", "../../?hello");
+
+        assertEquals("../..", UriUtil.getRelativeUri(baseUri, ""));
+    }
+    
+    protected void verify(final String base, final String target, final String rel) throws URISyntaxException {
+        final String resolvedRel = UriUtil.getRelativeUri(base, target);
+        assertEquals(rel, resolvedRel);
+        final String prefix = "http://foo.com";
+        final URI baseUri = new URI(prefix + base);
+        assertEquals(prefix + target, baseUri.resolve(resolvedRel).toString());
+    }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org