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

svn commit: r683865 - in /incubator/shindig/trunk: features/core.io/ java/gadgets/src/main/java/org/apache/shindig/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/ java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ java...

Author: beaton
Date: Thu Aug  7 23:05:56 2008
New Revision: 683865

URL: http://svn.apache.org/viewvc?rev=683865&view=rev
Log:
Preloads for OAuth.


Added:
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestParamsTest.java
Modified:
    incubator/shindig/trunk/features/core.io/io.js
    incubator/shindig/trunk/features/core.io/iotest.js
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherFactory.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequestParams.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTaskTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpTestFixture.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/PreloadTest.java
    incubator/shindig/trunk/javascript/container/gadgets.js
    incubator/shindig/trunk/javascript/samplecontainer/examples/oauth.xml

Modified: incubator/shindig/trunk/features/core.io/io.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/core.io/io.js?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/features/core.io/io.js (original)
+++ incubator/shindig/trunk/features/core.io/io.js Thu Aug  7 23:05:56 2008
@@ -223,7 +223,16 @@
         if (preload.rc !== 200) {
           callback({errors : ["Error " + preload.rc]});
         } else {
-          callback(transformResponseData(params, { body: preload.body }));
+          if (preload.oauthState) {
+            oauthState = preload.oauthState;
+          }
+          var resp = {
+            body: preload.body,
+            oauthApprovalUrl: preload.oauthApprovalUrl,
+            oauthError: preload.oauthError,
+            oauthErrorText: preload.oauthErrorText,
+          }
+          callback(transformResponseData(params, resp));
         }
         return true;
       }

Modified: incubator/shindig/trunk/features/core.io/iotest.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/core.io/iotest.js?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/features/core.io/iotest.js (original)
+++ incubator/shindig/trunk/features/core.io/iotest.js Thu Aug  7 23:05:56 2008
@@ -766,3 +766,49 @@
       });
   this.assertEquals("not preloaded", resp.text);
 };
+
+IoTest.prototype.testPreload_oauthApproval = function() {
+  gadgets.io.clearOAuthState();
+  gadgets.io.preloaded_ = {
+    "http://target.example.com/somepage" : {
+      "rc" : 200,
+      "oauthState" : "stateinfo",
+      "oauthApprovalUrl" : "http://www.example.com/approve",
+    }
+  };
+
+  var req = new fakeXhr.Expectation("POST", "http://www.example.com/json");
+  this.setStandardArgs(req, true);
+  req.setBodyArg("url", "http://target.example.com/somepage");
+  req.setBodyArg("authz", "oauth");
+  req.setBodyArg("st", "authtoken");
+  req.setBodyArg("refresh", null);
+  req.setBodyArg("oauthState", "stateinfo");
+  req.setHeader("Content-Type", "application/x-www-form-urlencoded");
+
+  var resp = this.makeFakeResponse(gadgets.json.stringify(
+      { 'http://target.example.com/somepage' : { 
+          'body' : 'not preloaded',
+         }
+      }
+      ));
+
+  this.fakeXhrs.expect(req, resp);
+
+  var params = {};
+  params["AUTHORIZATION"] = "OAUTH";
+  var resp = null;
+  gadgets.io.makeRequest("http://target.example.com/somepage",
+      function(data) {
+        resp = data;
+      },
+      params);
+  this.assertEquals("http://www.example.com/approve", resp.oauthApprovalUrl);
+
+  gadgets.io.makeRequest("http://target.example.com/somepage",
+      function(data) {
+        resp = data;
+      },
+      params);
+  this.assertEquals("not preloaded", resp.text);
+};

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java Thu Aug  7 23:05:56 2008
@@ -20,6 +20,7 @@
 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.oauth.OAuthRequestParams;
 import org.apache.shindig.gadgets.spec.Auth;
 import org.apache.shindig.gadgets.spec.Feature;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
@@ -206,6 +207,9 @@
         case SIGNED:
           return preloadFetcherFactory.getSigningFetcher(context.getToken())
               .fetch(request);
+        case OAUTH:
+          return preloadFetcherFactory.getOAuthFetcher(context.getToken(),
+              new OAuthRequestParams(preload)).fetch(request);
         default:
           return HttpResponse.error();
       }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherFactory.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherFactory.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherFactory.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherFactory.java Thu Aug  7 23:05:56 2008
