1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
/*
* 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 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 freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.Comparator;
import java.util.HashMap;
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 (Planet.PlanetFeed planetFeed : planet.feeds) {
try {
SyndFeed feed = new SyndFeedImpl();
feed.setFeedType(planetFeed.type);
feed.setTitle(planet.title);
feed.setDescription(planet.description);
feed.setAuthor(planet.author);
feed.setLink(planet.link+separatorChar+planetFeed.getFileName());
feed.setEntries(entries);
SyndFeedOutput output = new SyndFeedOutput();
output.output(feed, new File(path+separatorChar+planetFeed.getFileName()));
} catch (IOException ex) {
LOG.log(SEVERE, null, ex);
} catch (FeedException ex) {
LOG.log(SEVERE, null, ex);
}
}
StringBuilder content = new StringBuilder();
int max = 10;
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;
}
}
}
HashMap<String, Object> root = new HashMap<String, Object>();
root.put("content", content.toString());
root.put("planet", planet);
root.put("feeds", planet.feeds);
try {
Configuration cfg = new Configuration();
// Specify the data source where the template files come from.
// Here I set a file directory for it:
cfg.setDirectoryForTemplateLoading(new File("/home/mbien/streams"));
// Specify how templates will see the data-model. This is an advanced topic...
// but just use this:
cfg.setObjectWrapper(new DefaultObjectWrapper());
Template temp = cfg.getTemplate("planet-template.html");
Writer writer = new FileWriter(new File(path+separator+"planet.html"));
temp.process(root, writer);
writer.close();
} catch (IOException ex) {
LOG.log(SEVERE, null, ex);
} catch (TemplateException 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;
}
public static void main(String[] args) throws MalformedURLException {
new FeedAggregator().aggregate();
}
}
|