Author: etnu
Date: Sat Sep 6 20:15:47 2008
New Revision: 692769
URL: http://svn.apache.org/viewvc?rev=692769&view=rev
Log:
Added HttpPreloader. This will replace the Preload logic in GadgetServer when
the rendering pipeline cutover is complete.
Added:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/preload/HttpPreloaderTest.java
Added:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java?rev=692769&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java
Sat Sep 6 20:15:47 2008
@@ -0,0 +1,112 @@
+/*
+ * 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.preload;
+
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.gadgets.GadgetContext;
+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.OAuthArguments;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.spec.Preload;
+
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * Handles HTTP Preloading (/ModulePrefs/Preload elements).
+ *
+ * @see org.apache.shindig.gadgets.spec.Preload
+ */
+public class HttpPreloader implements Preloader {
+ // TODO: This needs to be fixed.
+ private final ContentFetcherFactory fetcher;
+
+ @Inject
+ public HttpPreloader(ContentFetcherFactory fetcherFactory) {
+ this.fetcher = fetcherFactory;
+ }
+
+ public Map<String, Callable<PreloadedData>> createPreloadTasks(GadgetContext
context,
+ GadgetSpec gadget) {
+ Map<String, Callable<PreloadedData>> preloads = Maps.newHashMap();
+
+ for (Preload preload : gadget.getModulePrefs().getPreloads()) {
+ preloads.put(preload.getHref().toString(), new PreloadTask(context,
preload));
+ }
+
+ return preloads;
+ }
+
+ private class PreloadTask implements Callable<PreloadedData> {
+ private final GadgetContext context;
+ private final Preload preload;
+
+ public PreloadTask(GadgetContext context, Preload preload) {
+ this.context = context;
+ this.preload = preload;
+ }
+
+ public PreloadedData call() throws Exception {
+ // TODO: This should be extracted into a common helper that takes any
+ // org.apache.shindig.gadgets.spec.RequestAuthenticationInfo.
+ HttpRequest request = new HttpRequest(Uri.fromJavaUri(preload.getHref()))
+ .setSignOwner(preload.isSignOwner())
+ .setSignViewer(preload.isSignViewer())
+ .setContainer(context.getContainer())
+ .setSecurityToken(context.getToken())
+ .setGadget(Uri.fromJavaUri(context.getUrl()));
+ HttpResponse response = null;
+ switch (preload.getAuthType()) {
+ case NONE:
+ response = fetcher.get().fetch(request);
+ break;
+ case SIGNED:
+ response =
fetcher.getSigningFetcher(context.getToken()).fetch(request);
+ break;
+ case OAUTH:
+ response = fetcher.getOAuthFetcher(context.getToken(), new
OAuthArguments(preload))
+ .fetch(request);
+ break;
+ }
+ return new HttpPreloadData(response);
+ }
+ }
+
+ /**
+ * Implements PreloadData by returning a Map that matches the output format
used by makeRequest.
+ */
+ private static class HttpPreloadData implements PreloadedData {
+ private final Map<String, String> data;
+
+ public HttpPreloadData(HttpResponse response) {
+ data = Maps.newHashMap(response.getMetadata());
+ data.put("body", response.getResponseAsString());
+ data.put("rc", Integer.toString(response.getHttpStatusCode()));
+ }
+
+ public Object toJson() {
+ return data;
+ }
+ }
+}
Added:
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/preload/HttpPreloaderTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/preload/HttpPreloaderTest.java?rev=692769&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/preload/HttpPreloaderTest.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/preload/HttpPreloaderTest.java
Sat Sep 6 20:15:47 2008
@@ -0,0 +1,201 @@
+/*
+ * 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.preload;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.shindig.auth.SecurityToken;
+import org.apache.shindig.common.testing.FakeGadgetToken;
+import org.apache.shindig.gadgets.GadgetContext;
+import org.apache.shindig.gadgets.http.ContentFetcherFactory;
+import org.apache.shindig.gadgets.http.HttpFetcher;
+import org.apache.shindig.gadgets.http.HttpRequest;
+import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.http.HttpResponseBuilder;
+import org.apache.shindig.gadgets.oauth.OAuthArguments;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.easymock.IMocksControl;
+import org.easymock.classextension.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * Tests for HttpPreloader.
+ */
+public class HttpPreloaderTest {
+ private static final String PRELOAD_HREF = "http://www.example.org/file";
+ private static final String PRELOAD_HREF2 = "http://www.example.org/file";
+ private static final String PRELOAD_CONTENT = "Preloaded data";
+ private static final String CONTAINER = "some-container";
+ private static final URI GADGET_URL =
URI.create("http://example.org/gadget.xml");
+ private static final Map<String, String> PRELOAD_METADATA =
Maps.immutableMap("foo", "bar");
+
+ private final IMocksControl control = EasyMock.createNiceControl();
+ private final ContentFetcherFactory fetchers =
control.createMock(ContentFetcherFactory.class);
+ private final RecordingHttpFetcher plainFetcher = new RecordingHttpFetcher();
+ private final RecordingHttpFetcher signedFetcher = new
RecordingHttpFetcher();
+ private final RecordingHttpFetcher oauthFetcher = new RecordingHttpFetcher();
+
+ private final GadgetContext context = new GadgetContext() {
+ @Override
+ public SecurityToken getToken() {
+ return new FakeGadgetToken();
+ }
+
+ @Override
+ public String getContainer() {
+ return CONTAINER;
+ }
+
+ @Override
+ public URI getUrl() {
+ return GADGET_URL;
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ expect(fetchers.get())
+ .andReturn(plainFetcher).anyTimes();
+ expect(fetchers.getSigningFetcher(isA(SecurityToken.class)))
+ .andReturn(signedFetcher).anyTimes();
+ expect(fetchers.getOAuthFetcher(isA(SecurityToken.class),
isA(OAuthArguments.class)))
+ .andReturn(oauthFetcher).anyTimes();
+ control.replay();
+ }
+
+ private void checkRequest(HttpRequest request) {
+ assertEquals(context.getContainer(), request.getContainer());
+ assertEquals(GADGET_URL.toString(), request.getGadget().toString());
+ assertEquals(context.getToken().getAppId(),
request.getSecurityToken().getAppId());
+ }
+
+ private static void checkResults(Map<String, String> results) {
+ assertEquals(PRELOAD_CONTENT, results.get("body"));
+ assertEquals(HttpResponse.SC_OK, Integer.parseInt(results.get("rc")));
+ assertTrue("Metadata values not copied to output.",
+ results.entrySet().containsAll(PRELOAD_METADATA.entrySet()));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void normalPreloads() throws Exception {
+ String xml =
+ "<Module><ModulePrefs title=''>" +
+ " <Preload href='" + PRELOAD_HREF + "'/>" +
+ "</ModulePrefs><Content/></Module>";
+ GadgetSpec gadget = new GadgetSpec(GADGET_URL, xml);
+ Preloader preloader = new HttpPreloader(fetchers);
+
+ Map<String, Callable<PreloadedData>> preloaded =
preloader.createPreloadTasks(context, gadget);
+
+ PreloadedData data = preloaded.get(PRELOAD_HREF).call();
+
+ checkRequest(plainFetcher.requests.get(0));
+ checkResults((Map<String, String>)data.toJson());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void signedPreloads() throws Exception {
+ String xml =
+ "<Module><ModulePrefs title=''>" +
+ " <Preload href='" + PRELOAD_HREF + "' authz='signed'
sign_viewer='false'/>" +
+ "</ModulePrefs><Content/></Module>";
+ GadgetSpec gadget = new GadgetSpec(GADGET_URL, xml);
+ Preloader preloader = new HttpPreloader(fetchers);
+
+ Map<String, Callable<PreloadedData>> preloaded =
preloader.createPreloadTasks(context, gadget);
+
+ PreloadedData data = preloaded.get(PRELOAD_HREF).call();
+
+ HttpRequest request = signedFetcher.requests.get(0);
+ checkRequest(request);
+ assertTrue(request.getSignOwner());
+ assertFalse(request.getSignViewer());
+ checkResults((Map<String, String>)data.toJson());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void oauthPreloads() throws Exception {
+ String xml =
+ "<Module><ModulePrefs title=''>" +
+ // This is kind of a bogus test since oauth params aren't set.
+ " <Preload href='" + PRELOAD_HREF + "' authz='oauth'/>" +
+ "</ModulePrefs><Content/></Module>";
+ GadgetSpec gadget = new GadgetSpec(GADGET_URL, xml);
+ Preloader preloader = new HttpPreloader(fetchers);
+
+ Map<String, Callable<PreloadedData>> preloaded =
preloader.createPreloadTasks(context, gadget);
+
+ PreloadedData data = preloaded.get(PRELOAD_HREF).call();
+
+ HttpRequest request = oauthFetcher.requests.get(0);
+ checkRequest(request);
+ checkResults((Map<String, String>)data.toJson());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void multiplePreloads() throws Exception {
+ String xml =
+ "<Module><ModulePrefs title=''>" +
+ " <Preload href='" + PRELOAD_HREF + "'/>" +
+ " <Preload href='" + PRELOAD_HREF2 + "'/>" +
+ "</ModulePrefs><Content/></Module>";
+ GadgetSpec gadget = new GadgetSpec(GADGET_URL, xml);
+ Preloader preloader = new HttpPreloader(fetchers);
+
+ Map<String, Callable<PreloadedData>> preloaded =
preloader.createPreloadTasks(context, gadget);
+
+ PreloadedData data = preloaded.get(PRELOAD_HREF).call();
+ checkRequest(plainFetcher.requests.get(0));
+ checkResults((Map<String, String>)data.toJson());
+
+ data = preloaded.get(PRELOAD_HREF2).call();
+ checkRequest(plainFetcher.requests.get(1));
+ checkResults((Map<String, String>)data.toJson());
+ }
+
+ private static class RecordingHttpFetcher implements HttpFetcher {
+ private List<HttpRequest> requests = Lists.newArrayList();
+
+ public HttpResponse fetch(HttpRequest request) {
+ requests.add(request);
+ return new HttpResponseBuilder()
+ .setMetadata(PRELOAD_METADATA)
+ .setResponseString(PRELOAD_CONTENT)
+ .create();
+ }
+ }
+}