@@ -28,6 +28,7 @@
 import org.apache.shindig.gadgets.http.HttpFetcher;
 
 import com.google.inject.Inject;
+import com.google.inject.Singleton;
 
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -35,6 +36,7 @@
 /**
  * Produces OAuth content fetchers for input tokens.
  */
+@Singleton
 public class OAuthFetcherFactory {
 
   protected OAuthFetcherConfig fetcherConfig;

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequestParams.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequestParams.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequestParams.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequestParams.java Thu Aug  7 23:05:56 2008
@@ -18,8 +18,13 @@
  */
 package org.apache.shindig.gadgets.oauth;
 
+import java.util.Map;
+import java.util.TreeMap;
+
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.shindig.gadgets.spec.Preload;
+
 /**
  * Bundles information about a proxy request that requires OAuth
  */
@@ -32,20 +37,44 @@
   public static final String CLIENT_STATE_PARAM = "oauthState";
   public static final String BYPASS_SPEC_CACHE_PARAM = "bypassSpecCache";
 
-  protected final String serviceName;
-  protected final String tokenName;
-  protected final String requestToken;
-  protected final String requestTokenSecret;
-  protected final String origClientState;
-  protected final boolean bypassSpecCache;
+  protected String serviceName;
+  protected String tokenName;
+  protected String requestToken;
+  protected String requestTokenSecret;
+  protected String origClientState;
+  protected boolean bypassSpecCache;
 
+  @SuppressWarnings("unchecked")
   public OAuthRequestParams(HttpServletRequest request) {
-    serviceName = getParam(request, SERVICE_PARAM, "");
-    tokenName = getParam(request, TOKEN_PARAM, "");
-    requestToken = getParam(request, REQUEST_TOKEN_PARAM, null);
-    requestTokenSecret = getParam(request, REQUEST_TOKEN_SECRET_PARAM, null);
-    origClientState = getParam(request, CLIENT_STATE_PARAM, null);
-    bypassSpecCache = parseBypassSpecCacheParam(request);
+    Map<String, String> params = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
+    Map<String, String[]> reqParams = request.getParameterMap();
+    for (String name : reqParams.keySet()) {
+      params.put(name, reqParams.get(name)[0]);
+    }
+    init(params);
+  }
+  
+  public OAuthRequestParams(Preload preload) {
+    Map<String, String> attrs = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
+    attrs.putAll(preload.getAttributes());
+    init(attrs);
+  }
+  
+  private void init(Map<String, String> attrs) {
+    serviceName = getParam(attrs, SERVICE_PARAM, "");
+    tokenName = getParam(attrs, TOKEN_PARAM, "");
+    requestToken = getParam(attrs, REQUEST_TOKEN_PARAM, null);
+    requestTokenSecret = getParam(attrs, REQUEST_TOKEN_SECRET_PARAM, null);
+    origClientState = getParam(attrs, CLIENT_STATE_PARAM, null);
+    bypassSpecCache = "1".equals(getParam(attrs, BYPASS_SPEC_CACHE_PARAM, null));
+  }
+  
+  private String getParam(Map<String, String> attrs, String name, String def) {
+    String val = attrs.get(name);
+    if (val == null) {
+      val = def;
+    }
+    return val;
   }
 
   // Testing only
@@ -89,16 +118,4 @@
   public String getRequestTokenSecret() {
     return requestTokenSecret;
   }
-
-  public static boolean parseBypassSpecCacheParam(HttpServletRequest request) {
-    return "1".equals(request.getParameter(BYPASS_SPEC_CACHE_PARAM));
-  }
-  
-  private String getParam(HttpServletRequest request, String name, String def) {
-    String val = request.getParameter(name);
-    if (val == null) {
-      val = def;
-    }
-    return val;
-  }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java Thu Aug  7 23:05:56 2008
@@ -479,6 +479,10 @@
         JSONObject jsonEntry = new JSONObject();
         jsonEntry.put("body", response.getResponseAsString())
             .put("rc", response.getHttpStatusCode());
+        // Merge in additional response data
+        for (Map.Entry<String, String> metadata : response.getMetadata().entrySet()) {
+          jsonEntry.put(metadata.getKey(), metadata.getValue());
+        }
         resp.put(entry.getKey().getHref().toString(), jsonEntry);
       } catch (JSONException e) {
         logger.log(

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java Thu Aug  7 23:05:56 2008
@@ -22,10 +22,14 @@
 
 import org.apache.commons.lang.StringUtils;
 import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
 
 import java.net.URI;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -75,7 +79,15 @@
   public Set<String> getViews() {
     return views;
   }
-
+  
+  /**
+   * All attributes from the preload tag
+   */
+  private final Map<String, String> attributes;
+  public Map<String, String> getAttributes() {
+    return Collections.unmodifiableMap(attributes);
+  }
+  
   public Preload substitute(Substitutions substituter) {
     return new Preload(this, substituter);
   }
@@ -90,9 +102,18 @@
        .append(" authz='").append(auth.toString().toLowerCase()).append('\'')
        .append(" sign_owner='").append(signOwner).append('\'')
        .append(" sign_viewer='").append(signViewer).append('\'')
-       .append(" views='").append(StringUtils.join(views, ',')).append("'/>");
+       .append(" views='").append(StringUtils.join(views, ',')).append('\'');
+    for (String attr : attributes.keySet()) {
+      if (SKIP_AUTO_PARSE.contains(attr)) {
+        continue;
+      }
+      buf.append(' ').append(attr).append("='").append(attributes.get(attr))
+         .append('\'');
+    }
+    buf.append("/>");
     return buf.toString();
   }
+  
   /**
    * Creates a new Preload from an xml node.
    *
@@ -119,6 +140,28 @@
     this.views = Collections.unmodifiableSet(views);
 
     auth = Auth.parse(XmlUtil.getAttribute(preload, AUTHZ_ATTR));
+    
+    attributes = new HashMap<String, String>();
+    NamedNodeMap attrs = preload.getAttributes();
+    for (int i=0; i < attrs.getLength(); ++i) {
+      Node attr = attrs.item(i);
+      if (SKIP_AUTO_PARSE.contains(attr.getNodeName())) {
+        continue;
+      } 
+      attributes.put(attr.getNodeName(), attr.getNodeValue());
+    }
+  }
+
+  // Attributes we parse by hand.  Other attributes are automatically treated
+  // as plain strings for substitution purposes.
+  private static final Set<String> SKIP_AUTO_PARSE;
+  static {
+    SKIP_AUTO_PARSE = new HashSet<String>();
+    SKIP_AUTO_PARSE.add("href");
+    SKIP_AUTO_PARSE.add("views");
+    SKIP_AUTO_PARSE.add("sign_owner");
+    SKIP_AUTO_PARSE.add("sign_viewer");
+    SKIP_AUTO_PARSE.add(AUTHZ_ATTR);
   }
 
   private Preload(Preload preload, Substitutions substituter) {
@@ -127,5 +170,12 @@
     views = preload.views;
     auth = preload.auth;
     href = substituter.substituteUri(null, preload.href);
+    attributes = new HashMap<String, String>(preload.attributes);
+    for (Map.Entry<String, String> attr : attributes.entrySet()) {
+      if (SKIP_AUTO_PARSE.contains(attr.getKey())) {
+        continue;
+      }
+      attr.setValue(substituter.substituteString(null, attr.getValue()));
+    }
   }
-}
\ No newline at end of file
+}

Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java Thu Aug  7 23:05:56 2008
@@ -19,18 +19,20 @@
 
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.shindig.common.BasicSecurityToken;
 import org.apache.shindig.common.SecurityToken;
 import org.apache.shindig.common.crypto.BlobCrypterException;
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.oauth.OAuthRequestParams;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
 
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
 public class GadgetServerTest extends GadgetTestFixture {
 
   private final static URI SPEC_URL = URI.create("http://example.org/g.xml");
@@ -310,7 +312,33 @@
     Gadget gadget = gadgetServer.processGadget(BASIC_CONTEXT);
     assertTrue(gadget.getPreloadMap().size() == 1);
   }
+  
+  public void testOAuthPreload() throws Exception {
+    String preloadUrl = "http://example.org/preload.txt";
+    String preloadData = "Preload Data";
+    HttpRequest preloadRequest
+        = new HttpRequest(URI.create(preloadUrl));
+
+    String gadgetXml
+        = "<Module>" +
+        "  <ModulePrefs title=\"foo\">" +
+        "    <Preload href=\"" + preloadUrl + "\" authz=\"oauth\" " +
+        		    "oauth_service_name='service'/>" +
+        "  </ModulePrefs>" +
+        "  <Content type=\"html\" view=\"v1,v2\">dummy</Content>" +
+        "</Module>";
+    expect(fetcher.fetch(SPEC_REQUEST))
+        .andReturn(new HttpResponse(gadgetXml));
+    expect(fetcherFactory.getOAuthFetcher(
+        isA(SecurityToken.class), isA(OAuthRequestParams.class)))
+        .andReturn(fetcher);
+    expect(fetcher.fetch(preloadRequest))
+        .andReturn(new HttpResponse(preloadData));
+    replay();
 
+    Gadget gadget = gadgetServer.processGadget(BASIC_CONTEXT);
+    assertTrue(gadget.getPreloadMap().size() == 1);
+  }
 
   public void testBlacklistedGadget() throws Exception {
     expect(blacklist.isBlacklisted(eq(SPEC_URL))).andReturn(true);

Added: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestParamsTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestParamsTest.java?rev=683865&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestParamsTest.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestParamsTest.java Thu Aug  7 23:05:56 2008
@@ -0,0 +1,51 @@
+/*
+ * 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.oauth;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+import org.apache.shindig.common.xml.XmlUtil;
+import org.apache.shindig.gadgets.spec.Preload;
+import org.junit.Test;
+
+/**
+ * Tests parameter parsing
+ */
+public class OAuthRequestParamsTest {
+ 
+  @Test
+  public void testInitFromPreload() throws Exception {
+    String xml = "<Preload href='http://www.example.com' " +
+    		"oauth_service_name='service' " +
+    		"OAUTH_TOKEN_NAME='token' " +
+    		"OAUTH_REQuest_token='requesttoken' " +
+    		"oauth_request_token_secret='tokensecret' " +
+    		"/>";
+
+    Preload preload = new Preload(XmlUtil.parse(xml));
+    OAuthRequestParams params = new OAuthRequestParams(preload);
+    assertEquals("service", params.getServiceName());
+    assertEquals("token", params.getTokenName());
+    assertEquals("requesttoken", params.getRequestToken());
+    assertEquals("tokensecret", params.getRequestTokenSecret());
+    assertNull(params.getOrigClientState());
+    assertFalse(params.getBypassSpecCache());
+  }
+}

Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTaskTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTaskTest.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTaskTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTaskTest.java Thu Aug  7 23:05:56 2008
@@ -23,6 +23,7 @@
 import static org.easymock.EasyMock.isA;
 
 import org.apache.shindig.common.ContainerConfig;
+import org.apache.shindig.common.SecurityToken;
 import org.apache.shindig.common.SecurityTokenDecoder;
 import org.apache.shindig.common.testing.FakeGadgetToken;
 import org.apache.shindig.common.util.Utf8UrlCoder;
@@ -30,6 +31,8 @@
 import org.apache.shindig.gadgets.GadgetContext;
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.oauth.OAuthFetcher;
+import org.apache.shindig.gadgets.oauth.OAuthRequestParams;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
 
 import org.easymock.EasyMock;
@@ -65,6 +68,16 @@
         "<Content type='html' view='ALIAS'>" + ALT_CONTENT + "</Content>" +
         "</Module>";
   final static String LIBS = "dummy:blah";
+  
+  final static String PRELOAD_XML =
+      "<Module>" +
+      "<ModulePrefs title='hello'>" +
+      "<Preload authz='oauth' href='http://oauth.example.com'/>" +
+      "</ModulePrefs>" +
+      "<Content type='html' quirks='false'>" + CONTENT + "</Content>" +
+      "<Content type='html' view='quirks' quirks='true'/>" +
+      "<Content type='html' view='ALIAS'>" + ALT_CONTENT + "</Content>" +
+      "</Module>";
 
   private ServletTestFixture fixture;
 
@@ -80,9 +93,9 @@
    * @return Output of the rendering request
    * @throws Exception
    */
-  private String parseBasicGadget(String view) throws Exception {
+  private String parseBasicGadget(String view, String xml) throws Exception {
     expectParseRequestParams(view);
-    expectFetchGadget();
+    expectFetchGadget(xml);
     expectLockedDomainCheck();
     expectWriteResponse();
     replay();
@@ -99,6 +112,7 @@
     expect(fixture.request.getParameterNames()).andReturn(EMPTY_PARAMS);
     expect(fixture.request.getParameter("container")).andReturn(null);
     expect(fixture.request.getHeader("Host")).andReturn("www.example.org");
+    expect(fixture.request.getParameter("st")).andStubReturn("fake-token");
   }
 
   private void expectLockedDomainCheck() throws Exception {
@@ -108,8 +122,8 @@
         EasyMock.eq("default"))).andReturn(true);
   }
 
