You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by et...@apache.org on 2008/09/25 17:58:19 UTC

svn commit: r699010 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/ main/java/org/apache/shindig/gadgets/render/ test/java/org/apache/shindig/gadgets/render/

Author: etnu
Date: Thu Sep 25 08:58:19 2008
New Revision: 699010

URL: http://svn.apache.org/viewvc?rev=699010&view=rev
Log:
Splitting responsibilities of Renderer into two classes to reduce dependencies. Requires temporary renaming.


Added:
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java
      - copied, changed from r698928, incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderDispatcher.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingResults.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/HtmlRendererTest.java
      - copied, changed from r698928, incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderDispatcherTest.java
Removed:
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java
Modified:
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java?rev=699010&r1=699009&r2=699010&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java Thu Sep 25 08:58:19 2008
@@ -45,6 +45,9 @@
   private GadgetContext context;
   private GadgetSpec spec;
   private Preloads preloads;
+  private View currentView;
+
+  @Deprecated
   private MutableContent mutableContent;
 
   @Deprecated
@@ -53,9 +56,6 @@
   @Deprecated
   private Map<Preload, Future<HttpResponse>> preloadMap;
 
-  @Deprecated
-  private View currentView;
-
   public Gadget() { }
 
   /**
@@ -107,17 +107,6 @@
     return spec;
   }
 
-  /**
-   * @param mutableContent Content associated with rendering this gadget.
-   */
-  public Gadget setMutableContent(MutableContent mutableContent) {
-    this.mutableContent = mutableContent;
-    return this;
-  }
-
-  public MutableContent getMutableContent() {
-    return mutableContent;
-  }
 
   /**
    * Sets the current content of the rendered output of this gadget.
@@ -133,10 +122,6 @@
     return mutableContent.getContent();
   }
 
-  public GadgetHtmlNode getParseTree() {
-    return mutableContent.getParseTree();
-  }
-
   /**
    * @param preloads The preloads for the gadget that is being processed.
    */
@@ -149,6 +134,18 @@
     return preloads;
   }
 
+  public Gadget setCurrentView(View currentView) {
+    this.currentView = currentView;
+    return this;
+  }
+
+  /**
+   * @return The View applicable for the current request.
+   */
+  public View getCurrentView() {
+    return currentView;
+  }
+
   /**
    * Convenience function for getting the locale spec for the current context.
    *
@@ -160,7 +157,21 @@
     return spec.getModulePrefs().getLocale(context.getLocale());
   }
 
+  @Deprecated
+  public Gadget setMutableContent(MutableContent mutableContent) {
+    this.mutableContent = mutableContent;
+    return this;
+  }
+
+  @Deprecated
+  public MutableContent getMutableContent() {
+    return mutableContent;
+  }
 
+  @Deprecated
+  public GadgetHtmlNode getParseTree() {
+    return mutableContent.getParseTree();
+  }
 
   /**
    * @return A mutable collection of JsLibrary objects attached to this Gadget.
@@ -179,14 +190,6 @@
   }
 
   /**
-   * @return The View applicable for the current request.
-   */
-  @Deprecated
-  public View getCurrentView() {
-    return currentView;
-  }
-
-  /**
    * Attempts to extract the "current" view for this gadget.
    *
    * @param config The container configuration; used to look for any view name

Copied: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java (from r698928, incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java)
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java?p2=incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java&p1=incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java&r1=698928&r2=699010&rev=699010&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java Thu Sep 25 08:58:19 2008
@@ -18,12 +18,10 @@
  */
 package org.apache.shindig.gadgets.render;
 
-import org.apache.shindig.common.ContainerConfig;
 import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.GadgetContext;
 import org.apache.shindig.gadgets.GadgetException;
-import org.apache.shindig.gadgets.GadgetSpecFactory;
 import org.apache.shindig.gadgets.http.ContentFetcherFactory;
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
@@ -34,27 +32,18 @@
 
 import com.google.inject.Inject;
 
