diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | nb-configuration.xml | 18 | ||||
-rw-r--r-- | nbactions.xml | 15 | ||||
-rw-r--r-- | pom.xml | 41 | ||||
-rw-r--r-- | src/main/java/com/jogamp/hungryharry/Config.java | 101 | ||||
-rw-r--r-- | src/main/java/com/jogamp/hungryharry/FeedAggregator.java | 187 | ||||
-rw-r--r-- | src/main/java/com/jogamp/hungryharry/config.xml | 41 |
7 files changed, 404 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/nb-configuration.xml b/nb-configuration.xml new file mode 100644 index 0000000..3486bc9 --- /dev/null +++ b/nb-configuration.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project-shared-configuration> + <!-- +This file contains additional configuration written by modules in the NetBeans IDE. +The configuration is intended to be shared among all the users of project and +therefore it is assumed to be part of version control checkout. +Without this configuration present, some functionality in the IDE may be limited or fail altogether. +--> + <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1"> + <!-- +Properties that influence various parts of the IDE, especially code formatting and the like. +You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up. +That way multiple projects can share the same settings (useful for formatting rules for example). +Any value defined here will override the pom.xml file value but is only applicable to the current project. +--> + <netbeans.compile.on.save>all</netbeans.compile.on.save> + </properties> +</project-shared-configuration> diff --git a/nbactions.xml b/nbactions.xml new file mode 100644 index 0000000..6d831cd --- /dev/null +++ b/nbactions.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<actions> + <action> + <actionName>run</actionName> + <goals> + <goal>process-classes</goal> + <goal>org.codehaus.mojo:exec-maven-plugin:1.1.1:exec</goal> + </goals> + <properties> + <exec.classpathScope>runtime</exec.classpathScope> + <exec.args>-classpath %classpath com.jogamp.hungryharry.FeedAggregator</exec.args> + <exec.executable>java</exec.executable> + </properties> + </action> + </actions> @@ -0,0 +1,41 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>com.jogamp</groupId> + <artifactId>HungryHarry</artifactId> + <packaging>jar</packaging> + <version>1.0-SNAPSHOT</version> + <name>HungryHarry</name> + <url>http://maven.apache.org</url> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.6</source> + <target>1.6</target> + <showDeprecation>true</showDeprecation> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.8.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>net.java.dev.rome</groupId> + <artifactId>rome</artifactId> + <version>1.0.0</version> + </dependency> + <dependency> + <groupId>net.java.dev.rome</groupId> + <artifactId>rome-fetcher</artifactId> + <version>1.0.0</version> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/com/jogamp/hungryharry/Config.java b/src/main/java/com/jogamp/hungryharry/Config.java new file mode 100644 index 0000000..9b69510 --- /dev/null +++ b/src/main/java/com/jogamp/hungryharry/Config.java @@ -0,0 +1,101 @@ +/* + * Created on Saturday, May 15 2010 17:07 + */ +package com.jogamp.hungryharry; + +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +/** + * Hungry Harrie's configuration. + * @author Michael Bien + */ +@XmlType(name = "") +@XmlRootElement(name = "config") +public class Config { + + @XmlElement(required = true) + public final List<Feed> feed; + + @XmlElement(required = true) + public final List<Template> template; + + @XmlElement(required = true) + public final Planet planet; + + public Config() { + feed = null; + template = null; + planet = null; + } + + @XmlType + public static class Feed { + + @XmlAttribute + public final String name; + @XmlAttribute + public final String url; + + public Feed() { + name = null; + url = null; + } + } + + @XmlType + public static class Template { + + @XmlAttribute + public final String keyword; + + @XmlAttribute(name="idpattern") + public final String idpattern; + + @XmlValue + public final String text; + + public Template() { + keyword = null; + text = null; + idpattern = null; + } + } + + @XmlType + public static class Planet { + + @XmlAttribute + public final String title; + + @XmlAttribute + public final String description; + + @XmlAttribute + public final String author; + + @XmlAttribute + public final String link; + + @XmlElement(name="feed") + public final List<String> feeds; + + @XmlElement(name="template") + public final String templatePath; + + public Planet() { + title = null; + description = null; + author = null; + link = null; + feeds = null; + templatePath = null; + } + } +} diff --git a/src/main/java/com/jogamp/hungryharry/FeedAggregator.java b/src/main/java/com/jogamp/hungryharry/FeedAggregator.java new file mode 100644 index 0000000..8bfc4eb --- /dev/null +++ b/src/main/java/com/jogamp/hungryharry/FeedAggregator.java @@ -0,0 +1,187 @@ +/* + * Created on Saturday, May 14 2010 17:08 + */ +package com.jogamp.hungryharry; + +import com.jogamp.hungryharry.Config.Planet; +import com.sun.syndication.io.SyndFeedOutput; +import java.io.PrintWriter; +import com.sun.syndication.feed.synd.SyndEntry; +import com.sun.syndication.fetcher.FetcherException; +import com.sun.syndication.io.FeedException; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import com.sun.syndication.feed.synd.SyndFeedImpl; +import com.sun.syndication.feed.synd.SyndFeed; +import com.sun.syndication.fetcher.FeedFetcher; +import com.sun.syndication.fetcher.impl.FeedFetcherCache; +import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache; +import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.util.Comparator; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import static java.util.Collections.*; +import static java.util.logging.Level.*; +import static java.io.File.*; + +/** + * Always hungry, always. + * + * @author Michael Bien + * + */ +public class FeedAggregator { + + private static final Logger LOG = Logger.getLogger(FeedAggregator.class.getName()); + + + private void aggregate() throws MalformedURLException { + + Config config = null; + try { + Unmarshaller unmarshaller = JAXBContext.newInstance(Config.class).createUnmarshaller(); + Object obj = unmarshaller.unmarshal(getClass().getResourceAsStream("config.xml")); + config = (Config) obj; + } catch (JAXBException ex) { + throw new RuntimeException("can not read configuration", ex); + } + + + List<Config.Feed> feeds = config.feed; + + List<URL> urls = new ArrayList<URL>(); + for (Config.Feed feed : feeds) { + urls.add(new URL(feed.url)); + } + + + List<SyndEntry> entries = new ArrayList<SyndEntry>(); + + FeedFetcherCache feedInfoCache = HashMapFeedInfoCache.getInstance(); + FeedFetcher feedFetcher = new HttpURLFeedFetcher(feedInfoCache); + + for (int i = 0; i < urls.size(); i++) { + try { + SyndFeed inFeed = feedFetcher.retrieveFeed(urls.get(i)); + entries.addAll(inFeed.getEntries()); + } catch (IOException ex) { + LOG.log(WARNING, "skipping feed", ex); + } catch (FetcherException ex) { + LOG.log(WARNING, "skipping feed", ex); + } catch (FeedException ex) { + LOG.log(WARNING, "skipping feed", ex); + } + } + + sort(entries, new Comparator<SyndEntry>() { + @Override + public int compare(SyndEntry o1, SyndEntry o2) { + return o2.getPublishedDate().compareTo(o1.getPublishedDate()); + } + }); + + Planet planet = config.planet; + String path = cutoffTail(planet.templatePath, separatorChar); + + for (String feedType : planet.feeds) { + + try { + SyndFeed feed = new SyndFeedImpl(); + feed.setFeedType(feedType); + + feed.setTitle(planet.title); + feed.setDescription(planet.description); + feed.setAuthor(planet.author); + feed.setLink(planet.link); + feed.setEntries(entries); + + SyndFeedOutput output = new SyndFeedOutput(); + + output.output(feed, new File(path+separatorChar+feedType+".xml")); + + } catch (IOException ex) { + LOG.log(SEVERE, null, ex); + } catch (FeedException ex) { + LOG.log(SEVERE, null, ex); + } + } + + StringBuilder content = new StringBuilder(); + int max = 20; + int n = 0; + for (SyndEntry entry : entries) { + if(n++>max) { + break; + } + String link = entry.getLink(); + for (Config.Template template : config.template) { + if(link.contains(template.keyword)) { + Pattern pattern = Pattern.compile(template.idpattern); + Matcher matcher = pattern.matcher(link); + matcher.find(); + content.append(template.text.replaceAll("#id#", matcher.group(1))); + break; + } + } + + } + + try { + StringBuilder template = readFileAsString(planet.templatePath); + + replace(template, "@atom@", planet.link); + replace(template, "@rss@", planet.link); + replace(template, "@content@", content.toString()); + + FileOutputStream fos = new FileOutputStream(new File(path+separator+"planet.html")); + fos.write(template.toString().getBytes()); + + } catch (IOException ex) { + LOG.log(SEVERE, null, ex); + } + } + + private String cutoffTail(String text, char cut) { + return text.substring(0, text.lastIndexOf(cut)); + } + + private StringBuilder replace(StringBuilder sb, String token, String replacement) { + int start = sb.indexOf(token); + sb.replace(start, start+token.length(), replacement); + return sb; + } + + private static StringBuilder readFileAsString(String filePath) throws java.io.IOException{ + StringBuilder fileData = new StringBuilder(1000); + BufferedReader reader = new BufferedReader(new FileReader(filePath)); + char[] buf = new char[1024]; + int numRead=0; + while((numRead=reader.read(buf)) != -1){ + String readData = String.valueOf(buf, 0, numRead); + fileData.append(readData); + buf = new char[1024]; + } + reader.close(); + return fileData; + } + + + + public static void main(String[] args) throws MalformedURLException { + new FeedAggregator().aggregate(); + } + +} diff --git a/src/main/java/com/jogamp/hungryharry/config.xml b/src/main/java/com/jogamp/hungryharry/config.xml new file mode 100644 index 0000000..2fddf55 --- /dev/null +++ b/src/main/java/com/jogamp/hungryharry/config.xml @@ -0,0 +1,41 @@ + +<config> + + <planet title="JogAmp Streams" + description="JogAmp Aggregated Feeds" + author="Hungry Harry" + link="http://jogamp.org/stream"> + <feed>atom_0.3</feed> + <feed>rss_2.0</feed> + <template>/home/mbien/streams/planet-template.html</template> + </planet> + + <feed name="vimeo" url="http://vimeo.com/tag:jogl/rss"/> + <feed name="demoscenepassivist" url="http://gdata.youtube.com/feeds/base/users/DemoscenePassivist/uploads?alt=rss&v=2&orderby=published&client=ytapi-youtube-profile"/> + + <template keyword="vimeo" idpattern="http://vimeo.com/([0-9]+)"> +<![CDATA[ + <object width="400" height="320"> + <param name="allowfullscreen" value="true" /> + <param name="allowscriptaccess" value="always" /> + <param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=#id#&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /> + <embed src="http://vimeo.com/moogaloop.swf?clip_id=#id#&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" + type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="320"> + </embed> + </object> +]]> + </template> + <template keyword="youtube" idpattern="http://www.youtube.com/watch\?v=([^&]+)"> +<![CDATA[ + <object width="480" height="385"> + <param name="movie" value="http://www.youtube.com/v/#id#&hl=en_US&fs=1&rel=0&color1=0x2b405b&color2=0x6b8ab6&hd=1"/> + <param name="allowFullScreen" value="true"/> + <param name="allowscriptaccess" value="always"/> + <embed src="http://www.youtube.com/v/#id#&hl=en_US&fs=1&rel=0&color1=0x2b405b&color2=0x6b8ab6&hd=1" + type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"> + </embed> + </object> +]]> + </template> + +</config> |