-  private void expectFetchGadget() throws Exception {
-    expect(fetcher.fetch(SPEC_REQUEST)).andReturn(new HttpResponse(SPEC_XML));
+  private void expectFetchGadget(String xml) throws Exception {
+    expect(fetcher.fetch(SPEC_REQUEST)).andReturn(new HttpResponse(xml));
   }
 
   private void expectWriteResponse() throws Exception {
@@ -117,18 +131,18 @@
   }
 
   public void testStandardsMode() throws Exception {
-    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     assertTrue(content.contains(GadgetRenderingTask.STRICT_MODE_DOCTYPE));
   }
 
   public void testQuirksMode() throws Exception {
-    String content = parseBasicGadget("quirks");
+    String content = parseBasicGadget("quirks", SPEC_XML);
     assertTrue(!content.contains(GadgetRenderingTask.STRICT_MODE_DOCTYPE));
   }
 
 
   public void testContentRendered() throws Exception {
-    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     assertTrue(content.contains(CONTENT));
   }
 
@@ -137,7 +151,7 @@
     String jsLibs = "http://example.org/js/foo:bar.js";
     expect(urlGenerator.getBundledJsUrl(isA(Collection.class),
         isA(GadgetContext.class))).andReturn(jsLibs);
-    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     assertTrue(content.contains("<script src=\"" + jsLibs + "\">"));
   }
 
