You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by li...@apache.org on 2010/05/06 16:25:16 UTC
svn commit: r941753 - in /shindig/trunk: java/gadgets/pom.xml
java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java
java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java
pom.xml
Author: lindner
Date: Thu May 6 14:25:15 2010
New Revision: 941753
URL: http://svn.apache.org/viewvc?rev=941753&view=rev
Log:
Patch from Mat Mannion | Shindig Feed Processor: Parse MediaRSS items into optional Media element
Modified:
shindig/trunk/java/gadgets/pom.xml
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java
shindig/trunk/pom.xml
Modified: shindig/trunk/java/gadgets/pom.xml
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/pom.xml?rev=941753&r1=941752&r2=941753&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/pom.xml (original)
+++ shindig/trunk/java/gadgets/pom.xml Thu May 6 14:25:15 2010
@@ -162,6 +162,10 @@
<artifactId>rome</artifactId>
</dependency>
<dependency>
+ <groupId>rome</groupId>
+ <artifactId>modules</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
</dependency>
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java?rev=941753&r1=941752&r2=941753&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/FeedProcessor.java Thu May 6 14:25:15 2010
@@ -18,21 +18,26 @@
*/
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.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;
-import java.io.StringReader;
-import java.util.List;
-
/**
* Processes RSS & Atom Feeds and converts them into JSON output.
*/
@@ -40,16 +45,20 @@ public class 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.
+ *
+ * @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 {
+ 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();
@@ -84,11 +93,9 @@ public class FeedProcessor {
entry.put("Link", e.getLink());
if (getSummaries) {
if (e.getContents() != null && !e.getContents().isEmpty()) {
- entry.put("Summary",
- ((SyndContent)e.getContents().get(0)).getValue());
+ entry.put("Summary", ((SyndContent) e.getContents().get(0)).getValue());
} else {
- entry.put("Summary",
- e.getDescription() != null ? e.getDescription().getValue() : "");
+ entry.put("Summary", e.getDescription() != null ? e.getDescription().getValue() : "");
}
}
@@ -105,6 +112,63 @@ public class FeedProcessor {
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);
}
@@ -114,11 +178,9 @@ public class FeedProcessor {
// 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);
+ 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);
+ throw new GadgetException(GadgetException.Code.MALFORMED_XML_DOCUMENT, e, HttpResponse.SC_BAD_GATEWAY);
}
}
}
Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java?rev=941753&r1=941752&r2=941753&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/FeedProcessorTest.java Thu May 6 14:25:15 2010
@@ -61,6 +61,43 @@ public class FeedProcessorTest {
"<description>" + FEED_ENTRY_SUMMARY + "</description>" +
"</item>" +
"</channel></rss>";
+ private final static String MEDIA_CONTENT_URL1 = "http://example.com/img1.jpg";
+ private final static String MEDIA_CONTENT_URL2 = "http://example.com/img2.jpg";
+ private final static String MEDIA_CONTENT_URL3 = "http://example.com/img3.jpg";
+ private final static String MEDIA_CONTENT_TYPE = "image/jpeg";
+ private final static int MEDIA_CONTENT_WIDTH = 800;
+ private final static int MEDIA_CONTENT_HEIGHT = 600;
+ private final static String MEDIA_THUMB_URL = "http://exmaple.com/thumb.jpg";
+ private final static int MEDIA_THUMB_WIDTH = 75;
+ private final static int MEDIA_THUMB_HEIGHT = 50;
+ private final static String DATA_RSS_WITH_MEDIARSS =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
+ "<rss version=\"2.0\" xmlns:media=\"http://search.yahoo.com/mrss/\"><channel>" +
+ "<title>" + FEED_TITLE + "</title>" +
+ "<link>http://example.org/</link>" +
+ "<description>Example RSS Feed</description>" +
+ "<pubDate>Sun, 19 May 2002 15:21:36 GMT</pubDate>" +
+ "<item>" +
+ "<title>" + FEED_ENTRY_TITLE + "</title>" +
+ "<link>" + FEED_ENTRY_LINK + "</link>" +
+ "<guid>" + FEED_ENTRY_LINK + "#item1" + "</guid>" +
+ "<pubDate>" + DATE_RSS + "</pubDate>" +
+ "<description>" + FEED_ENTRY_SUMMARY + "</description>" +
+ "<author>" + FEED_AUTHOR_EMAIL + "</author>" +
+ "<media:content url=\"" + MEDIA_CONTENT_URL1 + "\" type=\"" + MEDIA_CONTENT_TYPE + "\" isDefault=\"false\" expression=\"sample\" width=\"" + MEDIA_CONTENT_WIDTH + "\" height=\"" + MEDIA_CONTENT_HEIGHT + "\" />" +
+ "<media:content url=\"" + MEDIA_CONTENT_URL2 + "\" type=\"" + MEDIA_CONTENT_TYPE + "\" isDefault=\"false\" expression=\"sample\" width=\"" + MEDIA_CONTENT_WIDTH + "\" height=\"" + MEDIA_CONTENT_HEIGHT + "\" />" +
+ "<media:content url=\"" + MEDIA_CONTENT_URL3 + "\" type=\"" + MEDIA_CONTENT_TYPE + "\" isDefault=\"false\" expression=\"sample\" width=\"" + MEDIA_CONTENT_WIDTH + "\" height=\"" + MEDIA_CONTENT_HEIGHT + "\" />" +
+ "<media:thumbnail url=\"" + MEDIA_THUMB_URL + "\" width=\"" + MEDIA_THUMB_WIDTH + "\" height=\"" + MEDIA_THUMB_HEIGHT + "\" />" +
+ "</item>" +
+ "<item>" +
+ "<title>" + FEED_ENTRY_TITLE + "</title>" +
+ "<link>" + FEED_ENTRY_LINK + "</link>" +
+ "<guid>" + FEED_ENTRY_LINK + "#item1" + "</guid>" +
+ "<description>" + FEED_ENTRY_SUMMARY + "</description>" +
+ "<media:thumbnail url=\"" + MEDIA_THUMB_URL + "\" />" +
+ "</item>" +
+ "</channel></rss>";
+
private final static String URL_ATOM = "http://www.example.com/feed.atom";
private final static String DATE_ATOM = "2008-06-06T22:20:00Z";
private final static String DATA_ATOM =
@@ -85,6 +122,33 @@ public class FeedProcessorTest {
"<summary>" + FEED_ENTRY_SUMMARY + "</summary>" +
"</entry>" +
"</feed>";
+ private final static String DATA_ATOM_WITH_MEDIARSS =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
+ "<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:media=\"http://search.yahoo.com/mrss/\">" +
+ "<title>" + FEED_TITLE + "</title>" +
+ "<link href=\"http://example.org/\"/>" +
+ "<updated>2003-12-13T18:30:02Z</updated>" +
+ "<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>" +
+ "<author><name>" + FEED_AUTHOR + "</name></author>" +
+ "<entry>" +
+ "<title>" + FEED_ENTRY_TITLE + "</title>" +
+ "<link href=\"" + FEED_ENTRY_LINK + "\"/>" +
+ "<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>" +
+ "<updated>" + DATE_ATOM + "</updated>" +
+ "<summary>" + FEED_ENTRY_SUMMARY + "</summary>" +
+ "<media:content url=\"" + MEDIA_CONTENT_URL1 + "\" type=\"" + MEDIA_CONTENT_TYPE + "\" isDefault=\"false\" expression=\"sample\" width=\"" + MEDIA_CONTENT_WIDTH + "\" height=\"" + MEDIA_CONTENT_HEIGHT + "\" />" +
+ "<media:content url=\"" + MEDIA_CONTENT_URL2 + "\" type=\"" + MEDIA_CONTENT_TYPE + "\" isDefault=\"false\" expression=\"sample\" width=\"" + MEDIA_CONTENT_WIDTH + "\" height=\"" + MEDIA_CONTENT_HEIGHT + "\" />" +
+ "<media:content url=\"" + MEDIA_CONTENT_URL3 + "\" type=\"" + MEDIA_CONTENT_TYPE + "\" isDefault=\"false\" expression=\"sample\" width=\"" + MEDIA_CONTENT_WIDTH + "\" height=\"" + MEDIA_CONTENT_HEIGHT + "\" />" +
+ "<media:thumbnail url=\"" + MEDIA_THUMB_URL + "\" width=\"" + MEDIA_THUMB_WIDTH + "\" height=\"" + MEDIA_THUMB_HEIGHT + "\" />" +
+ "</entry>" +
+ "<entry>" +
+ "<title>" + FEED_ENTRY_TITLE + "</title>" +
+ "<link href=\"" + FEED_ENTRY_LINK + "\"/>" +
+ "<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da3443fa6a</id>" +
+ "<summary>" + FEED_ENTRY_SUMMARY + "</summary>" +
+ "<media:thumbnail url=\"" + MEDIA_THUMB_URL + "\" />" +
+ "</entry>" +
+ "</feed>";
private final static String BAD_XML = "broken xml !!!! & ><";
private final static String INVALID_XML = "<data><foo/></data>";
@@ -134,6 +198,52 @@ public class FeedProcessorTest {
assertNull("Summary should not be returned when getSummaries is false",
entry.optString("Summary", null));
}
+
+ @Test
+ public void parseMediaRss() throws Exception {
+ JSONObject feed = processor.process(URL_RSS, DATA_RSS_WITH_MEDIARSS, true, 1);
+
+ assertEquals(URL_RSS, feed.getString("URL"));
+ assertEquals(FEED_TITLE, feed.getString("Title"));
+ assertEquals(FEED_AUTHOR_EMAIL, feed.getString("Author"));
+
+ JSONArray entryArray = feed.getJSONArray("Entry");
+ JSONObject entry = entryArray.getJSONObject(0);
+
+ assertEquals(1, entryArray.length());
+ assertEquals(FEED_ENTRY_TITLE, entry.getString("Title"));
+ assertEquals(FEED_ENTRY_LINK, entry.getString("Link"));
+ assertEquals(FEED_ENTRY_SUMMARY, entry.getString("Summary"));
+
+ // Three lots of content, each with a width/height and type
+ JSONObject media = entry.getJSONObject("Media");
+ JSONArray contents = media.getJSONArray("Contents");
+
+ assertEquals(3, contents.length());
+
+ JSONObject contents1 = contents.getJSONObject(0);
+ assertEquals(MEDIA_CONTENT_URL1, contents1.getString("URL"));
+ assertEquals(MEDIA_CONTENT_TYPE, contents1.getString("Type"));
+ assertEquals(MEDIA_CONTENT_WIDTH, contents1.getInt("Width"));
+ assertEquals(MEDIA_CONTENT_HEIGHT, contents1.getInt("Height"));
+
+ JSONObject contents2 = contents.getJSONObject(1);
+ assertEquals(MEDIA_CONTENT_URL2, contents2.getString("URL"));
+ assertEquals(MEDIA_CONTENT_TYPE, contents2.getString("Type"));
+ assertEquals(MEDIA_CONTENT_WIDTH, contents2.getInt("Width"));
+ assertEquals(MEDIA_CONTENT_HEIGHT, contents2.getInt("Height"));
+
+ JSONObject contents3 = contents.getJSONObject(2);
+ assertEquals(MEDIA_CONTENT_URL3, contents3.getString("URL"));
+ assertEquals(MEDIA_CONTENT_TYPE, contents3.getString("Type"));
+ assertEquals(MEDIA_CONTENT_WIDTH, contents3.getInt("Width"));
+ assertEquals(MEDIA_CONTENT_HEIGHT, contents3.getInt("Height"));
+
+ JSONObject thumbnail = media.getJSONObject("Thumbnail");
+ assertEquals(MEDIA_THUMB_URL, thumbnail.getString("URL"));
+ assertEquals(MEDIA_THUMB_WIDTH, thumbnail.getInt("Width"));
+ assertEquals(MEDIA_THUMB_HEIGHT, thumbnail.getInt("Height"));
+ }
@Test
public void parseAtom() throws Exception {
@@ -175,6 +285,52 @@ public class FeedProcessorTest {
assertNull("Summary should not be returned when getSummaries is false",
entry.optString("Summary", null));
}
+
+ @Test
+ public void parseMediaAtom() throws Exception {
+ JSONObject feed = processor.process(URL_ATOM, DATA_ATOM_WITH_MEDIARSS, true, 1);
+
+ assertEquals(URL_ATOM, feed.getString("URL"));
+ assertEquals(FEED_TITLE, feed.getString("Title"));
+ assertEquals(FEED_AUTHOR, feed.getString("Author"));
+
+ JSONArray entryArray = feed.getJSONArray("Entry");
+ JSONObject entry = entryArray.getJSONObject(0);
+
+ assertEquals(1, entryArray.length());
+ assertEquals(FEED_ENTRY_TITLE, entry.getString("Title"));
+ assertEquals(FEED_ENTRY_LINK, entry.getString("Link"));
+ assertEquals(FEED_ENTRY_SUMMARY, entry.getString("Summary"));
+
+ // Three lots of content, each with a width/height and type
+ JSONObject media = entry.getJSONObject("Media");
+ JSONArray contents = media.getJSONArray("Contents");
+
+ assertEquals(3, contents.length());
+
+ JSONObject contents1 = contents.getJSONObject(0);
+ assertEquals(MEDIA_CONTENT_URL1, contents1.getString("URL"));
+ assertEquals(MEDIA_CONTENT_TYPE, contents1.getString("Type"));
+ assertEquals(MEDIA_CONTENT_WIDTH, contents1.getInt("Width"));
+ assertEquals(MEDIA_CONTENT_HEIGHT, contents1.getInt("Height"));
+
+ JSONObject contents2 = contents.getJSONObject(1);
+ assertEquals(MEDIA_CONTENT_URL2, contents2.getString("URL"));
+ assertEquals(MEDIA_CONTENT_TYPE, contents2.getString("Type"));
+ assertEquals(MEDIA_CONTENT_WIDTH, contents2.getInt("Width"));
+ assertEquals(MEDIA_CONTENT_HEIGHT, contents2.getInt("Height"));
+
+ JSONObject contents3 = contents.getJSONObject(2);
+ assertEquals(MEDIA_CONTENT_URL3, contents3.getString("URL"));
+ assertEquals(MEDIA_CONTENT_TYPE, contents3.getString("Type"));
+ assertEquals(MEDIA_CONTENT_WIDTH, contents3.getInt("Width"));
+ assertEquals(MEDIA_CONTENT_HEIGHT, contents3.getInt("Height"));
+
+ JSONObject thumbnail = media.getJSONObject("Thumbnail");
+ assertEquals(MEDIA_THUMB_URL, thumbnail.getString("URL"));
+ assertEquals(MEDIA_THUMB_WIDTH, thumbnail.getInt("Width"));
+ assertEquals(MEDIA_THUMB_HEIGHT, thumbnail.getInt("Height"));
+ }
@Test(expected=GadgetException.class)
public void parseBadXml() throws GadgetException {
Modified: shindig/trunk/pom.xml
URL: http://svn.apache.org/viewvc/shindig/trunk/pom.xml?rev=941753&r1=941752&r2=941753&view=diff
==============================================================================
--- shindig/trunk/pom.xml (original)
+++ shindig/trunk/pom.xml Thu May 6 14:25:15 2010
@@ -1449,6 +1449,11 @@
<version>1.0</version>
</dependency>
<dependency>
+ <groupId>rome</groupId>
+ <artifactId>modules</artifactId>
+ <version>0.3.2</version>
+ </dependency>
+ <dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>3.8</version>