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/03/09 02:39:20 UTC
svn commit: r920612 - in /shindig/trunk/java/gadgets/src:
main/java/org/apache/shindig/gadgets/rewrite/
test/java/org/apache/shindig/gadgets/rewrite/
Author: johnh
Date: Tue Mar 9 01:39:19 2010
New Revision: 920612
URL: http://svn.apache.org/viewvc?rev=920612&view=rev
Log:
Implements operation that pulls out @imports from CSS and turns them into external references in the proper order. Logic separated from HTMLContentRewriter. Not activated in any current code path as of this CL.
Added:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriter.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitor.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriterTest.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitorTest.java
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriter.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriter.java?rev=920612&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriter.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriter.java Tue Mar 9 01:39:19 2010
@@ -0,0 +1,53 @@
+/*
+ * 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.shindig.gadgets.rewrite;
+
+import com.google.inject.Inject;
+
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.gadgets.Gadget;
+import org.apache.shindig.gadgets.rewrite.DomWalker;
+import org.apache.shindig.gadgets.rewrite.DomWalker.Visitor;
+import org.apache.shindig.gadgets.uri.ConcatUriManager;
+import org.apache.shindig.gadgets.uri.ProxyUriManager;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class StyleTagExtractorContentRewriter extends DomWalker.Rewriter {
+ private final ContentRewriterFeature.Factory featureConfigFactory;
+ private final ProxyUriManager proxyUriManager;
+ private final CssRequestRewriter cssRewriter;
+
+ @Inject
+ public StyleTagExtractorContentRewriter(ContentRewriterFeature.Factory featureConfigFactory,
+ ConcatUriManager concatUriManager, ProxyUriManager proxyUriManager,
+ CssRequestRewriter cssRewriter) {
+ this.featureConfigFactory = featureConfigFactory;
+ this.proxyUriManager = proxyUriManager;
+ this.cssRewriter = cssRewriter;
+ }
+
+ @Override
+ protected List<Visitor> makeVisitors(Gadget context, Uri gadgetUri) {
+ ContentRewriterFeature.Config config = featureConfigFactory.get(gadgetUri);
+ return Arrays.<Visitor>asList(
+ new StyleTagExtractorVisitor(config, cssRewriter, proxyUriManager));
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitor.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitor.java?rev=920612&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitor.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitor.java Tue Mar 9 01:39:19 2010
@@ -0,0 +1,92 @@
+/*
+ * 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.shindig.gadgets.rewrite;
+
+import java.util.List;
+
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.common.xml.DomUtil;
+import org.apache.shindig.gadgets.Gadget;
+import org.apache.shindig.gadgets.rewrite.DomWalker.Visitor;
+import org.apache.shindig.gadgets.spec.View;
+import org.apache.shindig.gadgets.uri.ProxyUriManager;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class StyleTagExtractorVisitor implements Visitor {
+ private final ContentRewriterFeature.Config config;
+ private final CssRequestRewriter cssRewriter;
+ private final ProxyUriManager proxyUriManager;
+
+ public StyleTagExtractorVisitor(ContentRewriterFeature.Config config,
+ CssRequestRewriter cssRewriter, ProxyUriManager proxyUriManager) {
+ this.config = config;
+ this.cssRewriter = cssRewriter;
+ this.proxyUriManager = proxyUriManager;
+ }
+
+ public VisitStatus visit(Gadget gadget, Node node) throws RewritingException {
+ if (!config.isRewriteEnabled() || !config.getIncludedTags().contains("style")) {
+ return VisitStatus.BYPASS;
+ }
+
+ // Only process <style> elements.
+ if (node.getNodeType() != Node.ELEMENT_NODE ||
+ !node.getNodeName().equalsIgnoreCase("style")) {
+ return VisitStatus.BYPASS;
+ }
+
+ return VisitStatus.RESERVE_NODE;
+ }
+
+ public boolean revisit(Gadget gadget, List<Node> nodes)
+ throws RewritingException {
+ boolean mutated = false;
+ if (nodes.size() == 0) {
+ return mutated;
+ }
+
+ Uri contentBase = gadget.getSpec().getUrl();
+ View view = gadget.getCurrentView();
+ if (view != null && view.getHref() != null) {
+ contentBase = view.getHref();
+ }
+
+ Element head = (Element)DomUtil.getFirstNamedChildNode(
+ nodes.get(0).getOwnerDocument().getDocumentElement(), "head");
+ for (Node node : nodes) {
+ // Guaranteed safe cast due to reservation logic.
+ Element elem = (Element)node;
+ List<String> extractedUrls = cssRewriter.rewrite(
+ elem, contentBase, CssRequestRewriter.uriMaker(proxyUriManager, config), true);
+ for (String extractedUrl : extractedUrls) {
+ // Add extracted urls as link elements to head
+ Element newLink = head.getOwnerDocument().createElement("link");
+ newLink.setAttribute("rel", "stylesheet");
+ newLink.setAttribute("type", "text/css");
+ newLink.setAttribute("href", extractedUrl);
+ head.appendChild(newLink);
+ mutated = true;
+ }
+ }
+
+ return mutated;
+ }
+
+}
Added: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriterTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriterTest.java?rev=920612&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriterTest.java (added)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorContentRewriterTest.java Tue Mar 9 01:39:19 2010
@@ -0,0 +1,28 @@
+/*
+ * 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.shindig.gadgets.rewrite;
+
+import org.junit.Test;
+
+public class StyleTagExtractorContentRewriterTest {
+ @Test
+ public void implementIntegrationTests() throws Exception {
+ // TODO: what the method says
+ }
+}
Added: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitorTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitorTest.java?rev=920612&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitorTest.java (added)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/StyleTagExtractorVisitorTest.java Tue Mar 9 01:39:19 2010
@@ -0,0 +1,255 @@
+/*
+ * 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.shindig.gadgets.rewrite;
+
+import static org.easymock.classextension.EasyMock.createMock;
+import static org.easymock.classextension.EasyMock.eq;
+import static org.easymock.classextension.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.isA;
+import static org.easymock.classextension.EasyMock.replay;
+import static org.easymock.classextension.EasyMock.verify;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.internal.ImmutableSet;
+
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.gadgets.Gadget;
+import org.apache.shindig.gadgets.rewrite.CssRequestRewriter.UriMaker;
+import org.apache.shindig.gadgets.rewrite.DomWalker.Visitor.VisitStatus;
+import org.apache.shindig.gadgets.uri.PassthruManager;
+import org.apache.shindig.gadgets.uri.ProxyUriManager;
+
+import org.junit.Before;
+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.List;
+
+public class StyleTagExtractorVisitorTest extends DomWalkerTestBase {
+ private ProxyUriManager proxyUriManager;
+
+ @Before
+ public void setUp() {
+ super.setUp();
+ proxyUriManager = new PassthruManager();
+ }
+
+ @Test
+ public void visitBypassesComment() throws Exception {
+ Comment comment = doc.createComment("comment");
+ assertEquals(VisitStatus.BYPASS, getVisitStatus(comment));
+ }
+
+ @Test
+ public void visitBypassesText() throws Exception {
+ Text text = doc.createTextNode("text");
+ assertEquals(VisitStatus.BYPASS, getVisitStatus(text));
+ }
+
+ @Test
+ public void visitBypassesNonStyle() throws Exception {
+ Node node = elem("div");
+ assertEquals(VisitStatus.BYPASS, getVisitStatus(node));
+ }
+
+ @Test
+ public void visitBypassesStyleWhenRewriterOff() throws Exception {
+ assertEquals(VisitStatus.BYPASS, getVisitStatus(config(false, true, true), elem("style")));
+ }
+
+ @Test
+ public void visitBypassesStyleWhenStyleTagNotIncluded() throws Exception {
+ assertEquals(VisitStatus.BYPASS, getVisitStatus(config(true, false, true), elem("style")));
+ }
+
+ @Test
+ public void visitReservesStyleNode() throws Exception {
+ assertEquals(VisitStatus.RESERVE_NODE, getVisitStatus(elem("style")));
+ }
+
+ @Test
+ public void visitReservesCasedStyleNode() throws Exception {
+ assertEquals(VisitStatus.RESERVE_NODE, getVisitStatus(elem("sTyLE")));
+ }
+
+ @Test
+ public void revisitNothingExtracted() throws Exception {
+ Gadget gadget = gadget();
+ CssRequestRewriter cssRewriter = createMock(CssRequestRewriter.class);
+ replay(cssRewriter);
+
+ // Tag name isn't inspected since visit() filters this.
+ List<Node> nodes = ImmutableList.<Node>of();
+ Node head = addNodesToHtml(nodes);
+
+ assertFalse(getRevisitStatus(gadget, true, cssRewriter, nodes));
+ verify(cssRewriter);
+ assertEquals(0, head.getChildNodes().getLength());
+ }
+
+ @Test
+ public void revisitExtractSpecRelative() throws Exception {
+ Uri base = GADGET_URI;
+ Gadget gadget = gadget();
+ CssRequestRewriter cssRewriter = createMock(CssRequestRewriter.class);
+ Element elem1 = elem("elem1");
+ Element elem2 = elem("elem2");
+ String urlStr1 = "http://foo.com/1.css";
+ List<String> extractedUrls1 = ImmutableList.of(urlStr1);
+ String urlStr2 = "http://bar.com/1.css";
+ List<String> extractedUrls2 = ImmutableList.of(urlStr2);
+ expect(cssRewriter.rewrite(eq(elem1), eq(base), isA(UriMaker.class), eq(true)))
+ .andReturn(extractedUrls1).once();
+ expect(cssRewriter.rewrite(eq(elem2), eq(base), isA(UriMaker.class), eq(true)))
+ .andReturn(extractedUrls2).once();
+ replay(cssRewriter);
+
+ // Tag name isn't inspected since visit() filters this.
+ List<Node> nodes = ImmutableList.<Node>of(elem1, elem2);
+ Node head = addNodesToHtml(nodes);
+
+ assertTrue(getRevisitStatus(gadget, true, cssRewriter, nodes));
+ verify(cssRewriter);
+ assertEquals(2, head.getChildNodes().getLength());
+ Element child1 = (Element)head.getChildNodes().item(0);
+ assertEquals("link", child1.getTagName());
+ assertEquals("stylesheet", child1.getAttribute("rel"));
+ assertEquals("text/css", child1.getAttribute("type"));
+ // PassthruManager doesn't modify the inbound URI.
+ assertEquals(urlStr1, child1.getAttribute("href"));
+ Element child2 = (Element)head.getChildNodes().item(1);
+ assertEquals("link", child2.getTagName());
+ assertEquals("stylesheet", child2.getAttribute("rel"));
+ assertEquals("text/css", child2.getAttribute("type"));
+ // PassthruManager doesn't modify the inbound URI.
+ assertEquals(urlStr2, child2.getAttribute("href"));
+ }
+
+ @Test
+ public void revisitExtractViewHrefRelative() throws Exception {
+ Uri base = Uri.parse("http://view.com/viewbase.xml");
+ Gadget gadget = gadget(true, true, base);
+ CssRequestRewriter cssRewriter = createMock(CssRequestRewriter.class);
+ Element elem1 = elem("elem1");
+ Element elem2 = elem("elem2");
+ String urlStr1 = "http://foo.com/1.css";
+ List<String> extractedUrls1 = ImmutableList.of(urlStr1);
+ String urlStr2 = "http://bar.com/1.css";
+ List<String> extractedUrls2 = ImmutableList.of(urlStr2);
+ expect(cssRewriter.rewrite(eq(elem1), eq(base), isA(UriMaker.class), eq(true)))
+ .andReturn(extractedUrls1).once();
+ expect(cssRewriter.rewrite(eq(elem2), eq(base), isA(UriMaker.class), eq(true)))
+ .andReturn(extractedUrls2).once();
+ replay(cssRewriter);
+
+ // Tag name isn't inspected since visit() filters this.
+ List<Node> nodes = ImmutableList.<Node>of(elem1, elem2);
+ Node head = addNodesToHtml(nodes);
+
+ assertTrue(getRevisitStatus(gadget, true, cssRewriter, nodes));
+ verify(cssRewriter);
+ assertEquals(2, head.getChildNodes().getLength());
+ Element child1 = (Element)head.getChildNodes().item(0);
+ assertEquals("link", child1.getTagName());
+ assertEquals("stylesheet", child1.getAttribute("rel"));
+ assertEquals("text/css", child1.getAttribute("type"));
+ // PassthruManager doesn't modify the inbound URI.
+ assertEquals(urlStr1, child1.getAttribute("href"));
+ Element child2 = (Element)head.getChildNodes().item(1);
+ assertEquals("link", child2.getTagName());
+ assertEquals("stylesheet", child2.getAttribute("rel"));
+ assertEquals("text/css", child2.getAttribute("type"));
+ // PassthruManager doesn't modify the inbound URI.
+ assertEquals(urlStr2, child2.getAttribute("href"));
+ }
+
+ @Test
+ public void revisitExtractSpecRelativeDisabled() throws Exception {
+ Uri base = GADGET_URI;
+ Gadget gadget = gadget();
+ CssRequestRewriter cssRewriter = createMock(CssRequestRewriter.class);
+ Element elem1 = elem("elem1");
+ Element elem2 = elem("elem2");
+ List<String> extractedUrls1 = ImmutableList.of();
+ List<String> extractedUrls2 = ImmutableList.of();
+ expect(cssRewriter.rewrite(eq(elem1), eq(base), isA(UriMaker.class), eq(true)))
+ .andReturn(extractedUrls1).once();
+ expect(cssRewriter.rewrite(eq(elem2), eq(base), isA(UriMaker.class), eq(true)))
+ .andReturn(extractedUrls2).once();
+ replay(cssRewriter);
+
+ // Tag name isn't inspected since visit() filters this.
+ List<Node> nodes = ImmutableList.<Node>of(elem1, elem2);
+ Node head = addNodesToHtml(nodes);
+
+ assertFalse(getRevisitStatus(gadget, false, cssRewriter, nodes));
+ verify(cssRewriter);
+ assertEquals(0, head.getChildNodes().getLength());
+ }
+
+ private VisitStatus getVisitStatus(Node node) throws Exception {
+ return getVisitStatus(config(true, true, true), node);
+ }
+
+ private VisitStatus getVisitStatus(ContentRewriterFeature.Config config, Node node)
+ throws Exception {
+ // Pass null for all unused (viz. visitor()) APIs to underscore their lack of use.
+ return new StyleTagExtractorVisitor(config, null, null).visit(null, node);
+ }
+
+ private boolean getRevisitStatus(
+ Gadget gadget, boolean shouldRewriteUrl, CssRequestRewriter cssRewriter, List<Node> nodes)
+ throws Exception {
+ return new StyleTagExtractorVisitor(
+ config(true, true, shouldRewriteUrl), cssRewriter, proxyUriManager)
+ .revisit(gadget, nodes);
+ }
+
+ private ContentRewriterFeature.Config config(
+ boolean enabled, boolean styleInc, boolean rewriteUrl) {
+ ContentRewriterFeature.Config config = createMock(ContentRewriterFeature.Config.class);
+ expect(config.isRewriteEnabled()).andReturn(enabled).anyTimes();
+ expect(config.getIncludedTags())
+ .andReturn(ImmutableSet.of(styleInc ? "style" : "foo")).anyTimes();
+ expect(config.shouldRewriteURL(isA(String.class))).andReturn(rewriteUrl).anyTimes();
+ replay(config);
+ return config;
+ }
+
+ private Node addNodesToHtml(List<Node> nodes) throws Exception {
+ Node html = elem("html");
+ Node head = elem("head");
+ Node body = elem("body");
+ html.appendChild(head);
+ html.appendChild(body);
+ for (Node node : nodes) {
+ body.appendChild(node);
+ }
+ html.getOwnerDocument().appendChild(html);
+ return head;
+ }
+}