@@ -146,14 +160,68 @@
     expect(containerConfig.getJsonArray(ContainerConfig.DEFAULT_CONTAINER,
         "gadgets.features/views/dummy/aliases")).andReturn(aliases);
 
-    String content = parseBasicGadget("dummy");
+    String content = parseBasicGadget("dummy", SPEC_XML);
 
     assertTrue(content.contains(ALT_CONTENT));
   }
+  
+  public void testOAuthPreload_data() throws Exception {
+    expectParseRequestParams(GadgetSpec.DEFAULT_VIEW);
+    expectFetchGadget(PRELOAD_XML);
+    expect(securityTokenDecoder.createToken(
+        Collections.singletonMap(SecurityTokenDecoder.SECURITY_TOKEN_NAME, "fake-token"))).
+        andStubReturn(mock(SecurityToken.class));
+    OAuthFetcher oauthFetcher = mock(OAuthFetcher.class);
+    expect(fetcherFactory.getOAuthFetcher(
+        isA(SecurityToken.class), isA(OAuthRequestParams.class))).
+        andReturn(oauthFetcher);
+
+    expect(oauthFetcher.fetch(isA(HttpRequest.class))).
+        andReturn(new HttpResponse("preloaded data"));
+
+    expectLockedDomainCheck();
+    expectWriteResponse();
+    replay();
+    fixture.replay();
+    gadgetRenderer.process(fixture.request, fixture.recorder);
+    verify();
+    fixture.verify();
+    String content = fixture.recorder.getResponseAsString();
+    assertTrue(content.contains("preloaded data"));
+  }
+  
+  public void testOAuthPreload_metadata() throws Exception {
+    expectParseRequestParams(GadgetSpec.DEFAULT_VIEW);
+    expectFetchGadget(PRELOAD_XML);
+    expect(securityTokenDecoder.createToken(
+        Collections.singletonMap(SecurityTokenDecoder.SECURITY_TOKEN_NAME, "fake-token"))).
+        andStubReturn(mock(SecurityToken.class));
+    OAuthFetcher oauthFetcher = mock(OAuthFetcher.class);
+    expect(fetcherFactory.getOAuthFetcher(
+        isA(SecurityToken.class), isA(OAuthRequestParams.class))).
+        andReturn(oauthFetcher);
+
+    HttpResponse resp = new HttpResponse(401, null, null);
+    resp.getMetadata().put(OAuthFetcher.APPROVAL_URL, "approval please");
+    resp.getMetadata().put(OAuthFetcher.CLIENT_STATE, "state blob");
+
+    expect(oauthFetcher.fetch(isA(HttpRequest.class))).andReturn(resp);
+
+    expectLockedDomainCheck();
+    expectWriteResponse();
+    replay();
+    fixture.replay();
+    gadgetRenderer.process(fixture.request, fixture.recorder);
+    verify();
+    fixture.verify();
+    String content = fixture.recorder.getResponseAsString();
+    assertTrue(content.contains("approval please"));
+    assertTrue(content.contains("state blob"));
+  }
 
   public void testLockedDomainFailure() throws Exception {
     expectParseRequestParams(GadgetSpec.DEFAULT_VIEW);
-    expectFetchGadget();
+    expectFetchGadget(SPEC_XML);
     expectLockedDomainFailure();
     expectSendRedirect();
     replay();
@@ -211,7 +279,7 @@
     expect(securityTokenDecoder.createToken(Collections.singletonMap(SecurityTokenDecoder.SECURITY_TOKEN_NAME, "fake-token"))).andReturn(
         new FakeGadgetToken().setUpdatedToken("updated-token")
         .setTrustedJson("{ \"foo\" : \"bar\" }"));
-    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     JSONObject auth = parseShindigAuthConfig(content);
     assertEquals("updated-token", auth.getString("authToken"));
     assertEquals("{ \"foo\" : \"bar\" }", auth.getString("trustedJson"));
@@ -221,7 +289,7 @@
     expect(fixture.request.getParameter("st")).andReturn("fake-token");
     expect(securityTokenDecoder.createToken(Collections.singletonMap(SecurityTokenDecoder.SECURITY_TOKEN_NAME, "fake-token"))).andReturn(
         new FakeGadgetToken());
-    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     JSONObject auth = parseShindigAuthConfig(content);
     assertEquals(0, auth.length());
   }