-import org.json.JSONArray;
-import org.json.JSONException;
-
 /**
  * Handles producing output markup for a gadget based on the provided context.
  */
-public class Renderer {
-  private final GadgetSpecFactory gadgetSpecFactory;
+public class HtmlRenderer {
   private final ContentFetcherFactory fetcher;
   private final PreloaderService preloader;
-  private final ContainerConfig containerConfig;
 
   @Inject
-  public Renderer(GadgetSpecFactory gadgetSpecFactory,
-                  ContentFetcherFactory fetcher,
-                  PreloaderService preloader,
-                  ContainerConfig containerConfig) {
-    this.gadgetSpecFactory = gadgetSpecFactory;
+  public HtmlRenderer(ContentFetcherFactory fetcher,
+                  PreloaderService preloader) {
     this.fetcher = fetcher;
     this.preloader = preloader;
-    this.containerConfig = containerConfig;
   }
 
   /**
@@ -66,30 +55,15 @@
    *
    * - Perform rewriting operations on the output content, handled by Rewriter.
    *
-   * @param context The context for the gadget rendering operation.
+   * @param gadget The gadget for the rendering operation.
    * @return The rendered gadget content
    * @throws RenderingException if any issues arise that prevent rendering.
    */
-  public String render(GadgetContext context) throws RenderingException {
+  public String render(Gadget gadget) throws RenderingException {
     try {
-      GadgetSpec spec = gadgetSpecFactory.getGadgetSpec(context);
-
-      Gadget gadget = new Gadget()
-          .setContext(context)
-          .setSpec(spec);
-
-      // TODO: Move Gadget.getView into a utility method so that the correct view can be pulled from
-      // the gadget with aliasing done automatically.
-      View view = getView(context, spec);
-
-      if (view == null) {
-        throw new RenderingException("Unable to locate an appropriate view in this gadget. " +
-            "Requested: '" + context.getView() + "' Available: " + spec.getViews().keySet());
-      }
-
-      if (view.getType() == View.ContentType.URL) {
-        throw new RenderingException("Attempted to render a url-type gadget.");
-      }
+      View view = gadget.getCurrentView();
+      GadgetContext context = gadget.getContext();
+      GadgetSpec spec = gadget.getSpec();
 
       gadget.setPreloads(preloader.preload(context, spec));
 
@@ -98,9 +72,9 @@
       } else {
         // TODO: Add current url to GadgetContext to support transitive proxying.
         HttpRequest request = new HttpRequest(Uri.fromJavaUri(view.getHref()))
-            .setSecurityToken(context.getToken())
             .setOAuthArguments(new OAuthArguments(view))
             .setAuthType(view.getAuthType())
+            .setSecurityToken(context.getToken())
             .setContainer(context.getContainer())
             .setGadget(Uri.fromJavaUri(context.getUrl()));
         HttpResponse response = fetcher.fetch(request);
@@ -110,34 +84,4 @@
       throw new RenderingException(e);
     }
   }
-
-  /**
-   * Attempts to extract the "current" view for the given gadget.
-   */
-  private View getView(GadgetContext context, GadgetSpec spec) {
-    String viewName = context.getView();
-    View view = spec.getView(viewName);
-    if (view == null) {
-      JSONArray aliases = containerConfig.getJsonArray(context.getContainer(),
-          "gadgets.features/views/" + viewName + "/aliases");
-      if (aliases != null) {
-        try {
-          for (int i = 0, j = aliases.length(); i < j; ++i) {
-            viewName = aliases.getString(i);
-            view = spec.getView(viewName);
-            if (view != null) {
-              break;
-            }
-          }
-        } catch (JSONException e) {
-          view = null;
-        }
-      }
-
-      if (view == null) {
-        view = spec.getView(GadgetSpec.DEFAULT_VIEW);
-      }
-    }
-    return view;
-  }
 }

Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderDispatcher.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderDispatcher.java?rev=699010&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderDispatcher.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderDispatcher.java Thu Sep 25 08:58:19 2008
@@ -0,0 +1,179 @@
+/*
+ * 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.render;
+
+import org.apache.shindig.common.ContainerConfig;
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.gadgets.Gadget;
+import org.apache.shindig.gadgets.GadgetContext;
+import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.GadgetSpecFactory;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.spec.View;
+
+import com.google.inject.Inject;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+/**
+ * Validates a rendering request parameters before calling an appropriate renderer.
+ *
+ * TODO: Rename to Renderer
+ */
+public class RenderDispatcher {
+  private static final Logger LOG = Logger.getLogger(RenderDispatcher.class.getName());
+  private final HtmlRenderer renderer;
+  private final GadgetSpecFactory gadgetSpecFactory;
+  private final ContainerConfig containerConfig;
+
+  @Inject
+  public RenderDispatcher(HtmlRenderer renderer,
+                          GadgetSpecFactory gadgetSpecFactory,
+                          ContainerConfig containerConfig) {
+    this.renderer = renderer;
+    this.gadgetSpecFactory = gadgetSpecFactory;
+    this.containerConfig = containerConfig;
+  }
+
+  /**
+   * Attempts to render the requested gadget.
+   *
+   * @return The results of the rendering attempt.
+   *
+   * TODO: Localize error messages.
+   */
+  public RenderingResults render(GadgetContext context) {
+    URI url = context.getUrl();
+
+    if (url == null) {
+      return RenderingResults.error("Missing or malformed url parameter");
+    }
+
+    if (!"http".equalsIgnoreCase(url.getScheme()) && !"https".equalsIgnoreCase(url.getScheme())) {
+      return RenderingResults.error("Unsupported scheme (must be http or https).");
+    }
+
+    if (!validateParent(context)) {
+      return RenderingResults.error("Unsupported parent parameter. Check your container code.");
+    }
+
+    try {
+      GadgetSpec spec = gadgetSpecFactory.getGadgetSpec(context);
+      View view = getView(context, spec);
+
+      if (view == null) {
+        return RenderingResults.error("Unable to locate an appropriate view in this gadget. " +
+            "Requested: '" + context.getView() + "' Available: " + spec.getViews().keySet());
+      }
+
+      Gadget gadget = new Gadget()
+          .setContext(context)
+          .setSpec(spec)
+          .setCurrentView(view);
+
+      if (view.getType() == View.ContentType.URL) {
+        return RenderingResults.mustRedirect(getTypeUrlRedirect(gadget));
+      }
+
+      // TODO: Validate locked domain.
+
+      return RenderingResults.ok(renderer.render(gadget));
+    } catch (RenderingException e) {
+      LOG.log(Level.WARNING, "Failed to render gadget " + context.getUrl(), e);
+      return RenderingResults.error(e.getLocalizedMessage());
+    } catch (GadgetException e) {
+      LOG.log(Level.WARNING, "Failed to process gadget " + context.getUrl(), e);
+      return RenderingResults.error(e.getLocalizedMessage());
+    }
+  }
+
+  /**
+   * Validates that the parent parameter was acceptable.
+   *
+   * @return True if the parent parameter is valid for the current container.
+   */
+  private boolean validateParent(GadgetContext context) {
+    String container = context.getContainer();
+    String parent = context.getParameter("parent");
+
+    if (parent == null) {
+      // If there is no parent parameter, we are still safe because no
+      // dependent code ever has to trust it anyway.
+      return true;
+    }
+
+    try {
+      JSONArray parents = containerConfig.getJsonArray(container, "gadgets.parent");
+      if (parents == null) {
+        return true;
+      } else {
+        // We need to check each possible parent parameter against this regex.
+        for (int i = 0, j = parents.length(); i < j; ++i) {
+          if (Pattern.matches(parents.getString(i), parent)) {
+            return true;
+          }
+        }
+      }
+    } catch (JSONException e) {
+      LOG.log(Level.WARNING, "Configuration error", e);
+    }
+    return false;
+  }
+
+  private Uri getTypeUrlRedirect(Gadget gadget) {
+    // TODO: This should probably just call UrlGenerator.getIframeUrl().
+    return Uri.fromJavaUri(gadget.getCurrentView().getHref());
+  }
+
+  /**
+   * Attempts to extract the "current" view for the given gadget.
+   */
+  private View getView(GadgetContext context, GadgetSpec spec) {
+    String viewName = context.getView();
+    View view = spec.getView(viewName);
+    if (view == null) {
+      JSONArray aliases = containerConfig.getJsonArray(context.getContainer(),
+          "gadgets.features/views/" + viewName + "/aliases");
+      if (aliases != null) {
+        try {
+          for (int i = 0, j = aliases.length(); i < j; ++i) {
+            viewName = aliases.getString(i);
+            view = spec.getView(viewName);
+            if (view != null) {
+              break;
+            }
+          }
+        } catch (JSONException e) {
+          view = null;
+        }
+      }
+
+      if (view == null) {
+        view = spec.getView(GadgetSpec.DEFAULT_VIEW);
+      }
+    }
+    return view;
+  }
+}

Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingResults.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingResults.java?rev=699010&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingResults.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingResults.java Thu Sep 25 08:58:19 2008
@@ -0,0 +1,86 @@
+/*
+ * 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.render;
+
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.common.util.Check;
+
+/**
+ * Contains the results of a rendering operation.
+ */
+public class RenderingResults {
+  private final Status status;
+  private final String content;
+  private final String errorMessage;
+  private final Uri redirect;
+
+  private RenderingResults(Status status, String content, String errorMessage, Uri redirect) {
+    this.status = status;
+    this.content = content;
+    this.errorMessage = errorMessage;
+    this.redirect = redirect;
+  }
+
+  public static RenderingResults ok(String content) {
+    return new RenderingResults(Status.OK, content, null, null);
+  }
+
+  public static RenderingResults error(String errorMessage) {
+    return new RenderingResults(Status.ERROR, null, errorMessage, null);
+  }
+
+  public static RenderingResults mustRedirect(Uri redirect) {
+    return new RenderingResults(Status.MUST_REDIRECT, null, null, redirect);
+  }
+
+  /**
+   * @return The status of the rendering operation.
+   */
+  public Status getStatus() {
+    return status;
+  }
+
+  /**
+   * @return The content to render. Only available when status is OK.
+   */
+  public String getContent() {
+    Check.eq(status, Status.OK, "Only available when status is OK.");
+    return content;
+  }
+
+  /**
+   * @return The error message for rendering. Only available when status is ERROR.
+   */
+  public String getErrorMessage() {
+    Check.eq(status, Status.ERROR, "Only available when status is ERROR.");
+    return errorMessage;
+  }
+
+  /**
+   * @return The error message for rendering. Only available when status is ERROR.
+   */
+  public Uri getRedirect() {
+    Check.eq(status, Status.MUST_REDIRECT, "Only available when status is MUST_REDIRECT.");
+    return redirect;
+  }
+
+  public enum Status {
+    OK, MUST_REDIRECT, ERROR;
+  }
+}

Copied: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/HtmlRendererTest.java (from r698928, incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java)
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/HtmlRendererTest.java?p2=incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/HtmlRendererTest.java&p1=incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java&r1=698928&r2=699010&rev=699010&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/HtmlRendererTest.java Thu Sep 25 08:58:19 2008
@@ -23,24 +23,21 @@
 
 import org.apache.shindig.auth.AnonymousSecurityToken;
 import org.apache.shindig.auth.SecurityToken;
-import org.apache.shindig.common.ContainerConfig;
-import org.apache.shindig.common.ContainerConfigException;
 import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.common.xml.XmlUtil;
+import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.GadgetContext;
 import org.apache.shindig.gadgets.GadgetException;
-import org.apache.shindig.gadgets.GadgetSpecFactory;
 import org.apache.shindig.gadgets.http.ContentFetcherFactory;
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.preload.PreloaderService;
 import org.apache.shindig.gadgets.preload.Preloads;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.spec.View;
 
 import com.google.common.collect.Maps;
 
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 
 import java.net.URI;
@@ -50,121 +47,84 @@
 /**
  * Tests for Renderer
  */
-public class RendererTest {
+public class HtmlRendererTest {
   private static final Uri SPEC_URL = Uri.parse("http://example.org/gadget.xml");
   private static final String BASIC_HTML_CONTENT = "Hello, World!";
   private static final String PROXIED_HTML_CONTENT = "Hello, Universe!";
   private static final Uri PROXIED_HTML_HREF = Uri.parse("http://example.org/proxied.php");
-  private static final String GADGET =
-      "<Module>" +
-      " <ModulePrefs title='foo'/>" +
-      " <Content view='html' type='html'>" + BASIC_HTML_CONTENT + "</Content>" +
-      " <Content view='proxied' type='html' href='" + PROXIED_HTML_HREF + "'/>" +
-      " <Content view='proxied-signed' authz='signed' href='" + PROXIED_HTML_HREF + "'/>" +
-      " <Content view='proxied-oauth' authz='oauth' href='" + PROXIED_HTML_HREF + "'/>" +
-      " <Content view='url' type='url' href='http://example.org/always/an/error.html'/>" +
-      " <Content view='alias' type='html'>" + BASIC_HTML_CONTENT + "</Content>" +
-      "</Module>";
+  private static final GadgetContext CONTEXT = new GadgetContext() {
+    @Override
+    public URI getUrl() {
+      return SPEC_URL.toJavaUri();
+    }
+
+    @Override
+    public SecurityToken getToken() {
+      return new AnonymousSecurityToken();
+    }
+  };
 
-  private final FakeGadgetSpecFactory specFactory = new FakeGadgetSpecFactory();
   private final FakeContentFetcherFactory fetcher = new FakeContentFetcherFactory();
   private final FakePreloaderService preloaderService = new FakePreloaderService();
-  private FakeContainerConfig containerConfig;
-  private Renderer renderer;
+  private final HtmlRenderer renderer = new HtmlRenderer(fetcher, preloaderService);
 
-  @Before
-  public void setUp() throws Exception {
-    containerConfig = new FakeContainerConfig();
-    renderer = new Renderer(specFactory, fetcher, preloaderService, containerConfig);
-  }
-
-  private GadgetContext makeContext(final String view, final Uri specUrl) {
-    return new GadgetContext() {
-      @Override
-      public URI getUrl() {
-        return specUrl.toJavaUri();
-      }
-
-      @Override
-      public String getView() {
-        return view;
-      }
-
-      @Override
-      public SecurityToken getToken() {
-        return new AnonymousSecurityToken();
-      }
-    };
+  private Gadget makeGadget(String content) throws GadgetException {
+    GadgetSpec spec = new GadgetSpec(URI.create("#"),
+        "<Module><ModulePrefs title=''/><Content><![CDATA[" + content + "]]></Content></Module>");
+
+    return new Gadget()
+        .setSpec(spec)
+        .setContext(CONTEXT)
+        .setCurrentView(spec.getView("default"));
+  }
+
+  private Gadget makeHrefGadget(String authz) throws Exception {
+    Gadget gadget = makeGadget("");
+    String doc = "<Content href='" + PROXIED_HTML_HREF + "' authz='" + authz + "'/>";
+    View view = new View("proxied", Arrays.asList(XmlUtil.parse(doc)));
+    gadget.setCurrentView(view);
+    return gadget;
   }
 
   @Test
   public void renderPlainTypeHtml() throws Exception {
-    String content = renderer.render(makeContext("html", SPEC_URL));
+    String content = renderer.render(makeGadget(BASIC_HTML_CONTENT));
     assertEquals(BASIC_HTML_CONTENT, content);
   }
 
   @Test
-  public void renderProxiedTypeHtml() throws Exception {
+  public void renderProxied() throws Exception {
     fetcher.plainResponses.put(PROXIED_HTML_HREF, new HttpResponse(PROXIED_HTML_CONTENT));
-    String content = renderer.render(makeContext("proxied", SPEC_URL));
+    String content = renderer.render(makeHrefGadget("none"));
     assertEquals(PROXIED_HTML_CONTENT, content);
   }
 
-  @Test(expected = RenderingException.class)
-  public void renderTypeUrl() throws RenderingException {
-    renderer.render(makeContext("url", SPEC_URL));
-  }
-
-  @Test(expected = RenderingException.class)
-  public void renderInvalidUrl() throws RenderingException {
-    renderer.render(makeContext("url", Uri.parse("doesnotexist")));
-  }
-
   @Test
-  public void doPreloading() throws RenderingException {
-    renderer.render(makeContext("html", SPEC_URL));
-    assertTrue("Preloading not performed.", preloaderService.wasPreloaded);
-  }
-
-  @Test
-  public void renderProxiedSigned() throws RenderingException {
-    fetcher.oauthResponses.put(PROXIED_HTML_HREF, new HttpResponse(PROXIED_HTML_CONTENT));
-    String content = renderer.render(makeContext("proxied-signed", SPEC_URL));
+  public void renderProxiedSigned() throws Exception {
+    fetcher.signedResponses.put(PROXIED_HTML_HREF, new HttpResponse(PROXIED_HTML_CONTENT));
+    String content = renderer.render(makeHrefGadget("signed"));
     assertEquals(PROXIED_HTML_CONTENT, content);
   }
 
   @Test
-  public void renderProxiedOAuth() throws RenderingException {
+  public void renderProxiedOAuth() throws Exception {
+    // TODO: We need to disambiguate between oauth and signed.
     fetcher.oauthResponses.put(PROXIED_HTML_HREF, new HttpResponse(PROXIED_HTML_CONTENT));
-    String content = renderer.render(makeContext("proxied-oauth", SPEC_URL));
+    String content = renderer.render(makeHrefGadget("oauth"));
     assertEquals(PROXIED_HTML_CONTENT, content);
   }
 
   @Test
-  public void doViewAliasing() throws Exception {
-    JSONArray aliases = new JSONArray(Arrays.asList("alias"));
-    containerConfig.json.put("gadgets.features/views/aliased/aliases", aliases);
-    String content = renderer.render(makeContext("alias", SPEC_URL));
-    assertEquals(BASIC_HTML_CONTENT, content);
-  }
-
-  @Test(expected = RenderingException.class)
-  public void noSupportedViewThrows() throws RenderingException {
-    renderer.render(makeContext("not-real-view", SPEC_URL));
+  public void doPreloading() throws Exception {
+    renderer.render(makeGadget(BASIC_HTML_CONTENT));
+    assertTrue("Preloading not performed.", preloaderService.wasPreloaded);
   }
 
-  private static class FakeGadgetSpecFactory implements GadgetSpecFactory {
-    public GadgetSpec getGadgetSpec(GadgetContext context) throws GadgetException {
-      return new GadgetSpec(context.getUrl(), GADGET);
-    }
-
-    public GadgetSpec getGadgetSpec(URI uri, boolean ignoreCache) {
-      throw new UnsupportedOperationException();
-    }
-  }
+  // TODO: rewriting
 
   private static class FakeContentFetcherFactory extends ContentFetcherFactory {
     private final Map<Uri, HttpResponse> plainResponses = Maps.newHashMap();
+    private final Map<Uri, HttpResponse> signedResponses = Maps.newHashMap();
     private final Map<Uri, HttpResponse> oauthResponses = Maps.newHashMap();
 
     public FakeContentFetcherFactory() {
@@ -199,6 +159,8 @@
           response = plainResponses.get(request.getUri());
           break;
         case SIGNED:
+          response = signedResponses.get(request.getUri());
+          break;
         case OAUTH:
           response = oauthResponses.get(request.getUri());
           break;
@@ -221,17 +183,4 @@
       return null;
     }
   }
-
-  private static class FakeContainerConfig extends ContainerConfig {
-    private final JSONObject json = new JSONObject();
-
-    public FakeContainerConfig() throws ContainerConfigException {
-      super(null);
-    }
-
-    @Override
-    public Object getJson(String container, String parameter) {
-      return json.opt(parameter);
-    }
-  }
 }

Added: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderDispatcherTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderDispatcherTest.java?rev=699010&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderDispatcherTest.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderDispatcherTest.java Thu Sep 25 08:58:19 2008
@@ -0,0 +1,232 @@
+/*
+ * 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.render;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.shindig.common.ContainerConfig;
+import org.apache.shindig.common.ContainerConfigException;
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.gadgets.Gadget;
+import org.apache.shindig.gadgets.GadgetContext;
+import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.GadgetSpecFactory;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URI;
+import java.util.Arrays;
+
+/**
+ * Tests for RenderDispatcher.
+ */
+public class RenderDispatcherTest {
+  private static final Uri SPEC_URL = Uri.parse("http://example.org/gadget.xml");
+  private static final Uri TYPE_URL_HREF = Uri.parse("http://example.org/gadget.php");
+  private static final String BASIC_HTML_CONTENT = "Hello, World!";
+  private static final String GADGET =
+      "<Module>" +
+      " <ModulePrefs title='foo'/>" +
+      " <Content view='html' type='html'>" + BASIC_HTML_CONTENT + "</Content>" +
+      " <Content view='url' type='url' href='" + TYPE_URL_HREF + "'/>" +
+      " <Content view='alias' type='html'>" + BASIC_HTML_CONTENT + "</Content>" +
+      "</Module>";
+
+  private final FakeHtmlRenderer htmlRenderer = new FakeHtmlRenderer();
+  private final FakeGadgetSpecFactory gadgetSpecFactory = new FakeGadgetSpecFactory();
+  private FakeContainerConfig containerConfig;
+  private RenderDispatcher renderer;
+
+  @Before
+  public void setUp() throws Exception {
+    containerConfig = new FakeContainerConfig();
+    renderer = new RenderDispatcher(htmlRenderer, gadgetSpecFactory, containerConfig);
+  }
+
+  private GadgetContext makeContext(final String view, final Uri specUrl) {
+    return new GadgetContext() {
+      @Override
+      public URI getUrl() {
+        return specUrl.toJavaUri();
+      }
+
+      @Override
+      public String getView() {
+        return view;
+      }
+    };
+  }
+
+  @Test
+  public void renderTypeHtml() {
+    RenderingResults results = renderer.render(makeContext("html", SPEC_URL));
+    assertEquals(RenderingResults.Status.OK, results.getStatus());
+    assertEquals(BASIC_HTML_CONTENT, results.getContent());
+  }
+
+  @Test
+  public void renderTypeUrl() {
+    RenderingResults results = renderer.render(makeContext("url", SPEC_URL));
+    assertEquals(RenderingResults.Status.MUST_REDIRECT, results.getStatus());
+    assertEquals(TYPE_URL_HREF, results.getRedirect());
+  }
+
+  @Test
+  public void renderInvalidUrl() {
+    RenderingResults results = renderer.render(makeContext("url", Uri.parse("doesnotexist")));
+    assertEquals(RenderingResults.Status.ERROR, results.getStatus());
+    assertNotNull("No error message provided for invalid url.", results.getErrorMessage());
+  }
+
+  @Test
+  public void doViewAliasing() throws Exception {
+    JSONArray aliases = new JSONArray(Arrays.asList("some-alias", "alias"));
+    containerConfig.json.put("gadgets.features/views/aliased/aliases", aliases);
+    RenderingResults results = renderer.render(makeContext("aliased", SPEC_URL));
+    assertEquals(RenderingResults.Status.OK, results.getStatus());
+    assertEquals(BASIC_HTML_CONTENT, results.getContent());
+  }
+
+  @Test
+  public void noSupportedViewThrows() {
+    RenderingResults results = renderer.render(makeContext("not-real-view", SPEC_URL));
+    assertEquals(RenderingResults.Status.ERROR, results.getStatus());
+    assertNotNull("No error message provided for invalid view.", results.getErrorMessage());
+  }
+
+  @Test
+  public void handlesGadgetExceptionGracefully() {
+    gadgetSpecFactory.exception = new GadgetException(GadgetException.Code.INVALID_PATH, "foo");
+    RenderingResults results = renderer.render(makeContext("does-not-matter", SPEC_URL));
+    assertEquals(RenderingResults.Status.ERROR, results.getStatus());
+    assertEquals("foo", results.getErrorMessage());
+  }
+
+  @Test
+  public void handlesRenderingExceptionGracefully() {
+    htmlRenderer.exception = new RenderingException("oh no!");
+    RenderingResults results = renderer.render(makeContext("html", SPEC_URL));
+    assertEquals(RenderingResults.Status.ERROR, results.getStatus());
+    assertEquals("oh no!", results.getErrorMessage());
+  }
+
+  @Test
+  public void validateParent() throws Exception {
+    final String parent = "http://example.org/foo";
+    GadgetContext context = new GadgetContext() {
+      @Override
+      public URI getUrl() {
+        return SPEC_URL.toJavaUri();
+      }
+
+      @Override
+      public String getView() {
+        return "html";
+      }
+
+      @Override
+      public String getParameter(String name) {
+        if (name.equals("parent")) {
+          return parent;
+        }
+        return null;
+      }
+    };
+
+    containerConfig.json.put("gadgets.parent",
+        new JSONArray(Arrays.asList("http:\\/\\/example\\.org\\/[a-z]+", "localhost")));
+
+    RenderingResults results = renderer.render(context);
+    assertEquals(RenderingResults.Status.OK, results.getStatus());
+  }
+
+  @Test
+  public void validateBadParent() throws Exception {
+    final String parent = "http://example.org/foo";
+    GadgetContext context = new GadgetContext() {
+      @Override
+      public URI getUrl() {
+        return SPEC_URL.toJavaUri();
+      }
+
+      @Override
+      public String getParameter(String name) {
+        if (name.equals("parent")) {
+          return parent;
+        }
+        return null;
+      }
+    };
+
+    containerConfig.json.put("gadgets.parent",
+        new JSONArray(Arrays.asList("http:\\/\\/example\\.com\\/[a-z]+", "localhost")));
+
+    RenderingResults results = renderer.render(context);
+    assertEquals(RenderingResults.Status.ERROR, results.getStatus());
+    assertNotNull("No error message provided for bad parent.", results.getErrorMessage());
+  }
+
+  private static class FakeGadgetSpecFactory implements GadgetSpecFactory {
+    private GadgetException exception;
+    public GadgetSpec getGadgetSpec(GadgetContext context) throws GadgetException {
+      if (exception != null) {
+        throw exception;
+      }
+      return new GadgetSpec(context.getUrl(), GADGET);
+    }
+
+    public GadgetSpec getGadgetSpec(URI uri, boolean ignoreCache) {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  private static class FakeContainerConfig extends ContainerConfig {
+    private final JSONObject json = new JSONObject();
+
+    public FakeContainerConfig() throws ContainerConfigException {
+      super(null);
+    }
+
+    @Override
+    public Object getJson(String container, String parameter) {
+      return json.opt(parameter);
+    }
+  }
+
+  private static class FakeHtmlRenderer extends HtmlRenderer {
+    private RenderingException exception;
+
+    public FakeHtmlRenderer() {
+      super(null, null);
+    }
+
+    @Override
+    public String render(Gadget gadget) throws RenderingException {
+      if (exception != null) {
+        throw exception;
+      }
+      return gadget.getCurrentView().getContent();
+    }
+  }
+}