You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by jo...@apache.org on 2010/06/18 01:01:12 UTC
svn commit: r955778 - in /shindig/trunk/java/gadgets/src:
main/java/org/apache/shindig/gadgets/rewrite/
test/java/org/apache/shindig/gadgets/rewrite/
Author: johnh
Date: Thu Jun 17 23:01:12 2010
New Revision: 955778
URL: http://svn.apache.org/viewvc?rev=955778&view=rev
Log:
Support URI resolution to base URI provided by <base> tag in addition to "current site" URI.
Patch provided by Gagan Singh.
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceRewriter.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitor.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitorTest.java
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceRewriter.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceRewriter.java?rev=955778&r1=955777&r2=955778&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceRewriter.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceRewriter.java Thu Jun 17 23:01:12 2010
@@ -20,12 +20,6 @@ package org.apache.shindig.gadgets.rewri
import com.google.inject.Inject;
-import org.apache.shindig.common.uri.Uri;
-import org.apache.shindig.gadgets.Gadget;
-
-import java.util.Arrays;
-import java.util.List;
-
/**
* Rewriter that converts all url's to absolute.
*/
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitor.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitor.java?rev=955778&r1=955777&r2=955778&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitor.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitor.java Thu Jun 17 23:01:12 2010
@@ -18,40 +18,81 @@
*/
package org.apache.shindig.gadgets.rewrite;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
+import com.google.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.gadgets.Gadget;
import org.apache.shindig.gadgets.rewrite.DomWalker.Visitor;
import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+/**
+ * Visitor that resolves relative paths relative to the
+ * base tag (only if present) / current page url and marks urls as absolute.
+ */
public class AbsolutePathReferenceVisitor implements Visitor {
- public final static Map<String, String> RESOURCE_TAGS =
- ImmutableMap.<String, String>builder()
- .put("a", "href")
- .put("area", "href")
- .put("q", "cite")
+ public enum Tags {
+ // Resources which would be fetched by the browser when rendering the page.
+ RESOURCES(ImmutableMap.<String, String>builder()
.put("img", "src")
.put("input", "src")
.put("body", "background")
.put("embed", "src")
.put("link", "href")
.put("script", "src")
- .put("object", "src").build();
+ .put("object", "src").build()),
+
+ // Hyperlinks that the user clicks on to navigate pages.
+ HYPERLINKS(ImmutableMap.<String, String>builder()
+ .put("a", "href")
+ .put("area", "href")
+ .put("q", "cite").build());
+
+ Map<String, String> resourceTags;
+ private Tags(Map<String, String> resourceTags) {
+ this.resourceTags = resourceTags;
+ }
+
+ public Map<String, String> getResourceTags() {
+ return resourceTags;
+ }
+ }
+
+ // Map of tag name -> attribute type describing uris to make absolute.
+ private final Map<String, String> tagsToMakeAbsolute;
+
+ @Inject
+ public AbsolutePathReferenceVisitor(Tags... resourceTags) {
+ Map<String, String> tagsToMakeAbsolute = new HashMap<String, String>();
+ for (Tags r : resourceTags) {
+ tagsToMakeAbsolute.putAll(r.getResourceTags());
+ }
+
+ this.tagsToMakeAbsolute = tagsToMakeAbsolute;
+ }
+ // @Override
public VisitStatus visit(Gadget gadget, Node node) throws RewritingException {
- Attr nodeAttr = getUriAttributeFromNode(node, RESOURCE_TAGS);
+ Attr nodeAttr = getUriAttributeFromNode(node, tagsToMakeAbsolute);
if (nodeAttr != null) {
try {
- Uri prevUri = Uri.parse(nodeAttr.getValue());
- Uri resolved = gadget.getSpec().getUrl().resolve(prevUri);
- if (!resolved.equals(prevUri)) {
+ Uri nodeUri = Uri.parse(nodeAttr.getValue());
+ Uri baseUri = getBaseResolutionUri(gadget, node);
+
+ Uri resolved = baseUri.resolve(nodeUri);
+
+ if (!resolved.equals(nodeUri)) {
nodeAttr.setValue(resolved.toString());
return VisitStatus.MODIFY;
}
@@ -62,6 +103,7 @@ public class AbsolutePathReferenceVisito
return VisitStatus.BYPASS;
}
+ // @Override
public boolean revisit(Gadget gadget, List<Node> node) throws RewritingException {
// Modification happens immediately.
return false;
@@ -90,4 +132,58 @@ public class AbsolutePathReferenceVisito
return null;
}
+
+ /**
+ * Returns the uri to resolve any relative url on the current page to.
+ * This is equal to the base uri (in case the page has one) or the current
+ * page uri.
+ * @param gadget The gadget (container for page) being processed.
+ * @param node The current node being processed.
+ * @return The uri to resolve non absolute uri's relative to.
+ */
+ private Uri getBaseResolutionUri(Gadget gadget, Node node) {
+ Uri pageUri = gadget.getSpec().getUrl();
+ Uri baseUri = getBaseUri(node.getOwnerDocument());
+ return baseUri != null ? baseUri : pageUri;
+ }
+
+ /**
+ * Returns the base uri of the given document.
+ * Base uri is specified as <base href="...">
+ * @param doc The document.
+ * @return Base uri of the document.
+ */
+ @VisibleForTesting
+ Uri getBaseUri(Document doc) {
+ String baseHref = getBaseHref(doc);
+ if (baseHref != null) {
+ try {
+ return Uri.parse(baseHref);
+ } catch (Uri.UriException e) {
+ // Ignore.
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns href value of the base tag.
+ * @param doc The document to process.
+ * @return Value of href attribute of the base tag.
+ */
+ @VisibleForTesting
+ String getBaseHref(Document doc) {
+ NodeList list = doc.getElementsByTagName("base");
+ if (list.getLength() == 0) {
+ return null;
+ }
+
+ NamedNodeMap nodeMap = list.item(0).getAttributes();
+ if (nodeMap == null) {
+ return null;
+ }
+ Attr attr = (Attr) nodeMap.getNamedItem("href");
+ return attr != null ? attr.getValue() : null;
+ }
}
Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitorTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitorTest.java?rev=955778&r1=955777&r2=955778&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitorTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/AbsolutePathReferenceVisitorTest.java Thu Jun 17 23:01:12 2010
@@ -18,19 +18,20 @@
*/
package org.apache.shindig.gadgets.rewrite;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.gadgets.rewrite.DomWalker.Visitor.VisitStatus;
-
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import org.junit.Test;
-
import org.w3c.dom.Comment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
+import java.util.HashMap;
+import java.util.Map;
+
public class AbsolutePathReferenceVisitorTest extends DomWalkerTestBase {
private static final Uri ABSOLUTE_URI = Uri.parse("http://host.com/path");
private static final String JS_URI_STR = "javascript:foo();";
@@ -39,51 +40,67 @@ public class AbsolutePathReferenceVisito
private static final Uri PATH_RELATIVE_URI = Uri.parse("path/relative");
private static final Uri PATH_RELATIVE_RESOLVED_URI = GADGET_URI.resolve(PATH_RELATIVE_URI);
private static final String INVALID_URI_STRING = "!^|BAD URI|^!";
-
+
+ AbsolutePathReferenceVisitor visitorForAllTags() {
+ return new AbsolutePathReferenceVisitor(
+ AbsolutePathReferenceVisitor.Tags.RESOURCES,
+ AbsolutePathReferenceVisitor.Tags.HYPERLINKS);
+ }
+
+ AbsolutePathReferenceVisitor visitorForHyperlinks() {
+ return new AbsolutePathReferenceVisitor(
+ AbsolutePathReferenceVisitor.Tags.HYPERLINKS);
+ }
+
+ AbsolutePathReferenceVisitor visitorForResources() {
+ return new AbsolutePathReferenceVisitor(
+ AbsolutePathReferenceVisitor.Tags.RESOURCES);
+ }
+
@Test
public void bypassComment() throws Exception {
Comment comment = doc.createComment("howdy pardner");
assertEquals(VisitStatus.BYPASS, getVisitStatus(comment));
}
-
+
@Test
public void bypassText() throws Exception {
Text text = doc.createTextNode("back scratchah! get ya back scratcha he'yah!");
assertEquals(VisitStatus.BYPASS, getVisitStatus(text));
}
-
+
@Test
public void bypassNonSupportedTag() throws Exception {
Element div = elem("div", "src", RELATIVE_URI.toString(), "href", RELATIVE_URI.toString());
assertEquals(VisitStatus.BYPASS, getVisitStatus(div));
}
-
+
@Test
public void bypassTagWithoutAttrib() throws Exception {
Element a = elem("a");
assertEquals(VisitStatus.BYPASS, getVisitStatus(a));
}
-
+
@Test
public void absolutifyTagA() throws Exception {
checkAbsolutifyStates("a");
}
-
+
@Test
public void absolutifyTagImg() throws Exception {
checkAbsolutifyStates("img");
}
-
+
@Test
public void absolutifyTagLink() throws Exception {
checkAbsolutifyStates("link");
}
-
+
@Test
public void absolutifyTagScript() throws Exception {
checkAbsolutifyStates("script");
}
-
+
@Test
public void absolutifyTagObject() throws Exception {
checkAbsolutifyStates("object");
@@ -91,15 +108,63 @@ public class AbsolutePathReferenceVisito
@Test
public void revisitDoesNothing() throws Exception {
- assertFalse(new AbsolutePathReferenceVisitor().revisit(gadget(), null));
+ assertFalse(visitorForAllTags().revisit(gadget(), null));
}
-
+
+ @Test
+ public void resolveRelativeToBaseTagIfPresent() throws Exception {
+ Element baseTag = elem("base", "href", "http://www.example.org");
+ Element img = elem("img", "src", RELATIVE_URI.toString());
+ Element html = htmlDoc(null, baseTag, img);
+
+ assertEquals(VisitStatus.BYPASS, getVisitStatus(baseTag));
+ assertEquals(VisitStatus.MODIFY, getVisitStatus(img));
+ assertEquals("http://www.example.org" + RELATIVE_URI.toString(),
+ img.getAttribute("src"));
+ }
+
+ @Test
+ public void getBaseHrefReturnsNullIfBaseTagWithoutHrefAttribute()
+ throws Exception {
+ Element baseTag = elem("base");
+ Element img = elem("img", "src", RELATIVE_URI.toString());
+ Element html = htmlDoc(null, baseTag, img);
+
+ AbsolutePathReferenceVisitor visitor = visitorForAllTags();
+ assertEquals(VisitStatus.BYPASS, getVisitStatus(baseTag));
+ assertEquals(VisitStatus.MODIFY, getVisitStatus(img));
+ assertEquals(RELATIVE_RESOLVED_URI.toString(), img.getAttribute("src"));
+ }
+
+ @Test
+ public void testGetBaseUri() throws Exception {
+ Element baseTag1 = elem("base", "href", "http://www.example1.org");
+ Element baseTag2 = elem("base", "href", "http://www.example2.org");
+
+ Element img = elem("img", "src", RELATIVE_URI.toString());
+ Element a = elem("a", "href", RELATIVE_URI.toString());
+
+ Node[] headNodes = { baseTag1 };
+ Element html = htmlDoc(headNodes, baseTag2, img, a);
+
+ AbsolutePathReferenceVisitor visitor = visitorForAllTags();
+ assertEquals("http://www.example1.org",
+ visitor.getBaseHref(html.getOwnerDocument()));
+ assertEquals("http://www.example1.org",
+ visitor.getBaseUri(html.getOwnerDocument()).toString());
+ }
+
private void checkAbsolutifyStates(String tagName) throws Exception {
String lcTag = tagName.toLowerCase();
String ucTag = tagName.toUpperCase();
- String validAttr = AbsolutePathReferenceVisitor.RESOURCE_TAGS.get(lcTag);
+ Map<String, String> resourceTags = new HashMap<String, String>();
+ resourceTags.putAll(AbsolutePathReferenceVisitor.Tags
+ .RESOURCES.getResourceTags());
+ resourceTags.putAll(AbsolutePathReferenceVisitor.Tags
+ .HYPERLINKS.getResourceTags());
+ String validAttr = resourceTags.get(lcTag);
String invalidAttr = validAttr + "whoknows";
-
+
// lowercase, correct attrib, relative-possible URL
Element lcValidRelative = elem(lcTag, validAttr, RELATIVE_URI.toString());
assertEquals(VisitStatus.MODIFY, getVisitStatus(lcValidRelative));
@@ -142,6 +207,6 @@ public class AbsolutePathReferenceVisito
}
private VisitStatus getVisitStatus(Node node) throws Exception {
- return new AbsolutePathReferenceVisitor().visit(gadget(), node);
+ return visitorForAllTags().visit(gadget(), node);
}
}