@@ -230,7 +298,7 @@
     expect(fixture.request.getParameter("st")).andReturn("fake-token");
     expect(securityTokenDecoder.createToken(Collections.singletonMap(SecurityTokenDecoder.SECURITY_TOKEN_NAME, "fake-token"))).andReturn(
         new FakeGadgetToken().setTrustedJson("trusted"));
-    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     JSONObject auth = parseShindigAuthConfig(content);
     assertEquals(1, auth.length());
     assertEquals("trusted", auth.getString("trustedJson"));
@@ -240,26 +308,26 @@
     expect(fixture.request.getParameter("st")).andReturn("fake-token");
     expect(securityTokenDecoder.createToken(Collections.singletonMap(SecurityTokenDecoder.SECURITY_TOKEN_NAME, "fake-token"))).andReturn(
         new FakeGadgetToken().setUpdatedToken("updated-token"));
-    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    String content = parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     JSONObject auth = parseShindigAuthConfig(content);
     assertEquals(1, auth.length());
     assertEquals("updated-token", auth.getString("authToken"));
   }
 
   public void testRenderSetsProperCacheControlHeaders() throws Exception {
-    parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     fixture.checkCacheControlHeaders(GadgetRenderingTask.DEFAULT_CACHE_TTL, true);
   }
 
   public void testRenderSetsLongLivedCacheControlHeadersWhenVParamIsSet() throws Exception {
     expect(fixture.request.getParameter("v")).andReturn("some value");
-    parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     fixture.checkCacheControlHeaders(HttpUtil.DEFAULT_TTL, true);
   }
 
   public void testRenderSetsNoCacheHeadersWhenNoCacheParamIsSet() throws Exception {
     expect(fixture.request.getParameter("nocache")).andReturn("1");
-    parseBasicGadget(GadgetSpec.DEFAULT_VIEW);
+    parseBasicGadget(GadgetSpec.DEFAULT_VIEW, SPEC_XML);
     fixture.checkCacheControlHeaders(0, true);
   }
 

Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpTestFixture.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpTestFixture.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpTestFixture.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpTestFixture.java Thu Aug  7 23:05:56 2008
@@ -20,7 +20,6 @@
 
 import org.apache.shindig.gadgets.GadgetTestFixture;
 import org.apache.shindig.gadgets.LockedDomainService;
