You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by jo...@apache.org on 2008/01/16 09:06:32 UTC

svn commit: r612381 - in /incubator/shindig/trunk/java/gadgets: ./ src/main/java/org/apache/shindig/gadgets/ src/main/java/org/apache/shindig/gadgets/http/

Author: johnh
Date: Wed Jan 16 00:06:30 2008
New Revision: 612381

URL: http://svn.apache.org/viewvc?rev=612381&view=rev
Log:
First commit of Caja support in Shindig.

* GadgetContentFilter introduced as a general mechanism for filtering Gadget output.
* CajaContentFilter is the first example of the above.
* pom.xml cleaned up to have only one Caja reference

This commit is based on Ihab A.B. Awad's patch, and resolves JIRA issue SHINDIG-17. Thanks Ihab!


Added:
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContentFilter.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CajaContentFilter.java
Modified:
    incubator/shindig/trunk/java/gadgets/pom.xml
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java

Modified: incubator/shindig/trunk/java/gadgets/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/pom.xml?rev=612381&r1=612380&r2=612381&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/pom.xml (original)
+++ incubator/shindig/trunk/java/gadgets/pom.xml Wed Jan 16 00:06:30 2008
@@ -56,7 +56,7 @@
   </build>
   <repositories>
     <repository>
-      <id>google-caja</id>
+      <id>caja</id>
       <url>http://google-caja.googlecode.com/svn/maven</url>
     </repository>
   </repositories>
@@ -80,12 +80,6 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>caja</groupId>
-      <artifactId>caja</artifactId>
-      <version>r339</version>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.4</version>
@@ -102,6 +96,12 @@
       <artifactId>easymockclassextension</artifactId>
       <version>2.2.2</version>
       <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>caja</groupId>
+      <artifactId>caja</artifactId>
+      <version>r394</version>
+      <scope>compile</scope>
     </dependency>
   </dependencies>
   <distributionManagement>

Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContentFilter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContentFilter.java?rev=612381&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContentFilter.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContentFilter.java Wed Jan 16 00:06:30 2008
@@ -0,0 +1,22 @@
+/*
+ * Licensed 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;
+
+/**
+ * Simple interface for a class which filters the content of a Gadget
+ * before returning it to the requestor.
+ */
+public interface GadgetContentFilter {
+  public String filter(String content) throws GadgetException;
+}

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java?rev=612381&r1=612380&r2=612381&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java Wed Jan 16 00:06:30 2008
@@ -75,6 +75,7 @@
         core.put(entry.getName(), entry);
       }
     }
