From cb2c7ff419beb17ed3305a42a6ff1081909be298 Mon Sep 17 00:00:00 2001 From: Steve Terlecki Date: Mon, 27 Sep 2010 11:35:37 -0400 Subject: [PATCH 1/8] Fix for forcing the setupFrame method in the rpc.js file to always setup the iFrame's RPC channel. Particularly important when switching views of a gadget while staying on the same page. --- features/src/main/javascript/features/rpc/rpc.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/src/main/javascript/features/rpc/rpc.js b/features/src/main/javascript/features/rpc/rpc.js index c39c95ef8..78e4e54d4 100644 --- a/features/src/main/javascript/features/rpc/rpc.js +++ b/features/src/main/javascript/features/rpc/rpc.js @@ -407,8 +407,8 @@ gadgets.rpc = function() { * RPC mechanism. Gadgets, in turn, will complete the setup * of the channel once they send their first messages. */ - function setupFrame(frameId, token, forcesecure) { - if (setup[frameId] === true) { + function setupFrame(frameId, token, forcesecure, forceFrameSetup) { + if (setup[frameId] === true && !(forceFrameSetup === true)) { return; } @@ -521,7 +521,7 @@ gadgets.rpc = function() { * @member gadgets.rpc * @deprecated */ - function setAuthToken(targetId, token, forcesecure) { + function setAuthToken(targetId, token, forcesecure, forceFrameSetup) { token = token || ""; // Coerce token to a String, ensuring that all authToken values @@ -529,7 +529,7 @@ gadgets.rpc = function() { // in the process(rpc) method. authToken[targetId] = String(token); - setupFrame(targetId, token, forcesecure); + setupFrame(targetId, token, forcesecure, forceFrameSetup); } function setupContainerGadgetContext(rpctoken, opt_forcesecure) { From 8f36aea65347e9fcee05261fc4be28ba87b30c99 Mon Sep 17 00:00:00 2001 From: Steve Terlecki Date: Wed, 29 Sep 2010 08:08:03 -0400 Subject: [PATCH 2/8] Adding support for feed image in the FeedProcessor class so that the image configured for the main feed is available in the json returned to the gadget. --- .../apache/shindig/gadgets/FeedProcessor.java | 22 +++++++++++++++++++ .../shindig/gadgets/FeedProcessorTest.java | 10 +++++++++ 2 files changed, 32 insertions(+) diff --git a/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java b/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java index 6db45bfc7..f72b1c02a 100644 --- a/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java +++ b/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java @@ -30,6 +30,7 @@ import com.sun.syndication.feed.synd.SyndContent; import com.sun.syndication.feed.synd.SyndEntry; import com.sun.syndication.feed.synd.SyndFeed; +import com.sun.syndication.feed.synd.SyndImage; import com.sun.syndication.feed.synd.SyndPerson; import com.sun.syndication.io.FeedException; import com.sun.syndication.io.SyndFeedInput; @@ -67,6 +68,27 @@ public JSONObject process(String feedUrl, String feedXml, boolean getSummaries, json.put("Description", feed.getDescription()); json.put("Link", feed.getLink()); + //Retrieve the feed image if it is available as well as an image url if the image is available. + if(feed.getImage() != null && !feed.getImage().getUrl().isEmpty()){ + SyndImage feedImage = (SyndImage)feed.getImage(); + JSONObject jsonImage = new JSONObject(); + jsonImage.put("Url", feedImage.getUrl()); + if(feedImage.getTitle() != null + && !feedImage.getTitle().isEmpty()){ + jsonImage.put("Title", feedImage.getTitle()); + } + if(feedImage.getDescription() != null && + !feedImage.getDescription().isEmpty()){ + jsonImage.put("Description", feedImage.getDescription()); + } + if(feedImage.getLink() != null && + !feedImage.getLink().isEmpty()){ + jsonImage.put("Link", feedImage.getLink()); + } + json.put("Image", jsonImage); + } + + List authors = feed.getAuthors(); String jsonAuthor = null; if (authors != null && !authors.isEmpty()) { diff --git a/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java b/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java index bc839a4d0..9949be0bd 100644 --- a/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java +++ b/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java @@ -33,6 +33,10 @@ public class FeedProcessorTest { private final static String FEED_TITLE = "Example Feed"; private final static String FEED_AUTHOR = "John Doe"; private final static String FEED_AUTHOR_EMAIL = "john.doe@example.com"; + private final static String FEED_IMAGE_URL = "http://example.org/example.gif"; + private final static String FEED_IMAGE_TITLE = "Example Feed Image"; + private final static String FEED_IMAGE_DESCRIPTION = "Example Feed Image Description"; + private final static String FEED_IMAGE_LINK = "http://example.org/"; private final static String FEED_ENTRY_TITLE = "Atom-Powered Robots Run Amok"; private final static String FEED_ENTRY_LINK = "http://example.org/2003/12/13/entry03"; private final static String FEED_ENTRY_SUMMARY = "Some text."; @@ -46,6 +50,12 @@ public class FeedProcessorTest { "http://example.org/" + "Example RSS Feed" + "Sun, 19 May 2002 15:21:36 GMT" + + "" + + "" + FEED_IMAGE_URL + "" + + "" + FEED_IMAGE_TITLE + "" + + "" + FEED_IMAGE_DESCRIPTION + "" + + "" + FEED_IMAGE_LINK + "" + + "" + "" + "" + FEED_ENTRY_TITLE + "" + "" + FEED_ENTRY_LINK + "" + From 8fcc9f9a93f4e61ba614f890f7c3ce5f5d9bdc58 Mon Sep 17 00:00:00 2001 From: Steve Terlecki Date: Wed, 29 Sep 2010 10:55:25 -0400 Subject: [PATCH 3/8] Updating the JsonRpcHandler.java class to include the description field for the gadget metadata. This is part of the gadget spec and makes sense to have available along with the other info that the JsonRpcHandler.java provides. --- .../org/apache/shindig/gadgets/servlet/JsonRpcHandler.java | 1 + .../org/apache/shindig/gadgets/servlet/FakeProcessor.java | 3 ++- .../apache/shindig/gadgets/servlet/JsonRpcHandlerTest.java | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsonRpcHandler.java b/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsonRpcHandler.java index 3e470875c..bf859234a 100644 --- a/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsonRpcHandler.java +++ b/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsonRpcHandler.java @@ -218,6 +218,7 @@ protected JSONObject getGadgetJson(Gadget gadget, GadgetSpec spec) .put("moduleId", context.getModuleId()) .put("title", prefs.getTitle()) .put("titleUrl", prefs.getTitleUrl().toString()) + .put("description", prefs.getDescription()) .put("views", views) .put("features", features) .put("featureDetails", featureDetailList) diff --git a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/FakeProcessor.java b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/FakeProcessor.java index 5b4108254..879733dcc 100644 --- a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/FakeProcessor.java +++ b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/FakeProcessor.java @@ -37,13 +37,14 @@ public class FakeProcessor extends Processor { public static final Uri SPEC_URL2 = Uri.parse("http://example.org/g2.xml"); public static final String SPEC_TITLE = "JSON-TEST"; public static final String SPEC_TITLE2 = "JSON-TEST2"; + public static final String SPEC_DESCRIPTION = "JSON-DESCRIPTION"; public static final int PREFERRED_HEIGHT = 100; public static final int PREFERRED_WIDTH = 242; public static final String LINK_REL = "rel"; public static final String LINK_HREF = "http://example.org/foo"; public static final String SPEC_XML = "" + - "" + + "" + " " + "" + "" + diff --git a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/JsonRpcHandlerTest.java b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/JsonRpcHandlerTest.java index 38f26866f..70bc6822a 100644 --- a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/JsonRpcHandlerTest.java +++ b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/JsonRpcHandlerTest.java @@ -71,6 +71,7 @@ public void testSimpleRequest() throws Exception { JSONObject gadget = outGadgets.getJSONObject(0); assertEquals(FakeProcessor.SPEC_URL.toString(), gadget.getString("iframeUrl")); assertEquals(FakeProcessor.SPEC_TITLE, gadget.getString("title")); + assertEquals(FakeProcessor.SPEC_DESCRIPTION, gadget.getString("description")); assertEquals(0, gadget.getInt("moduleId")); JSONObject view = gadget.getJSONObject("views").getJSONObject(GadgetSpec.DEFAULT_VIEW); @@ -135,10 +136,12 @@ public void testMultipleGadgets() throws Exception { JSONObject gadget = outGadgets.getJSONObject(i); if (gadget.getString("url").equals(FakeProcessor.SPEC_URL.toString())) { assertEquals(FakeProcessor.SPEC_TITLE, gadget.getString("title")); + assertEquals(FakeProcessor.SPEC_DESCRIPTION, gadget.getString("description")); assertEquals(0, gadget.getInt("moduleId")); first = true; } else { assertEquals(FakeProcessor.SPEC_TITLE2, gadget.getString("title")); + assertEquals(false, gadget.has("description")); assertEquals(1, gadget.getInt("moduleId")); second = true; } @@ -170,6 +173,7 @@ public void testMultipleGadgetsWithAnError() throws Exception { JSONObject gadget = outGadgets.getJSONObject(i); if (gadget.getString("url").equals(FakeProcessor.SPEC_URL.toString())) { assertEquals(FakeProcessor.SPEC_TITLE, gadget.getString("title")); + assertEquals(FakeProcessor.SPEC_DESCRIPTION, gadget.getString("description")); assertEquals(0, gadget.getInt("moduleId")); first = true; } else { From 4fd5f559ae512c8920adf379998a39a5d3903d9f Mon Sep 17 00:00:00 2001 From: Steve Terlecki Date: Fri, 1 Oct 2010 10:12:53 -0400 Subject: [PATCH 4/8] Fix for json stringify. The stringify method includes undefined objects in the json string output which causes the json parse method to throw a Syntax error. This is a problem for the requestNavigateTo rpc call because it includes optional arguments. If those arguments aren't supplied, they still get included in the output of stringify. This appears to only be a problem in IE7. --- features/src/main/javascript/features/core.json/json.js | 1 - 1 file changed, 1 deletion(-) diff --git a/features/src/main/javascript/features/core.json/json.js b/features/src/main/javascript/features/core.json/json.js index 41544e3b7..996d738cc 100644 --- a/features/src/main/javascript/features/core.json/json.js +++ b/features/src/main/javascript/features/core.json/json.js @@ -175,7 +175,6 @@ if (window.JSON && window.JSON.parse && window.JSON.stringify) { // Join all of the member texts together and wrap them in braces. return '{' + a.join(',') + '}'; } - return "undefined"; } return { From 448ffbe1ccfa5882a56bc5b51aeff629e9dcdb72 Mon Sep 17 00:00:00 2001 From: Steve Terlecki Date: Fri, 1 Oct 2010 10:14:02 -0400 Subject: [PATCH 5/8] Simpler approach to fixing the issue with re-establishing the rpc channel. Rather than skipping the setup if it appears to already be configured, when setupFrame is called always setup the frame. --- features/src/main/javascript/features/rpc/rpc.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/features/src/main/javascript/features/rpc/rpc.js b/features/src/main/javascript/features/rpc/rpc.js index 78e4e54d4..c7bcc0f62 100644 --- a/features/src/main/javascript/features/rpc/rpc.js +++ b/features/src/main/javascript/features/rpc/rpc.js @@ -407,12 +407,9 @@ gadgets.rpc = function() { * RPC mechanism. Gadgets, in turn, will complete the setup * of the channel once they send their first messages. */ - function setupFrame(frameId, token, forcesecure, forceFrameSetup) { - if (setup[frameId] === true && !(forceFrameSetup === true)) { - return; - } + function setupFrame(frameId, token, forcesecure) { - if (typeof setup[frameId] === 'undefined') { + if (typeof setup[frameId] === 'undefined') { setup[frameId] = 0; } @@ -521,7 +518,7 @@ gadgets.rpc = function() { * @member gadgets.rpc * @deprecated */ - function setAuthToken(targetId, token, forcesecure, forceFrameSetup) { + function setAuthToken(targetId, token, forcesecure) { token = token || ""; // Coerce token to a String, ensuring that all authToken values @@ -529,7 +526,7 @@ gadgets.rpc = function() { // in the process(rpc) method. authToken[targetId] = String(token); - setupFrame(targetId, token, forcesecure, forceFrameSetup); + setupFrame(targetId, token, forcesecure); } function setupContainerGadgetContext(rpctoken, opt_forcesecure) { From 9c3b4b6651fdfb3b2595db21d07e3e0b6d4a51a0 Mon Sep 17 00:00:00 2001 From: billwolckenlmco Date: Tue, 19 Oct 2010 18:15:27 -0400 Subject: [PATCH 6/8] Convert FeedProcessor to an interface and allow for Guice-injected replacement. --- .../apache/shindig/gadgets/FeedProcessor.java | 156 +------------ .../shindig/gadgets/FeedProcessorImpl.java | 208 ++++++++++++++++++ .../gadgets/servlet/HttpRequestHandler.java | 8 +- .../gadgets/servlet/MakeRequestHandler.java | 8 +- ...orTest.java => FeedProcessorImplTest.java} | 10 +- .../servlet/HttpRequestHandlerTest.java | 11 +- .../servlet/MakeRequestHandlerTest.java | 2 +- .../servlet/MakeRequestServletTest.java | 2 +- .../gadgets/servlet/ServletTestFixture.java | 9 + 9 files changed, 253 insertions(+), 161 deletions(-) create mode 100644 java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessorImpl.java rename java/gadgets/src/test/java/org/apache/shindig/gadgets/{FeedProcessorTest.java => FeedProcessorImplTest.java} (98%) diff --git a/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java b/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java index f72b1c02a..1c2e4d71c 100644 --- a/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java +++ b/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java @@ -39,10 +39,14 @@ import org.json.JSONException; import org.json.JSONObject; +import com.google.inject.ImplementedBy; + + /** * Processes RSS & Atom Feeds and converts them into JSON output. */ -public class FeedProcessor { +@ImplementedBy(FeedProcessorImpl.class) +public interface FeedProcessor { /** * Converts feed XML to JSON. @@ -57,152 +61,6 @@ public class FeedProcessor { * Number of entries to return. * @return The JSON representation of the feed. */ - @SuppressWarnings("unchecked") - public JSONObject process(String feedUrl, String feedXml, boolean getSummaries, int numEntries) - throws GadgetException { - try { - SyndFeed feed = new SyndFeedInput().build(new StringReader(feedXml)); - JSONObject json = new JSONObject(); - json.put("Title", feed.getTitle()); - json.put("URL", feedUrl); - json.put("Description", feed.getDescription()); - json.put("Link", feed.getLink()); - - //Retrieve the feed image if it is available as well as an image url if the image is available. - if(feed.getImage() != null && !feed.getImage().getUrl().isEmpty()){ - SyndImage feedImage = (SyndImage)feed.getImage(); - JSONObject jsonImage = new JSONObject(); - jsonImage.put("Url", feedImage.getUrl()); - if(feedImage.getTitle() != null - && !feedImage.getTitle().isEmpty()){ - jsonImage.put("Title", feedImage.getTitle()); - } - if(feedImage.getDescription() != null && - !feedImage.getDescription().isEmpty()){ - jsonImage.put("Description", feedImage.getDescription()); - } - if(feedImage.getLink() != null && - !feedImage.getLink().isEmpty()){ - jsonImage.put("Link", feedImage.getLink()); - } - json.put("Image", jsonImage); - } - - - List authors = feed.getAuthors(); - String jsonAuthor = null; - if (authors != null && !authors.isEmpty()) { - SyndPerson author = authors.get(0); - if (author.getName() != null) { - jsonAuthor = author.getName(); - } else if (author.getEmail() != null) { - jsonAuthor = author.getEmail(); - } - } - JSONArray entries = new JSONArray(); - json.put("Entry", entries); - - int entryCnt = 0; - for (Object obj : feed.getEntries()) { - SyndEntry e = (SyndEntry) obj; - if (entryCnt >= numEntries) { - break; - } - entryCnt++; - - JSONObject entry = new JSONObject(); - entry.put("Title", e.getTitle()); - entry.put("Link", e.getLink()); - if (getSummaries) { - if (e.getContents() != null && !e.getContents().isEmpty()) { - entry.put("Summary", ((SyndContent) e.getContents().get(0)).getValue()); - } else { - entry.put("Summary", e.getDescription() != null ? e.getDescription().getValue() : ""); - } - } - - if (e.getUpdatedDate() != null) { - entry.put("Date", e.getUpdatedDate().getTime()); - } else if (e.getPublishedDate() != null) { - entry.put("Date", e.getPublishedDate().getTime()); - } else { - entry.put("Date", 0); - } - - // if no author at feed level, use the first entry author - if (jsonAuthor == null) { - jsonAuthor = e.getAuthor(); - } - - JSONObject media = new JSONObject(); - MediaEntryModule mediaModule = (MediaEntryModule) e.getModule(MediaModule.URI); - if (mediaModule != null) { - if (mediaModule.getMediaContents().length > 0) { - JSONArray contents = new JSONArray(); - - for (MediaContent c : mediaModule.getMediaContents()) { - JSONObject content = new JSONObject(); - - if (c.getReference() instanceof UrlReference) { - content.put("URL", ((UrlReference) c.getReference()).getUrl().toString()); - } - - if (c.getType() != null) { - content.put("Type", c.getType()); - } - - if (c.getWidth() != null) { - content.put("Width", c.getWidth()); - } - - if (c.getHeight() != null) { - content.put("Height", c.getHeight()); - } - - contents.put(content); - } - - media.put("Contents", contents); - } - - if (mediaModule.getMetadata() != null) { - if (mediaModule.getMetadata().getThumbnail().length > 0) { - // "If multiple thumbnails are included, it is assumed that they are in order of importance" - // Only use the first thumbnail for simplicity's - // sake - - JSONObject thumbnail = new JSONObject(); - - Thumbnail t = mediaModule.getMetadata().getThumbnail()[0]; - thumbnail.put("URL", t.getUrl().toString()); - - if (t.getWidth() != null) { - thumbnail.put("Width", t.getWidth()); - } - - if (t.getHeight() != null) { - thumbnail.put("Height", t.getHeight()); - } - - media.put("Thumbnail", thumbnail); - } - } - } - - entry.put("Media", media); - - entries.put(entry); - } - - json.put("Author", (jsonAuthor != null) ? jsonAuthor : ""); - return json; - } catch (JSONException e) { - // This shouldn't ever happen. - throw new RuntimeException(e); - } catch (FeedException e) { - throw new GadgetException(GadgetException.Code.MALFORMED_XML_DOCUMENT, e, HttpResponse.SC_BAD_GATEWAY); - } catch (IllegalArgumentException e) { - throw new GadgetException(GadgetException.Code.MALFORMED_XML_DOCUMENT, e, HttpResponse.SC_BAD_GATEWAY); - } - } + JSONObject process(String feedUrl, String feedXml, boolean getSummaries, int numEntries) + throws GadgetException; } diff --git a/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessorImpl.java b/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessorImpl.java new file mode 100644 index 000000000..8035340ba --- /dev/null +++ b/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessorImpl.java @@ -0,0 +1,208 @@ +/* + * 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 java.io.StringReader; +import java.util.List; + +import com.sun.syndication.feed.module.mediarss.types.UrlReference; + +import com.sun.syndication.feed.module.mediarss.MediaEntryModule; +import com.sun.syndication.feed.module.mediarss.MediaModule; +import com.sun.syndication.feed.module.mediarss.types.MediaContent; +import com.sun.syndication.feed.module.mediarss.types.Thumbnail; +import com.sun.syndication.feed.synd.SyndContent; +import com.sun.syndication.feed.synd.SyndEntry; +import com.sun.syndication.feed.synd.SyndFeed; +import com.sun.syndication.feed.synd.SyndImage; +import com.sun.syndication.feed.synd.SyndPerson; +import com.sun.syndication.io.FeedException; +import com.sun.syndication.io.SyndFeedInput; +import org.apache.shindig.gadgets.http.HttpResponse; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Processes RSS & Atom Feeds and converts them into JSON output. + */ +public class FeedProcessorImpl implements FeedProcessor { + + /** + * Converts feed XML to JSON. + * + * @param feedUrl + * The url that the feed was retrieved from. + * @param feedXml + * The raw XML of the feed to be converted. + * @param getSummaries + * True if summaries should be returned. + * @param numEntries + * Number of entries to return. + * @return The JSON representation of the feed. + */ + @SuppressWarnings("unchecked") + public JSONObject process(String feedUrl, String feedXml, boolean getSummaries, int numEntries) + throws GadgetException { + try { + SyndFeed feed = new SyndFeedInput().build(new StringReader(feedXml)); + JSONObject json = new JSONObject(); + json.put("Title", feed.getTitle()); + json.put("URL", feedUrl); + json.put("Description", feed.getDescription()); + json.put("Link", feed.getLink()); + + //Retrieve the feed image if it is available as well as an image url if the image is available. + if(feed.getImage() != null && !feed.getImage().getUrl().isEmpty()){ + SyndImage feedImage = (SyndImage)feed.getImage(); + JSONObject jsonImage = new JSONObject(); + jsonImage.put("Url", feedImage.getUrl()); + if(feedImage.getTitle() != null + && !feedImage.getTitle().isEmpty()){ + jsonImage.put("Title", feedImage.getTitle()); + } + if(feedImage.getDescription() != null && + !feedImage.getDescription().isEmpty()){ + jsonImage.put("Description", feedImage.getDescription()); + } + if(feedImage.getLink() != null && + !feedImage.getLink().isEmpty()){ + jsonImage.put("Link", feedImage.getLink()); + } + json.put("Image", jsonImage); + } + + + List authors = feed.getAuthors(); + String jsonAuthor = null; + if (authors != null && !authors.isEmpty()) { + SyndPerson author = authors.get(0); + if (author.getName() != null) { + jsonAuthor = author.getName(); + } else if (author.getEmail() != null) { + jsonAuthor = author.getEmail(); + } + } + JSONArray entries = new JSONArray(); + json.put("Entry", entries); + + int entryCnt = 0; + for (Object obj : feed.getEntries()) { + SyndEntry e = (SyndEntry) obj; + if (entryCnt >= numEntries) { + break; + } + entryCnt++; + + JSONObject entry = new JSONObject(); + entry.put("Title", e.getTitle()); + entry.put("Link", e.getLink()); + if (getSummaries) { + if (e.getContents() != null && !e.getContents().isEmpty()) { + entry.put("Summary", ((SyndContent) e.getContents().get(0)).getValue()); + } else { + entry.put("Summary", e.getDescription() != null ? e.getDescription().getValue() : ""); + } + } + + if (e.getUpdatedDate() != null) { + entry.put("Date", e.getUpdatedDate().getTime()); + } else if (e.getPublishedDate() != null) { + entry.put("Date", e.getPublishedDate().getTime()); + } else { + entry.put("Date", 0); + } + + // if no author at feed level, use the first entry author + if (jsonAuthor == null) { + jsonAuthor = e.getAuthor(); + } + + JSONObject media = new JSONObject(); + MediaEntryModule mediaModule = (MediaEntryModule) e.getModule(MediaModule.URI); + if (mediaModule != null) { + if (mediaModule.getMediaContents().length > 0) { + JSONArray contents = new JSONArray(); + + for (MediaContent c : mediaModule.getMediaContents()) { + JSONObject content = new JSONObject(); + + if (c.getReference() instanceof UrlReference) { + content.put("URL", ((UrlReference) c.getReference()).getUrl().toString()); + } + + if (c.getType() != null) { + content.put("Type", c.getType()); + } + + if (c.getWidth() != null) { + content.put("Width", c.getWidth()); + } + + if (c.getHeight() != null) { + content.put("Height", c.getHeight()); + } + + contents.put(content); + } + + media.put("Contents", contents); + } + + if (mediaModule.getMetadata() != null) { + if (mediaModule.getMetadata().getThumbnail().length > 0) { + // "If multiple thumbnails are included, it is assumed that they are in order of importance" + // Only use the first thumbnail for simplicity's + // sake + + JSONObject thumbnail = new JSONObject(); + + Thumbnail t = mediaModule.getMetadata().getThumbnail()[0]; + thumbnail.put("URL", t.getUrl().toString()); + + if (t.getWidth() != null) { + thumbnail.put("Width", t.getWidth()); + } + + if (t.getHeight() != null) { + thumbnail.put("Height", t.getHeight()); + } + + media.put("Thumbnail", thumbnail); + } + } + } + + entry.put("Media", media); + + entries.put(entry); + } + + json.put("Author", (jsonAuthor != null) ? jsonAuthor : ""); + return json; + } catch (JSONException e) { + // This shouldn't ever happen. + throw new RuntimeException(e); + } catch (FeedException e) { + throw new GadgetException(GadgetException.Code.MALFORMED_XML_DOCUMENT, e, HttpResponse.SC_BAD_GATEWAY); + } catch (IllegalArgumentException e) { + throw new GadgetException(GadgetException.Code.MALFORMED_XML_DOCUMENT, e, HttpResponse.SC_BAD_GATEWAY); + } + } +} diff --git a/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpRequestHandler.java b/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpRequestHandler.java index f6a33ea7f..0c5c3860f 100644 --- a/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpRequestHandler.java +++ b/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpRequestHandler.java @@ -48,6 +48,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.inject.Inject; +import com.google.inject.Provider; /** * An alternate implementation of the Http proxy service using the standard API dispatcher for REST @@ -96,12 +97,15 @@ public class HttpRequestHandler { private final RequestPipeline requestPipeline; private final ResponseRewriterRegistry contentRewriterRegistry; + private final Provider feedProcessorProvider; @Inject public HttpRequestHandler(RequestPipeline requestPipeline, - ResponseRewriterRegistry contentRewriterRegistry) { + ResponseRewriterRegistry contentRewriterRegistry, + Provider feedProcessorProvider) { this.requestPipeline = requestPipeline; this.contentRewriterRegistry = contentRewriterRegistry; + this.feedProcessorProvider = feedProcessorProvider; } @@ -298,7 +302,7 @@ protected Object transformBody(HttpApiRequest request, HttpResponse results) /** Processes a feed (RSS or Atom) using FeedProcessor. */ protected Object processFeed(HttpApiRequest req, String responseBody) throws GadgetException { - return new FeedProcessor().process(req.href.toString(), responseBody, req.summarize, + return feedProcessorProvider.get().process(req.href.toString(), responseBody, req.summarize, req.entryCount); } diff --git a/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java b/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java index 153a6e42e..fb3bbc1bc 100644 --- a/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java +++ b/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java @@ -19,6 +19,7 @@ package org.apache.shindig.gadgets.servlet; import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Singleton; import org.apache.commons.lang.StringUtils; @@ -72,12 +73,15 @@ public class MakeRequestHandler { private final RequestPipeline requestPipeline; private final ResponseRewriterRegistry contentRewriterRegistry; + private final Provider feedProcessorProvider; @Inject public MakeRequestHandler(RequestPipeline requestPipeline, - ResponseRewriterRegistry contentRewriterRegistry) { + ResponseRewriterRegistry contentRewriterRegistry, + Provider feedProcessorProvider) { this.requestPipeline = requestPipeline; this.contentRewriterRegistry = contentRewriterRegistry; + this.feedProcessorProvider = feedProcessorProvider; } /** @@ -273,7 +277,7 @@ private String processFeed(String url, HttpServletRequest req, String xml) throw new GadgetException(GadgetException.Code.INVALID_PARAMETER, "numEntries paramater is not a number", HttpResponse.SC_BAD_REQUEST); } - return new FeedProcessor().process(url, xml, getSummaries, numEntries).toString(); + return feedProcessorProvider.get().process(url, xml, getSummaries, numEntries).toString(); } /** diff --git a/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java b/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorImplTest.java similarity index 98% rename from java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java rename to java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorImplTest.java index 9949be0bd..7aa9e8b8d 100644 --- a/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java +++ b/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorImplTest.java @@ -26,9 +26,9 @@ import org.junit.Test; /** - * Tests for FeedProcessor + * Tests for FeedProcessorImpl */ -public class FeedProcessorTest { +public class FeedProcessorImplTest { private final static String FEED_TITLE = "Example Feed"; private final static String FEED_AUTHOR = "John Doe"; @@ -162,10 +162,10 @@ public class FeedProcessorTest { private final static String BAD_XML = "broken xml !!!! & ><"; private final static String INVALID_XML = ""; - private final FeedProcessor processor; + private final FeedProcessorImpl processor; - public FeedProcessorTest() { - processor = new FeedProcessor(); + public FeedProcessorImplTest() { + processor = new FeedProcessorImpl(); } @Test diff --git a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpRequestHandlerTest.java b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpRequestHandlerTest.java index b52892580..c7861ae7a 100644 --- a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpRequestHandlerTest.java +++ b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpRequestHandlerTest.java @@ -32,6 +32,8 @@ import org.apache.shindig.common.testing.FakeGadgetToken; import org.apache.shindig.common.uri.Uri; import org.apache.shindig.gadgets.AuthType; +import org.apache.shindig.gadgets.FeedProcessor; +import org.apache.shindig.gadgets.FeedProcessorImpl; import org.apache.shindig.gadgets.http.HttpRequest; import org.apache.shindig.gadgets.http.HttpResponse; import org.apache.shindig.gadgets.http.HttpResponseBuilder; @@ -60,6 +62,7 @@ import com.google.common.collect.ImmutableSet; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.Provider; /** * Has coverage for all tests in MakeRequestHandlerTest and should be maintained in sync until @@ -82,6 +85,12 @@ public class HttpRequestHandlerTest extends EasyMockTestCase { private final Map emptyFormItems = Collections.emptyMap(); + private final Provider feedProcessorProvider = new Provider() { + public FeedProcessor get() { + return new FeedProcessorImpl(); + } + }; + @Before public void setUp() throws Exception { token = new FakeGadgetToken(); @@ -90,7 +99,7 @@ public void setUp() throws Exception { Injector injector = Guice.createInjector(); converter = new BeanJsonConverter(injector); - HttpRequestHandler handler = new HttpRequestHandler(pipeline, rewriterRegistry); + HttpRequestHandler handler = new HttpRequestHandler(pipeline, rewriterRegistry, feedProcessorProvider); registry = new DefaultHandlerRegistry(injector, converter, new HandlerExecutionListener.NoOpHandler()); registry.addHandlers(ImmutableSet.of(handler)); diff --git a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java index 2725dd040..b6f4f9aba 100644 --- a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java +++ b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestHandlerTest.java @@ -63,7 +63,7 @@ public class MakeRequestHandlerTest extends ServletTestFixture { private static final SecurityToken DUMMY_TOKEN = new FakeGadgetToken(); private final MakeRequestHandler handler - = new MakeRequestHandler(pipeline, rewriterRegistry); + = new MakeRequestHandler(pipeline, rewriterRegistry, feedProcessorProvider); private void expectGetAndReturnBody(String response) throws Exception { expectGetAndReturnBody(AuthType.NONE, response); diff --git a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestServletTest.java b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestServletTest.java index 7b11d9ce7..cac24d1ac 100644 --- a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestServletTest.java +++ b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/MakeRequestServletTest.java @@ -51,7 +51,7 @@ public class MakeRequestServletTest extends ServletTestFixture { = Collections.enumeration(Collections.emptyList()); private final MakeRequestServlet servlet = new MakeRequestServlet(); - private final MakeRequestHandler handler = new MakeRequestHandler(pipeline, null); + private final MakeRequestHandler handler = new MakeRequestHandler(pipeline, null, feedProcessorProvider); private final HttpRequest internalRequest = new HttpRequest(REQUEST_URL); private final HttpResponse internalResponse = new HttpResponse(RESPONSE_BODY); diff --git a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java index 066a102a0..469716352 100644 --- a/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java +++ b/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java @@ -20,6 +20,8 @@ import org.apache.shindig.common.EasyMockTestCase; import org.apache.shindig.common.servlet.HttpServletResponseRecorder; +import org.apache.shindig.gadgets.FeedProcessor; +import org.apache.shindig.gadgets.FeedProcessorImpl; import org.apache.shindig.gadgets.LockedDomainService; import org.apache.shindig.gadgets.http.RequestPipeline; import org.apache.shindig.gadgets.rewrite.CaptureRewriter; @@ -32,6 +34,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.google.inject.Provider; + /** * Contains everything needed for making servlet requests, plus a bunch of stuff that shouldn't be * here. @@ -47,4 +51,9 @@ public abstract class ServletTestFixture extends EasyMockTestCase { public final HttpServletResponse response = mock(HttpServletResponse.class); public final HttpServletResponseRecorder recorder = new HttpServletResponseRecorder(response); public final LockedDomainService lockedDomainService = mock(LockedDomainService.class); + public final Provider feedProcessorProvider = new Provider() { + public FeedProcessor get() { + return new FeedProcessorImpl(); + } + }; } From 6180545c62c541fa9e71030eccec003dc27d7906 Mon Sep 17 00:00:00 2001 From: billwolckenlmco Date: Wed, 20 Oct 2010 13:07:53 -0400 Subject: [PATCH 7/8] Update version to 2.0.1.2 --- assembly/pom.xml | 2 +- extras/pom.xml | 2 +- features/pom.xml | 2 +- java/common/pom.xml | 2 +- java/gadgets/pom.xml | 2 +- java/samples/pom.xml | 2 +- java/server/pom.xml | 2 +- java/social-api/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/assembly/pom.xml b/assembly/pom.xml index 9e3384036..376af8527 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 ../pom.xml diff --git a/extras/pom.xml b/extras/pom.xml index 8d99f9fc3..2b695c47e 100644 --- a/extras/pom.xml +++ b/extras/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 ../pom.xml diff --git a/features/pom.xml b/features/pom.xml index 5149f6030..16cba36be 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -23,7 +23,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 ../pom.xml diff --git a/java/common/pom.xml b/java/common/pom.xml index 6bbcc6e29..1317251c6 100644 --- a/java/common/pom.xml +++ b/java/common/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 ../../pom.xml diff --git a/java/gadgets/pom.xml b/java/gadgets/pom.xml index 5f7b29073..3aa15020e 100644 --- a/java/gadgets/pom.xml +++ b/java/gadgets/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 ../../pom.xml diff --git a/java/samples/pom.xml b/java/samples/pom.xml index d438a600f..c86bd351e 100644 --- a/java/samples/pom.xml +++ b/java/samples/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 ../../pom.xml diff --git a/java/server/pom.xml b/java/server/pom.xml index a0fe74c38..2fb29d7b8 100644 --- a/java/server/pom.xml +++ b/java/server/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 ../../pom.xml diff --git a/java/social-api/pom.xml b/java/social-api/pom.xml index 08d839568..6092d2b38 100644 --- a/java/social-api/pom.xml +++ b/java/social-api/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 ../../pom.xml diff --git a/pom.xml b/pom.xml index bdef6a23e..c5502b3bf 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ org.apache.shindig shindig-project - 2.0.1-SNAPSHOT + 2.0.1.2 pom Apache Shindig Project From 914156e84c62d5c210cca2718e80a2d780dd7cef Mon Sep 17 00:00:00 2001 From: Rob Keane Date: Wed, 20 Apr 2011 13:46:12 -0400 Subject: [PATCH 8/8] Removed NIX transport and added better handling for same domain RPC --- assembly/pom.xml | 2 +- extras/pom.xml | 2 +- features/pom.xml | 2 +- .../features/rpc/blank.transport.js | 48 +++ .../main/javascript/features/rpc/feature.xml | 4 +- .../javascript/features/rpc/nix.transport.js | 342 ------------------ .../src/main/javascript/features/rpc/rpc.js | 9 +- java/common/pom.xml | 2 +- java/gadgets/pom.xml | 2 +- java/samples/pom.xml | 2 +- java/server/pom.xml | 2 +- java/social-api/pom.xml | 2 +- pom.xml | 2 +- 13 files changed, 67 insertions(+), 354 deletions(-) create mode 100644 features/src/main/javascript/features/rpc/blank.transport.js delete mode 100644 features/src/main/javascript/features/rpc/nix.transport.js diff --git a/assembly/pom.xml b/assembly/pom.xml index 376af8527..89929770b 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1.2 + 2.0.1.3 ../pom.xml diff --git a/extras/pom.xml b/extras/pom.xml index 2b695c47e..ff03ea745 100644 --- a/extras/pom.xml +++ b/extras/pom.xml @@ -22,7 +22,7 @@ org.apache.shindig shindig-project - 2.0.1.2 + 2.0.1.3 ../pom.xml diff --git a/features/pom.xml b/features/pom.xml index 16cba36be..51ad9c31e 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -23,7 +23,7 @@ org.apache.shindig shindig-project - 2.0.1.2 + 2.0.1.3 ../pom.xml diff --git a/features/src/main/javascript/features/rpc/blank.transport.js b/features/src/main/javascript/features/rpc/blank.transport.js new file mode 100644 index 000000000..0433e0303 --- /dev/null +++ b/features/src/main/javascript/features/rpc/blank.transport.js @@ -0,0 +1,48 @@ +/* + * 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. + */ + +gadgets.rpctx = gadgets.rpctx || {}; + +if (!gadgets.rpctx.blank) { // make lib resilient to double-inclusion + +gadgets.rpctx.blank = function() { + return { + getCode: function() { + return 'blank'; + }, + + isParentVerifiable: function() { + return true; + }, + + init: function(processFn, readyFn) { + readyFn('..', true); // Immediately ready to send to parent. + return true; + }, + + setup: function(receiverId, token, forceSecure) { + return true; + }, + + call: function(targetId, from, rpc) { + // should never happen + } + }; +}(); + +} // !end of double-inclusion guard diff --git a/features/src/main/javascript/features/rpc/feature.xml b/features/src/main/javascript/features/rpc/feature.xml index a5f7fe77c..3a81151f1 100644 --- a/features/src/main/javascript/features/rpc/feature.xml +++ b/features/src/main/javascript/features/rpc/feature.xml @@ -36,7 +36,7 @@ useLegacyProtocol: Boolean