-import org.apache.shindig.gadgets.http.ContentFetcherFactory;
 import org.apache.shindig.gadgets.rewrite.ContentRewriter;
 import org.apache.shindig.gadgets.rewrite.NoOpContentRewriter;
 
@@ -31,8 +30,6 @@
 public abstract class HttpTestFixture extends GadgetTestFixture {
   public final GadgetRenderingTask gadgetRenderer;
   public final JsonRpcHandler jsonRpcHandler;
-  public final ContentFetcherFactory contentFetcherFactory
-      = mock(ContentFetcherFactory.class);
   public final UrlGenerator urlGenerator = mock(UrlGenerator.class);
   public final LockedDomainService lockedDomainService =
     mock(LockedDomainService.class);

Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java Thu Aug  7 23:05:56 2008
@@ -315,6 +315,8 @@
         .andReturn("fake-token").atLeastOnce();
     expect(fixture.request.getParameter(Preload.AUTHZ_ATTR))
         .andReturn(Auth.OAUTH.toString()).atLeastOnce();
+    // This isn't terribly accurate, but is close enough for this test.
+    expect(fixture.request.getParameterMap()).andStubReturn(Collections.EMPTY_MAP);
     fixture.replay();
 
     handler.fetch(fixture.request, fixture.recorder);

Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/PreloadTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/PreloadTest.java?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/PreloadTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/PreloadTest.java Thu Aug  7 23:05:56 2008
@@ -20,6 +20,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import org.apache.shindig.common.xml.XmlUtil;
@@ -120,13 +121,28 @@
 
     assertEquals(HREF, substituted.getHref().toString());
   }