+    
     // Everything depends on core JS being set up first because in gadget
     // rendering mode, we pre-populate some of the data.
     core.put(FEAT_MSG_BUNDLE,

Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CajaContentFilter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CajaContentFilter.java?rev=612381&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CajaContentFilter.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CajaContentFilter.java Wed Jan 16 00:06:30 2008
@@ -0,0 +1,99 @@
+/*
+ * Licensed 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.http;
+
+import org.apache.shindig.gadgets.GadgetContentFilter;
+import org.apache.shindig.gadgets.GadgetException;
+
+import com.google.caja.lexer.ExternalReference;
+import com.google.caja.opensocial.DefaultGadgetRewriter;
+import com.google.caja.opensocial.GadgetContentRewriter;
+import com.google.caja.opensocial.UriCallback;
+import com.google.caja.opensocial.GadgetRewriteException;
+import com.google.caja.opensocial.UriCallbackException;
+import com.google.caja.opensocial.UriCallbackOption;
+import com.google.caja.reporting.SimpleMessageQueue;
+import com.google.caja.reporting.MessageQueue;
+import com.google.caja.reporting.Message;
+import com.google.caja.reporting.MessageContext;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CajaContentFilter implements GadgetContentFilter {
+  private final URI retrievedUri;
+  
+  public CajaContentFilter(URI retrievedUri) {
+    this.retrievedUri = retrievedUri;
+  }
+  
+  public String filter(String content) throws GadgetException {
+    UriCallback cb = new UriCallback() {
+      public UriCallbackOption getOption(ExternalReference externalReference,
+                                         String string) {
+        return UriCallbackOption.REWRITE;
+      }
+      
+      public Reader retrieve(ExternalReference externalReference, String string)
+          throws UriCallbackException {
+        throw new UriCallbackException(externalReference);
+      }
+      
+      public URI rewrite(ExternalReference externalReference, String string)
+          throws UriCallbackException {
+        return externalReference.getUri();
+      }
+    };
+
+    MessageQueue mq = new SimpleMessageQueue();
+    GadgetContentRewriter rw = new DefaultGadgetRewriter(mq);
+    Readable input = new StringReader(content);
+    Appendable output = new StringBuilder();
+
+    try {
+      rw.rewriteContent(retrievedUri, input, cb, output);
+    } catch (GadgetRewriteException e) {
+      throwCajolingException(e, mq);
+    } catch (UriCallbackException e) {
+      throwCajolingException(e, mq);
+    } catch (IOException e) {
+      throwCajolingException(e, mq);
+    }
+
+    return output.toString();
+  }
+
+  private void throwCajolingException(Exception cause, MessageQueue mq)
+      throws GadgetException {
+    StringBuilder errbuilder = new StringBuilder();
+    MessageContext mc = new MessageContext();
+    List<GadgetException> exceptions = new ArrayList<GadgetException>();
+    
+    if (cause != null) {
+      errbuilder.append(cause).append("\n");
+    }
+    
+    for (Message m : mq.getMessages()) {
+      errbuilder.append(m.format(mc)).append("\n");
+    }
+    
+    throw new GadgetException(
+        GadgetException.Code.MALFORMED_FOR_SAFE_INLINING,
+        errbuilder.toString());
+  }
+}

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java?rev=612381&r1=612380&r2=612381&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java Wed Jan 16 00:06:30 2008
@@ -16,6 +16,7 @@
 import org.apache.shindig.gadgets.BasicGadgetDataCache;
 import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
 import org.apache.shindig.gadgets.Gadget;
+import org.apache.shindig.gadgets.GadgetContentFilter;
 import org.apache.shindig.gadgets.GadgetDataCache;
 import org.apache.shindig.gadgets.GadgetException;
 import org.apache.shindig.gadgets.GadgetFeatureRegistry;
@@ -37,6 +38,8 @@
 import java.net.URLEncoder;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Executor;
@@ -55,12 +58,12 @@
   private GadgetServer gadgetServer;
   private String jsServicePath;
   private GadgetFeatureRegistry registry;
+  private static final String CAJA_PARAM = "caja";
   private static final String USERPREF_PARAM_PREFIX = "up_";
   private static final String LIBS_PARAM_NAME = "libs";
   private static final String JS_FILE_SUFFIX = ".js";
   public static final String DEFAULT_JS_SERVICE_PATH = "js/";
 
-
   /**
    * Creates a {@code GadgetRenderingServlet} with default executor,
    * caches, etc.
@@ -145,6 +148,13 @@
     ProcessingOptions options = new ProcessingOptions();
     options.ignoreCache = getIgnoreCache(req);
 
+    // Prepare a list of GadgetContentFilters applied to the output
+    List<GadgetContentFilter> contentFilters =
+        new LinkedList<GadgetContentFilter>();
+    if (getUseCaja(req)) {
+      contentFilters.add(new CajaContentFilter(uri));
+    }
+    
     Gadget gadget = null;
     try {
       gadget = gadgetServer.processGadget(gadgetId,
@@ -152,17 +162,19 @@
                                           context.getLocale(),
                                           RenderingContext.GADGET,
                                           options);
-      outputGadget(gadget, resp);
+      outputGadget(gadget, contentFilters, resp);
     } catch (GadgetServer.GadgetProcessException e) {
       outputErrors(e, resp);
     }
   }
 
-  private void outputGadget(Gadget gadget, HttpServletResponse resp)
-      throws IOException {
+  private void outputGadget(Gadget gadget,
+                            List<GadgetContentFilter> contentFilters,
+                            HttpServletResponse resp)
+      throws IOException, GadgetServer.GadgetProcessException {
     switch(gadget.getContentType()) {
     case HTML:
-      outputHtmlGadget(gadget, resp);
+      outputHtmlGadget(gadget, contentFilters, resp);
       break;
     case URL:
       outputUrlGadget(gadget, resp);
@@ -174,8 +186,10 @@
     }
   }
 
-  private void outputHtmlGadget(Gadget gadget, HttpServletResponse resp)
-      throws IOException {
+  private void outputHtmlGadget(Gadget gadget,
+                                List<GadgetContentFilter> contentFilters,
+                                HttpServletResponse resp)
+      throws IOException, GadgetServer.GadgetProcessException {
     resp.setContentType("text/html");
 
     StringBuilder markup = new StringBuilder();
@@ -190,6 +204,7 @@
     StringBuilder externJs = new StringBuilder();
     StringBuilder inlineJs = new StringBuilder();
     String externFmt = "<script src=\"%s\"></script>\n";
+    
     for (JsLibrary library : gadget.getJsLibraries()) {
       if (library.getType() == JsLibrary.Type.URL) {
         externJs.append(String.format(externFmt, library.getContent()));
@@ -197,14 +212,30 @@
         inlineJs.append(library.getContent()).append("\n");
       }
     }
+    
     if (inlineJs.length() > 0) {
       markup.append("<script><!--\n").append(inlineJs)
-          .append("\n-->\n</script>");
+            .append("\n-->\n</script>");
     }
+    
     if (externJs.length() > 0) {
       markup.append(externJs);
     }
-    markup.append(gadget.getContentData());
+    
+    List<GadgetException> gadgetExceptions = new LinkedList<GadgetException>();
+    String content = gadget.getContentData();
+    for (GadgetContentFilter filter : contentFilters) {
+      try {
+        content = filter.filter(content);
+      } catch (GadgetException e) {
+        gadgetExceptions.add(e);
+      }
+    }
+    if (gadgetExceptions.size() > 0) {
+      throw new GadgetServer.GadgetProcessException(gadgetExceptions);
+    }
+    
+    markup.append(content);
     markup.append("<script>gadgets.util.runOnLoadHandlers();</script>");
     markup.append("</body></html>");
 
@@ -314,5 +345,10 @@
       noCacheParam = req.getParameter("bpc");
     }
     return noCacheParam != null && noCacheParam.equals("1");
+  }
+  
+  protected boolean getUseCaja(HttpServletRequest req) {
+    String cajaParam = req.getParameter(CAJA_PARAM);
+    return cajaParam != null && cajaParam.equals("1");
   }
 }