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/06/13 21:36:57 UTC
svn commit: r667626 - in /incubator/shindig/trunk/java/gadgets/src:
main/java/org/apache/shindig/gadgets/
main/java/org/apache/shindig/gadgets/spec/
test/java/org/apache/shindig/gadgets/
Author: etnu
Date: Fri Jun 13 12:36:56 2008
New Revision: 667626
URL: http://svn.apache.org/viewvc?rev=667626&view=rev
Log:
Applied patch for SHINDIG-363 from Patrick Fairbank, with some small modifications and extensive new tests for BasicGadgetSpecFactory.
Added:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ViewContentFetcher.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/ViewContentFetcherTest.java
Modified:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.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/GadgetTestFixture.java
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java?rev=667626&r1=667625&r2=667626&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java Fri Jun 13 12:36:56 2008
@@ -18,10 +18,6 @@
*/
package org.apache.shindig.gadgets;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-
import org.apache.shindig.common.cache.Cache;
import org.apache.shindig.common.cache.LruCache;
import org.apache.shindig.gadgets.http.HttpFetcher;
@@ -31,8 +27,15 @@
import org.apache.shindig.gadgets.spec.GadgetSpec;
import org.apache.shindig.gadgets.spec.View;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+
import java.net.URI;
-import java.util.logging.Level;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.logging.Logger;
/**
@@ -41,27 +44,32 @@
@Singleton
public class BasicGadgetSpecFactory implements GadgetSpecFactory {
- private static final Logger logger
- = Logger.getLogger(BasicGadgetSpecFactory.class.getName());
+ private static final Logger logger = Logger.getLogger(BasicGadgetSpecFactory.class.getName());
private final HttpFetcher specFetcher;
-
private final ContentRewriter rewriter;
-
+ private final Executor executor;
private final long specMinTTL;
// A cache of GadgetSpecs with expirations
private final Cache<URI, SpecTimeoutPair> inMemorySpecCache;
- public GadgetSpec getGadgetSpec(GadgetContext context)
- throws GadgetException {
+ public GadgetSpec getGadgetSpec(GadgetContext context) throws GadgetException {
return getGadgetSpec(context.getUrl(), context.getIgnoreCache());
}
- public GadgetSpec getGadgetSpec(URI gadgetUri, boolean ignoreCache)
- throws GadgetException {
+ /**
+ * Retrieves a gadget specification from the cache or from the Internet.
+ */
+ public GadgetSpec getGadgetSpec(URI gadgetUri, boolean ignoreCache) throws GadgetException {
+ if (ignoreCache) {
+ return fetchGadgetSpecFromWeb(gadgetUri, true);
+ }
+
GadgetSpec spec = null;
long expiration = -1;
+
+ // Attempt to retrieve the gadget spec from the cache.
synchronized (inMemorySpecCache) {
SpecTimeoutPair gadgetSpecEntry = inMemorySpecCache.getElement(gadgetUri);
if (gadgetSpecEntry != null) {
@@ -69,52 +77,91 @@
expiration = gadgetSpecEntry.timeout;
}
}
- if (ignoreCache || spec == null || expiration < System.currentTimeMillis()) {
+
+ // If the gadget spec is not in the cache or has expired, fetch it from its URI.
+ if (spec == null || expiration < System.currentTimeMillis()) {
try {
- HttpRequest request = HttpRequest.getRequest(
- gadgetUri, ignoreCache);
- HttpResponse response = specFetcher.fetch(request);
- if (response.getHttpStatusCode() != HttpResponse.SC_OK) {
- throw new GadgetException(
- GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT,
- "Unable to retrieve gadget xml. HTTP error " +
- response.getHttpStatusCode());
- } else {
- spec = new GadgetSpec(gadgetUri, response.getResponseAsString());
- for (View v : spec.getViews().values()) {
- if (v.getType() == View.ContentType.HTML && rewriter != null) {
- v.setRewrittenContent(
- rewriter.rewriteGadgetView(spec, v.getContent(), "text/html"));
- }
- }
- // Add the updated spec back to the cache and force the min TTL
- expiration = Math
- .max(response.getCacheExpiration(), System.currentTimeMillis() + specMinTTL);
- synchronized (inMemorySpecCache) {
- inMemorySpecCache.addElement(gadgetUri, new SpecTimeoutPair(spec, expiration));
- }
- }
- } catch (GadgetException ge) {
+ return fetchGadgetSpecFromWeb(gadgetUri, false);
+ } catch (GadgetException e) {
if (spec == null) {
- throw ge;
+ throw e;
} else {
- logger.log(Level.WARNING,
- "Gadget spec fetch failed for " + gadgetUri + " - using cached ", ge);
+ logger.info("Gadget spec fetch failed for " + gadgetUri + " - using cached ");
}
}
}
+
+ return spec;
+ }
+
+ /**
+ * Retrieves a gadget specification from the Internet, processes its views and
+ * adds it to the cache.
+ */
+ private GadgetSpec fetchGadgetSpecFromWeb(URI gadgetUri, boolean ignoreCache)
+ throws GadgetException {
+ HttpRequest request = HttpRequest.getRequest(gadgetUri, ignoreCache);
+ HttpResponse response = specFetcher.fetch(request);
+ if (response.getHttpStatusCode() != HttpResponse.SC_OK) {
+ throw new GadgetException(GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT,
+ "Unable to retrieve gadget xml. HTTP error " +
+ response.getHttpStatusCode());
+ }
+ GadgetSpec spec = new GadgetSpec(gadgetUri, response.getResponseAsString());
+
+ // Find the type=HTML views that link to their content externally.
+ List<View> hrefViewList = new ArrayList<View>();
+ for (View v : spec.getViews().values()) {
+ if (v.getType() != View.ContentType.URL && v.getHref() != null) {
+ hrefViewList.add(v);
+ }
+ }
+
+ // Retrieve all external view contents simultaneously.
+ CountDownLatch latch = new CountDownLatch(hrefViewList.size());
+ for (View v : hrefViewList) {
+ executor.execute(new ViewContentFetcher(v, latch, specFetcher, ignoreCache));
+ }
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ for (View v : spec.getViews().values()) {
+ if (v.getType() != View.ContentType.URL) {
+ // A non-null href at this point indicates that the retrieval of remote
+ // content has failed.
+ if (v.getHref() != null) {
+ throw new GadgetException(GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT,
+ "Unable to retrieve remote gadget content.");
+ }
+ if (rewriter != null) {
+ v.setRewrittenContent(rewriter.rewriteGadgetView(spec, v.getContent(), "text/html"));
+ }
+ }
+ }
+
+ // Add the updated spec back to the cache and force the min TTL
+ long expiration = Math.max(
+ response.getCacheExpiration(), System.currentTimeMillis() + specMinTTL);
+ synchronized (inMemorySpecCache) {
+ inMemorySpecCache.addElement(gadgetUri, new SpecTimeoutPair(spec, expiration));
+ }
+
return spec;
}
@Inject
public BasicGadgetSpecFactory(HttpFetcher specFetcher,
- ContentRewriter rewriter,
- @Named("gadget-spec.cache.capacity")int gadgetSpecCacheCapacity,
- @Named("gadget-spec.cache.minTTL")long minTTL) {
+ ContentRewriter rewriter,
+ Executor executor,
+ @Named("gadget-spec.cache.capacity")int gadgetSpecCacheCapacity,
+ @Named("gadget-spec.cache.minTTL")long minTTL) {
this.specFetcher = specFetcher;
this.rewriter = rewriter;
- this.inMemorySpecCache = new LruCache<URI, SpecTimeoutPair>(
- gadgetSpecCacheCapacity);
+ this.executor = executor;
+ this.inMemorySpecCache = new LruCache<URI, SpecTimeoutPair>(gadgetSpecCacheCapacity);
this.specMinTTL = minTTL;
}
@@ -127,4 +174,4 @@
this.timeout = timeout;
}
}
-}
\ No newline at end of file
+}
Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ViewContentFetcher.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ViewContentFetcher.java?rev=667626&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ViewContentFetcher.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ViewContentFetcher.java Fri Jun 13 12:36:56 2008
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+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.spec.View;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.logging.Logger;
+
+/**
+ * Retrieves the content pointed to by the href in a type=html view and inserts
+ * it into the view.
+ */
+public class ViewContentFetcher implements Runnable {
+ private static final Logger logger = Logger.getLogger(ViewContentFetcher.class.getName());
+ private final View view;
+ private final CountDownLatch latch;
+ private final HttpFetcher httpFetcher;
+ private final boolean ignoreCache;
+
+ public ViewContentFetcher(View view,
+ CountDownLatch latch,
+ HttpFetcher httpFetcher,
+ boolean ignoreCache) {
+ this.view = view;
+ this.latch = latch;
+ this.httpFetcher = httpFetcher;
+ this.ignoreCache = ignoreCache;
+ }
+
+ /**
+ * Retrieves the remote view content.
+ */
+ public void run() {
+ HttpRequest request = HttpRequest.getRequest(view.getHref(), ignoreCache);
+ try {
+ HttpResponse response = httpFetcher.fetch(request);
+ if (response.getHttpStatusCode() != HttpResponse.SC_OK) {
+ throw new GadgetException(GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT,
+ "Unable to retrieve gadget content. HTTP error " +
+ response.getHttpStatusCode());
+ } else {
+ view.setContent(response.getResponseAsString());
+
+ // Reset the href since the content is now inline; a non-null href will
+ // indicate a failed retrieval attempt.
+ view.setHref(null);
+ }
+ } catch (GadgetException e) {
+ logger.info("Failed to retrieve content at " + view.getHref());
+ }
+ latch.countDown();
+ }
+}
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java?rev=667626&r1=667625&r2=667626&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java Fri Jun 13 12:36:56 2008
@@ -64,6 +64,9 @@
public URI getHref() {
return href;
}
+ public void setHref(URI href) {
+ this.href = href;
+ }
/**
* Content@quirks
@@ -98,6 +101,9 @@
public String getContent() {
return content;
}
+ public void setContent(String content) {
+ this.content = content;
+ }
/**
* Whether or not the content section has any __UP_ hangman variables.
@@ -190,9 +196,6 @@
if (type == ContentType.URL && this.href == null) {
throw new SpecParserException(
"Content@href must be set when Content@type is \"url\".");
- } else if (type == ContentType.HTML && this.href != null) {
- throw new SpecParserException(
- "Content@href must not be set when Content@type is not \"url\".");
}
}
Added: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java?rev=667626&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java Fri Jun 13 12:36:56 2008
@@ -0,0 +1,237 @@
+/*
+ * 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;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+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.rewrite.ContentRewriter;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+
+import com.google.common.collect.Maps;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+/**
+ * Tests for BasicGadgetSpecFactory
+ */
+public class BasicGadgetSpecFactoryTest {
+ private final static URI SPEC_URL = URI.create("http://example.org/gadget.xml");
+ private final static URI REMOTE_URL = URI.create("http://example.org/remote.html");
+ private final static String LOCAL_CONTENT = "Hello, local content!";
+ private final static String ALT_LOCAL_CONTENT = "Hello, local content!";
+ private final static String REMOTE_CONTENT = "Hello, remote content!";
+ private final static String LOCAL_SPEC_XML
+ = "<Module>" +
+ " <ModulePrefs title='GadgetSpecFactoryTest'/>" +
+ " <Content type='html'>" + LOCAL_CONTENT + "</Content>" +
+ "</Module>";
+ private final static String ALT_LOCAL_SPEC_XML
+ = "<Module>" +
+ " <ModulePrefs title='GadgetSpecFactoryTest'/>" +
+ " <Content type='html'>" + ALT_LOCAL_CONTENT + "</Content>" +
+ "</Module>";
+ private final static String REMOTE_SPEC_XML
+ = "<Module>" +
+ " <ModulePrefs title='GadgetSpecFactoryTest'/>" +
+ " <Content type='html' href='" + REMOTE_URL + "'/>" +
+ "</Module>";
+ private final static String URL_SPEC_XML
+ = "<Module>" +
+ " <ModulePrefs title='GadgetSpecFactoryTest'/>" +
+ " <Content type='url' href='" + REMOTE_URL + "'/>" +
+ "</Module>";
+
+ private final static GadgetContext NO_CACHE_CONTEXT = new GadgetContext() {
+ @Override
+ public boolean getIgnoreCache() {
+ return true;
+ }
+ @Override
+ public URI getUrl() {
+ return SPEC_URL;
+ }
+ };
+ private final static Executor FAKE_EXECUTOR = new Executor() {
+ public void execute(Runnable runnable) {
+ runnable.run();
+ }
+ };
+
+ private final HttpFetcher fetcher = EasyMock.createNiceMock(HttpFetcher.class);
+ private final CaptureRewriter rewriter = new CaptureRewriter();
+
+ private final BasicGadgetSpecFactory specFactory
+ = new BasicGadgetSpecFactory(fetcher, rewriter, FAKE_EXECUTOR, 5, -1000);
+
+ @Test
+ public void specFetched() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ HttpResponse response = new HttpResponse(LOCAL_SPEC_XML);
+ expect(fetcher.fetch(request)).andReturn(response);
+ replay(fetcher);
+
+ GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL, true);
+
+ assertEquals(LOCAL_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getContent());
+ assertEquals(LOCAL_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getRewrittenContent());
+ assertTrue("Content not rewritten.", rewriter.rewroteView);
+ }
+
+ @Test
+ public void specFetchedWithContext() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ HttpResponse response = new HttpResponse(LOCAL_SPEC_XML);
+ expect(fetcher.fetch(request)).andReturn(response);
+ replay(fetcher);
+
+ GadgetSpec spec = specFactory.getGadgetSpec(NO_CACHE_CONTEXT);
+
+ assertEquals(LOCAL_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getContent());
+ assertEquals(LOCAL_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getRewrittenContent());
+ assertTrue("Content not rewritten.", rewriter.rewroteView);
+ }
+
+ @Test
+ public void staleSpecIsRefetched() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ Map<String, List<String>> headers = Maps.newHashMap();
+ headers.put("Pragma", Arrays.asList("no-cache"));
+ HttpResponse expiredResponse = new HttpResponse(
+ HttpResponse.SC_OK, LOCAL_SPEC_XML.getBytes("UTF-8"), headers);
+ HttpResponse updatedResponse = new HttpResponse(ALT_LOCAL_SPEC_XML);
+ expect(fetcher.fetch(request)).andReturn(expiredResponse).once();
+ expect(fetcher.fetch(request)).andReturn(updatedResponse).once();
+ replay(fetcher);
+
+ specFactory.getGadgetSpec(SPEC_URL, true);
+ GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL, false);
+
+ assertEquals(ALT_LOCAL_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getContent());
+ assertEquals(ALT_LOCAL_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getRewrittenContent());
+ assertTrue("Content not rewritten.", rewriter.rewroteView);
+ }
+
+ @Test
+ public void staleSpecReturnedFromCacheOnError() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ Map<String, List<String>> headers = Maps.newHashMap();
+ headers.put("Pragma", Arrays.asList("no-cache"));
+ HttpResponse expiredResponse = new HttpResponse(
+ HttpResponse.SC_OK, LOCAL_SPEC_XML.getBytes("UTF-8"), headers);
+ expect(fetcher.fetch(request)).andReturn(expiredResponse);
+ expect(fetcher.fetch(request)).andReturn(HttpResponse.notFound()).once();
+ replay(fetcher);
+
+ specFactory.getGadgetSpec(SPEC_URL, true);
+ GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL, false);
+
+ assertEquals(ALT_LOCAL_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getContent());
+ assertEquals(ALT_LOCAL_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getRewrittenContent());
+ assertTrue("Content not rewritten.", rewriter.rewroteView);
+ }
+
+ @Test
+ public void externalContentFetched() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ HttpResponse response = new HttpResponse(REMOTE_SPEC_XML);
+ HttpRequest viewRequest = HttpRequest.getRequest(REMOTE_URL, true);
+ HttpResponse viewResponse = new HttpResponse(REMOTE_CONTENT);
+ expect(fetcher.fetch(request)).andReturn(response);
+ expect(fetcher.fetch(viewRequest)).andReturn(viewResponse);
+ replay(fetcher);
+
+ GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL, true);
+
+ assertEquals(REMOTE_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getContent());
+ assertEquals(REMOTE_CONTENT, spec.getView(GadgetSpec.DEFAULT_VIEW).getRewrittenContent());
+ assertTrue("Content not rewritten.", rewriter.rewroteView);
+ }
+
+ @Test
+ public void typeUrlNotFetchedRemote() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ HttpResponse response = new HttpResponse(URL_SPEC_XML);
+ expect(fetcher.fetch(request)).andReturn(response);
+ replay(fetcher);
+
+ GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL, true);
+
+ assertEquals(REMOTE_URL, spec.getView(GadgetSpec.DEFAULT_VIEW).getHref());
+ assertEquals("", spec.getView(GadgetSpec.DEFAULT_VIEW).getContent());
+ assertEquals(null, spec.getView(GadgetSpec.DEFAULT_VIEW).getRewrittenContent());
+ assertFalse("Content was rewritten for type=url.", rewriter.rewroteView);
+ }
+
+ @Test(expected = GadgetException.class)
+ public void badFetchThrows() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ expect(fetcher.fetch(request)).andReturn(HttpResponse.error());
+ replay(fetcher);
+
+ GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL, true);
+ }
+
+ @Test(expected = GadgetException.class)
+ public void badRemoteContentThrows() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ HttpResponse response = new HttpResponse(REMOTE_SPEC_XML);
+ HttpRequest viewRequest = HttpRequest.getRequest(REMOTE_URL, true);
+ expect(fetcher.fetch(request)).andReturn(response);
+ expect(fetcher.fetch(viewRequest)).andReturn(HttpResponse.error());
+ replay(fetcher);
+
+ GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL, true);
+ }
+
+ @Test(expected = GadgetException.class)
+ public void throwingFetcherRethrows() throws Exception {
+ HttpRequest request = HttpRequest.getRequest(SPEC_URL, true);
+ expect(fetcher.fetch(request)).andThrow(
+ new GadgetException(GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT));
+ replay(fetcher);
+
+ GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL, true);
+ }
+
+ private static class CaptureRewriter implements ContentRewriter {
+ private boolean rewroteView = false;
+
+ public HttpResponse rewrite(HttpRequest request, HttpResponse original) {
+ return original;
+ }
+
+ public String rewriteGadgetView(GadgetSpec spec, String original, String mimeType) {
+ rewroteView = true;
+ return original;
+ }
+ }
+}
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=667626&r1=667625&r2=667626&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 Fri Jun 13 12:36:56 2008
@@ -91,6 +91,22 @@
gadget.getSpec().getModulePrefs().getTitle());
}
+ public void testGadgetSpecLookupWithFetcherFailure() throws Exception {
+ HttpResponse resp = new HttpResponse(HttpResponse.SC_NOT_FOUND);
+
+ expect(fetcher.fetch(SPEC_REQUEST)).andReturn(resp);
+ replay();
+
+ try {
+ Gadget gadget = gadgetServer.processGadget(BASIC_CONTEXT);
+ fail("Expected a GadgetException for a failed http fetch.");
+ } catch (GadgetException e) {
+ // Expected for a bad gadget spec URI.
+ }
+
+ verify();
+ }
+
public void testSubstitutionsDone() throws Exception {
String gadgetXml
= "<Module>" +
@@ -318,4 +334,59 @@
}
verify();
}
+
+ public void testViewContentFetching() throws Exception {
+ URI viewUri = URI.create("http://example.org/content.htm");
+ String gadgetXml
+ = "<Module>" +
+ " <ModulePrefs title=\"foo\">" +
+ " </ModulePrefs>" +
+ " <Content type=\"html\" href=\"" + viewUri +"\" view=\"bar\" />" +
+ "</Module>";
+ String content ="<h2>foo</h2>";
+
+ HttpResponse spec = new HttpResponse(gadgetXml);
+ expect(fetcher.fetch(SPEC_REQUEST)).andReturn(spec);
+
+ HttpRequest viewContentRequest = new HttpRequest(viewUri);
+ HttpResponse viewContentResponse = new HttpResponse(content);
+ expect(fetcher.fetch(viewContentRequest)).andReturn(viewContentResponse);
+
+ replay();
+
+ Gadget gadget = gadgetServer.processGadget(BASIC_CONTEXT);
+
+ verify();
+
+ assertNull(gadget.getSpec().getView("bar").getHref());
+ assertEquals(content, gadget.getSpec().getView("bar").getContent());
+ }
+
+ public void testViewContentFetchingWithBadHref() throws Exception {
+ URI viewUri = URI.create("http://example.org/nonexistantcontent.htm");
+ String gadgetXml
+ = "<Module>" +
+ " <ModulePrefs title=\"foo\">" +
+ " </ModulePrefs>" +
+ " <Content type=\"html\" href=\"" + viewUri +"\" view=\"bar\" />" +
+ "</Module>";
+
+ HttpResponse spec = new HttpResponse(gadgetXml);
+ expect(fetcher.fetch(SPEC_REQUEST)).andReturn(spec);
+
+ HttpRequest viewContentRequest = new HttpRequest(viewUri);
+ HttpResponse viewContentResponse = new HttpResponse(HttpResponse.SC_NOT_FOUND);
+ expect(fetcher.fetch(viewContentRequest)).andReturn(viewContentResponse);
+
+ replay();
+
+ try {
+ Gadget gadget = gadgetServer.processGadget(BASIC_CONTEXT);
+ fail("Expected a GadgetException for a failed http fetch of remote gadget content.");
+ } catch (GadgetException e) {
+ // Expected for a bad content href URI.
+ }
+
+ verify();
+ }
}
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java?rev=667626&r1=667625&r2=667626&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java Fri Jun 13 12:36:56 2008
@@ -39,8 +39,6 @@
= mock(ContentFetcherFactory.class);
public final HttpFetcher fetcher = mock(HttpFetcher.class);
public final GadgetBlacklist blacklist = mock(GadgetBlacklist.class);
- public final GadgetSpecFactory specFactory =
- new BasicGadgetSpecFactory(fetcher, new NoOpContentRewriter(), 0, 0L);
public final MessageBundleFactory bundleFactory =
new BasicMessageBundleFactory(fetcher, 0, 0L);
public GadgetFeatureRegistry registry;
@@ -50,6 +48,8 @@
r.run();
}
};
+ public final GadgetSpecFactory specFactory = new BasicGadgetSpecFactory(
+ fetcher, new NoOpContentRewriter(), executor, 0, 0L);
public GadgetTestFixture() {
Added: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/ViewContentFetcherTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/ViewContentFetcherTest.java?rev=667626&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/ViewContentFetcherTest.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/ViewContentFetcherTest.java Fri Jun 13 12:36:56 2008
@@ -0,0 +1,117 @@
+/*
+ * 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;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.apache.shindig.common.xml.XmlUtil;
+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.spec.View;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.w3c.dom.Element;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Tests for ViewContentFetcher
+ */
+public class ViewContentFetcherTest {
+ private final HttpFetcher fetcher = EasyMock.createNiceMock(HttpFetcher.class);
+ private final static URI CONTENT_URI = URI.create("http://example.com/content.htm");
+ private final static String CONTENT = "<h2>foo</h2>";
+ private final static String VIEW_XML = "<Content type='html' href='" + CONTENT_URI + "' />";
+
+ @Test
+ public void getViewContent() throws Exception {
+ List<Element> elementList = new ArrayList<Element>();
+ elementList.add(XmlUtil.parse(VIEW_XML));
+ View view = new View(null, elementList);
+ CountDownLatch latch = new CountDownLatch(1);
+
+ HttpResponse response = new HttpResponse(CONTENT);
+ expect(fetcher.fetch(isA(HttpRequest.class))).andReturn(response).once();
+
+ replay(fetcher);
+
+ ViewContentFetcher viewContentFetcher = new ViewContentFetcher(view, latch, fetcher, false);
+ viewContentFetcher.run();
+
+ verify(fetcher);
+
+ assertNull(view.getHref());
+ assertEquals(CONTENT, view.getContent());
+ assertEquals(0, latch.getCount());
+ }
+
+ @Test
+ public void httpFetchException() throws Exception {
+ List<Element> elementList = new ArrayList<Element>();
+ elementList.add(XmlUtil.parse(VIEW_XML));
+ View view = new View(null, elementList);
+ CountDownLatch latch = new CountDownLatch(1);
+
+ expect(fetcher.fetch(isA(HttpRequest.class))).andThrow(
+ new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR)).once();
+
+ replay(fetcher);
+
+ ViewContentFetcher viewContentFetcher = new ViewContentFetcher(view, latch, fetcher, false);
+ viewContentFetcher.run();
+
+ verify(fetcher);
+
+ assertEquals(CONTENT_URI, view.getHref());
+ assertEquals("", view.getContent());
+ assertEquals(0, latch.getCount());
+ }
+
+ @Test
+ public void httpResponseNotOk() throws Exception {
+ List<Element> elementList = new ArrayList<Element>();
+ elementList.add(XmlUtil.parse(VIEW_XML));
+ View view = new View(null, elementList);
+ CountDownLatch latch = new CountDownLatch(1);
+
+ HttpResponse response = new HttpResponse(HttpResponse.SC_NOT_FOUND);
+ expect(fetcher.fetch(isA(HttpRequest.class))).andReturn(response).once();
+
+ replay(fetcher);
+
+ ViewContentFetcher viewContentFetcher = new ViewContentFetcher(view, latch, fetcher, false);
+ viewContentFetcher.run();
+
+ verify(fetcher);
+
+ assertEquals(CONTENT_URI, view.getHref());
+ assertEquals("", view.getContent());
+ assertEquals(0, latch.getCount());
+ }
+}