+  
+  @Test
+  public void arbitraryAttributes() throws Exception {
+    String xml = "<Preload href='" + HREF + "' foo='bar' yo='momma' sub='__MSG_preload__'/>";
+    
+    Preload preload = new Preload(XmlUtil.parse(xml));
+    Substitutions substituter = new Substitutions();
+    substituter.addSubstitution(Substitutions.Type.MESSAGE, "preload", "stuff");
+    Preload substituted = preload.substitute(substituter);
+    assertEquals("bar", substituted.getAttributes().get("foo"));
+    assertEquals("momma", substituted.getAttributes().get("yo"));
+    assertEquals("stuff", substituted.getAttributes().get("sub"));
+    assertNull(substituted.getAttributes().get("href"));
+  }
 
   @Test
   public void toStringIsSane() throws Exception {
     String xml = "<Preload" +
     		     " href='" + HREF + '\'' +
     		     " sign_owner='false'" +
-    		     " views='" + StringUtils.join(VIEWS, ',') + "'/>";
+    		     " views='" + StringUtils.join(VIEWS, ',') + "'" +
+    		     " some_attribute='yes' />";
 
     Preload preload = new Preload(XmlUtil.parse(xml));
     Preload preload2 = new Preload(XmlUtil.parse(preload.toString()));
@@ -135,6 +151,7 @@
     assertFalse(preload2.isSignOwner());
     assertEquals(VIEWS, preload2.getViews());
     assertEquals(HREF, preload2.getHref().toString());
+    assertEquals("yes", preload2.getAttributes().get("some_attribute"));
   }
 
   @Test(expected = SpecParserException.class)

Modified: incubator/shindig/trunk/javascript/container/gadgets.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/gadgets.js?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/gadgets.js (original)
+++ incubator/shindig/trunk/javascript/container/gadgets.js Thu Aug  7 23:05:56 2008
@@ -545,9 +545,9 @@
       (this.debug ? '&debug=1' : '') +
       this.getAdditionalParams() +
       this.getUserPrefsParams() +
+      (this.secureToken ? '&st=' + this.secureToken : '') +
       '&url=' + encodeURIComponent(this.specUrl) +
       '#rpctoken=' + this.rpcToken +
-      (this.secureToken ? '&st=' + this.secureToken : '') +
       (this.viewParams ?
           '&view-params=' +  encodeURIComponent(JSON.stringify(this.viewParams)) : '') +
       (this.hashData ? '&' + this.hashData : '');

Modified: incubator/shindig/trunk/javascript/samplecontainer/examples/oauth.xml
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/samplecontainer/examples/oauth.xml?rev=683865&r1=683864&r2=683865&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/samplecontainer/examples/oauth.xml (original)
+++ incubator/shindig/trunk/javascript/samplecontainer/examples/oauth.xml Thu Aug  7 23:05:56 2008
@@ -8,6 +8,7 @@
         <Authorization url="http://localhost:9090/oauth-provider/authorize" />
       </Service>
     </OAuth>
+    <Preload authz="oauth" href="http://localhost:9090/oauth-provider/echo" />
   </ModulePrefs>
   <Content type="html">
       <![CDATA[