package pnews;
-public enum Category {
- ACTUALITE("Les actualités à la une"),
- FRANCE("France"),
- SPORT("Sport"),
- EUROPE("Europe"),
- MONDE("Monde"),
- ECONOMIE("Economie"),
- ESSONNE("Essonne"),
- TECHNOLOGIE("Technologie"),
- PEOPLE("People");
-
- private final String title;
+public class Category {
+ private final String name;
+
+ public Category(String name) {
+ this.name = name;
+ }
- private Category(String title) {
- this.title = title;
+ public String getTitle() {
+ return name;
}
- public String getId() {
- return name();
+ public String getURL() {
+ return "/fr/" + name.toLowerCase();
}
- public String getTitle() {
- return title;
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return getName();
}
}
import pnews.Article;
import pnews.Category;
+import pnews.Feed;
public class ArticleProvider {
- public final static ArticleProvider singleton = new ArticleProvider();
private static final Logger LOG = Logger.getLogger(ArticleProvider.class.getName());
private final Map<Category, List<Article>> articlesByCategory = new HashMap<>();
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
+ private final Config config;
- private ArticleProvider() {
- for (Category cat:Category.values())
+ public ArticleProvider(Config config) {
+ this.config = config;
+ for (Category cat: config.getCategories())
scheduler.scheduleAtFixedRate(new Refresher(cat), 2, 600, TimeUnit.SECONDS);
}
return new SyndFeedInput().build(r);
}
-
-
private List<Article> getArticlesForUpdate(Category cat) {
List<Article> result;
feedTitle = feed.getTitle().trim();
- LOG.info("addArticles " + cat.getId() + " " + feedTitle + " number of articles: " + feed.getEntries().size());
+ LOG.info("addArticles " + cat.getName() + " " + feedTitle + " number of articles: " + feed.getEntries().size());
for (SyndEntry entry: feed.getEntries()) {
String link = entry.getLink().trim();
}
}
- LOG.info("addArticles done " + cat.getId());
+ LOG.info("addArticles done " + cat.getName());
}
private void retrieveArticles(Category cat) throws IllegalArgumentException, MalformedURLException, FeedException, IOException {
- String[] feeds;
+ List<Feed> feeds;
- feeds = Config.getFeedsByCategory().get(cat);
+ feeds = config.getFeedsByCategory().get(cat);
if (feeds != null)
- for (String str: feeds)
+ for (Feed f: feeds)
try {
- addArticles(cat, getSyndFeed(str));
+ addArticles(cat, getSyndFeed(f.getURL()));
} catch (Throwable e) {
LOG.log(Level.SEVERE,
- "retrieveArticles failure " + cat.getId() + " " + str,
+ "retrieveArticles failure " + cat.getName() + " " + f.toString(),
e);
}
else
@Override
public void run() {
- LOG.info("refresher "+ category.getId());
+ LOG.info("refresher "+ category.getName());
try {
retrieveArticles(category);
LOG.log(Level.SEVERE, "refresher failure", e);
}
- LOG.info("refresher "+ category.getId() + " done");
+ LOG.info("refresher "+ category.getName() + " done");
}
}
}
import pnews.Feed;
public class Config {
- public static Feed[] getFeeds() {
+ private Feed[] feeds;
+ private Category[] categories;
+
+ public void loadConfig() {
Reader r;
- List<Feed> feeds;
- JsonObject jfeeds;
+ JsonObject jfeeds, jroot;
+ List<Feed> feedList;
+ Map<String, Category> cats;
r = null;
try {
r = new InputStreamReader(Config.class.getClassLoader().getResourceAsStream("feeds.json"));
- jfeeds = Json.createReader(r).readObject();
+ jroot = Json.createReader(r).readObject();
} finally {
if (r != null)
try { r.close(); } catch (IOException e) { };
}
- feeds = new ArrayList<Feed>(jfeeds.size());
+ jfeeds = jroot.getJsonObject("feeds");
+
+ feedList = new ArrayList<Feed>(jfeeds.size());
+ cats = new HashMap<>();
jfeeds.forEach((k, v)-> {
JsonObject jf;
+ String str;
+ Category cat;
JsonArray jcategories;
jf = (JsonObject)v;
jcategories = jf.getJsonArray("categories");
- feeds.add(new Feed(k, Category.valueOf(jcategories.getString(0))));
- });
+ str = jcategories.getString(0);
+
+ cat = cats.get(str);
+ if (cat == null) {
+ cat = new Category(str);
+ cats.put(str, cat);
+ }
- return feeds.toArray(new Feed[] {});
+ feedList.add(new Feed(k, cat));
+ });
+
+ feeds = feedList.toArray(new Feed[0]);
+ categories = cats.values().toArray(new Category[0]);
+ }
+
+ public Feed[] getFeeds() {
+ return feeds;
}
- public static Map<Category, String[]> getFeedsByCategory() {
- Map<Category, String[]> result;
+ public Map<Category, List<Feed>> getFeedsByCategory() {
+ Map<Category, List<Feed>> result;
+ Feed[] feeds;
+ List<Feed> catFeeds;
+ Category cat;
result = new HashMap<>();
- result.put(Category.ACTUALITE,
- new String[] {
- "http://www.europe1.fr/var/export/rss/europe1/actus.xml",
- "http://www.francetvinfo.fr/titres.rss",
- "http://www.rfi.fr/general/rss",
- "http://www.cnews.fr/rss/une",
- "http://www.ladepeche.fr/rss/a-la-une.rss",
- "https://www.franceinter.fr/rss/a-la-une.xml",
- "https://www.francebleu.fr/rss/a-la-une.xml",
- "http://www.bfmtv.com/rss/info/flux-rss/flux-toutes-les-actualites/"
- });
-
- result.put(Category.SPORT,
- new String[] { "http://www.europe1.fr/var/export/rss/europe1/sport.xml",
- "http://www.sportune.fr/feed",
- "http://www.france24.com/fr/sports/rss" });
-
- result.put(Category.FRANCE,
- new String[] { "http://www.france24.com/fr/france/rss",
- "http://www.francetvinfo.fr/france.rss",
- "http://www.rfi.fr/france/rss"});
-
- result.put(Category.EUROPE,
- new String[] { "http://www.france24.com/fr/europe/rss" });
-
- result.put(Category.MONDE,
- new String[] { "http://www.europe1.fr/var/export/rss/europe1/international.xml",
- "http://www.france24.com/fr/actualites/rss" });
-
-
- result.put(Category.ECONOMIE,
- new String[] { "http://www.france24.com/fr/economie/rss",
- "http://www.europe1.fr/var/export/rss/europe1/economie.xml",
- "http://www.rfi.fr/economie/rss" });
-
- result.put(Category.ESSONNE,
- new String[] { "http://www.tourisme-essonne.com/rss/actus/",
- "http://www.ville-palaiseau.fr/rss/actualites.htm" });
-
- result.put(Category.PEOPLE,
- new String[] { "http://www.premiere.fr/rss/actu-live",
- "http://www.purepeople.com/rss/news_t0.xml"
- });
+ feeds = getFeeds();
+ for (Feed f: feeds) {
+ cat = f.getCategory();
- result.put(Category.TECHNOLOGIE,
- new String[] { "http://www.generation-nt.com/export/rss.xml",
- "http://www.europe1.fr/var/export/rss/europe1/sciences.xml",
- "http://feeds.feedburner.com/lesnumeriques/news",
- "http://www.zdnet.fr/feeds/rss/actualites/",
- "http://www.frandroid.com/feed",
- "http://www.silicon.fr/feed",
- "http://www.fredzone.org/feed",
- "http://www.futura-sciences.com/rss/actualites.xml",
- "https://www-03.ibm.com/press/fr/fr/rssfeed.wss?keyword=null&maxFeed=&feedType=RSS&topic=all"});
+ catFeeds = result.get(cat);
+ if (catFeeds == null) {
+ catFeeds = new ArrayList<Feed>();
+ result.put(cat, catFeeds);
+ }
+ catFeeds.add(f);
+ }
return result;
}
+ public Category[] getCategories() {
+ return categories;
+ }
+
+ public Category getDefaultCategory() {
+ return categories[0];
+ }
+
public static void main(String[] args) {
- Feed[] feeds;
+ Config cfg;
+ Feed[] feeds;
+ Category[] cats;
+
+ cfg = new Config();
+ cfg.loadConfig();
- feeds = getFeeds();
+ cats = cfg.getCategories();
+ for (Category cat: cats)
+ System.out.println(cat);
+
+ feeds = cfg.getFeeds();
System.out.println("Number of feeds: " + feeds.length);
for (Feed f: feeds)
buf.append("<div class='article-content'>\n");
buf.append("<div class='article-title'>\n");
- appendA(buf, a.title, "redirect?url=" + URLEncoder.encode(a.link, "UTF-8"), null);
+ appendA(buf, a.title, "/redirect?url=" + URLEncoder.encode(a.link, "UTF-8"), null);
buf.append("</div>\n");
buf.append("<div class='article-info'>" + a.website + " - " + a.publicationDate + "</div>");
buf.append("</div>\n");
}
- private static void appendMenu(StringBuffer buf, Category catActive) {
+ private static void appendMenu(StringBuffer buf, Category catActive, Category[] cats) {
String cl;
buf.append("<nav>\n");
buf.append("<ul>\n");
- for (Category cat: Category.values()) {
+ for (Category cat: cats) {
buf.append("<li>");
if (cat.equals(catActive))
else
cl = null;
- appendA(buf, cat.getId(), cat.getId(), cl);
+ appendA(buf, cat.getName(), cat.getURL(), cl);
buf.append("</li>");
}
buf.append("</nav>\n");
}
- public static String toHTML(List<Article> articles, Category catActive) {
+ public static String toHTML(List<Article> articles, Category catActive, Category[] cats) {
StringBuffer buf;
int i;
buf.append("<html lang='fr'>\n");
buf.append("<head>\n");
buf.append("<meta charset=\"UTF-8\">\n");
- buf.append("<link rel='stylesheet' href='style.css' />\n");
+ buf.append("<link rel='stylesheet' href='/style.css' />\n");
buf.append("<title>");
buf.append(catActive.getTitle());
buf.append(" - PNews</title>\n");
buf.append("</head>\n");
buf.append("<body>\n");
- appendMenu(buf, catActive);
+ appendMenu(buf, catActive, cats);
i = 0;
for (Article e: articles) {
public class JSON {
private static final Logger LOG = Logger.getLogger(JSON.class.getName());
- public static String getStats() {
+ public static String getStats(Category[] cats) {
JsonObject jstats, jreadcounts, jcategories, jmemory;
- Article[] articles;
Runtime runtime;
+ Article[] articles;
jstats = new JsonObject();
jcategories = new JsonObject();
jstats.add("categories", jcategories);
- for (Category cat: Category.values())
+ for (Category cat: cats)
try {
- jcategories.addProperty(cat.getId(), ArticleProvider.singleton.getArticles(cat).size());
- } catch (IllegalArgumentException | FeedException | IOException e) {
+ jcategories.addProperty(cat.getName(),
+ articles.length);
+ } catch (IllegalArgumentException e) {
LOG.log(Level.SEVERE, "Fail to retrieve articles", e);
}
private static final String CLASS_NAME = Pnews.class.getName();
private static final Logger LOG = Logger.getLogger(Pnews.class.getName());
private static final long serialVersionUID = 1L;
- private static final ArticleProvider provider = ArticleProvider.singleton;
+ private ArticleProvider provider;
+ private Config config;
private static String getQueryParameter(HttpServletRequest rq, String key)
throws UnsupportedEncodingException {
rp.setContentType("application/json;charset=utf-8");
rp.setCharacterEncoding("utf-8");
- rp.getWriter().write(JSON.getStats());
+ rp.getWriter().write(JSON.getStats(config.getCategories()));
}
try {
articles = provider.getArticles(cat);
if (articles != null) {
- html = HTML.toHTML(articles, cat);
+ html = HTML.toHTML(articles, cat, config.getCategories());
rp.setContentType("text/html;charset=utf-8");
rp.getWriter().write(html);
rp.setCharacterEncoding("utf-8");
} else {
LOG.severe("writeArticles cannot retrieve any articles");
- html = HTML.toHTML(new ArrayList<Article>(), cat);
+ html = HTML.toHTML(new ArrayList<Article>(), cat, config.getCategories());
rp.setContentType("text/html");
rp.getWriter().write(html);
}
}
if (path.equals("/")) {
- writeArticles(Category.ACTUALITE, resp);
+ writeArticles(config.getDefaultCategory(), resp);
return ;
}
return ;
}
- for (Category cat: Category.values()) {
- if (path.equals('/' + cat.getId())) {
+ for (Category cat: config.getCategories()) {
+ if (path.equals(cat.getURL())) {
writeArticles(cat, resp);
return ;
}
}
@Override
- public void init(ServletConfig config) throws ServletException {
- LOG.info("Pnews servlet init " + config.getServletContext().getContextPath());
-
+ public void init(ServletConfig cfg) throws ServletException {
+ LOG.info("Pnews servlet init " + cfg.getServletContext().getContextPath());
+
+ config = new Config();
+ config.loadConfig();
+
+ provider = new ArticleProvider(config);
}
}
{
- "http://www.europe1.fr/var/export/rss/europe1/actus.xml": {
- "categories": ["ACTUALITE"],
- "language": "fr"
- },
- "http://www.francetvinfo.fr/titres.rss": {
- "categories": ["ACTUALITE"],
- "language": "fr"
- },
- "http://www.rfi.fr/general/rss": {
- "categories": ["ACTUALITE"],
- "language": "fr"
- },
- "http://www.cnews.fr/rss/une": {
- "categories": ["ACTUALITE"],
- "language": "fr"
- },
- "http://www.ladepeche.fr/rss/a-la-une.rss": {
- "categories": ["ACTUALITE"],
- "language": "fr"
- },
- "https://www.franceinter.fr/rss/a-la-une.xml": {
- "categories": ["ACTUALITE"],
- "language": "fr"
- },
- "https://www.francebleu.fr/rss/a-la-une.xml": {
- "categories": ["ACTUALITE"],
- "language": "fr"
- },
- "http://www.bfmtv.com/rss/info/flux-rss/flux-toutes-les-actualites/": {
- "categories": ["ACTUALITE"],
- "language": "fr"
+ "feeds": {
+ "http://www.europe1.fr/var/export/rss/europe1/actus.xml": { "categories": ["ACTUALITE"] },
+ "http://www.francetvinfo.fr/titres.rss": { "categories": ["ACTUALITE"] },
+ "http://www.rfi.fr/general/rss": { "categories": ["ACTUALITE"] },
+ "http://www.cnews.fr/rss/une": { "categories": ["ACTUALITE"] },
+ "http://www.ladepeche.fr/rss/a-la-une.rss": { "categories": ["ACTUALITE"] },
+ "https://www.franceinter.fr/rss/a-la-une.xml": { "categories": ["ACTUALITE"] },
+ "https://www.francebleu.fr/rss/a-la-une.xml": { "categories": ["ACTUALITE"] },
+ "http://www.bfmtv.com/rss/info/flux-rss/flux-toutes-les-actualites/": { "categories": ["ACTUALITE"] },
+ "http://www.europe1.fr/var/export/rss/europe1/sport.xml": { "categories": ["SPORT"] },
+ "http://www.sportune.fr/feed": { "categories": ["SPORT"] },
+ "http://www.france24.com/fr/sports/rss": { "categories": ["SPORT"] },
+ "http://www.france24.com/fr/france/rss": { "categories": ["FRANCE"] },
+ "http://www.francetvinfo.fr/france.rss": { "categories": ["FRANCE"] },
+ "http://www.rfi.fr/france/rss": { "categories": ["FRANCE"] },
+ "http://www.france24.com/fr/europe/rss": { "categories": ["EUROPE"] },
+ "http://www.europe1.fr/var/export/rss/europe1/international.xml": { "categories": ["MONDE"] },
+ "http://www.france24.com/fr/actualites/rss": { "categories": ["MONDE"] },
+ "http://www.france24.com/fr/economie/rss": { "categories": ["ECONOMIE"] },
+ "http://www.europe1.fr/var/export/rss/europe1/economie.xml": { "categories": ["ECONOMIE"] },
+ "http://www.rfi.fr/economie/rss": { "categories": ["ECONOMIE"] },
+ "http://www.tourisme-essonne.com/rss/actus/": { "categories": ["ESSONNE"] },
+ "http://www.ville-palaiseau.fr/rss/actualites.htm": { "categories": ["ESSONNE"] },
+ "http://www.premiere.fr/rss/actu-live": { "categories": ["PEOPLE"] },
+ "http://www.purepeople.com/rss/news_t0.xml": { "categories": ["PEOPLE"] },
+ "http://www.generation-nt.com/export/rss.xml": { "categories": ["TECHNOLOGIE"] },
+ "http://www.europe1.fr/var/export/rss/europe1/sciences.xml": { "categories": ["TECHNOLOGIE"] },
+ "http://feeds.feedburner.com/lesnumeriques/news": { "categories": ["TECHNOLOGIE"] },
+ "http://www.zdnet.fr/feeds/rss/actualites/": { "categories": ["TECHNOLOGIE"] },
+ "http://www.frandroid.com/feed": { "categories": ["TECHNOLOGIE"] },
+ "http://www.silicon.fr/feed": { "categories": ["TECHNOLOGIE"] },
+ "http://www.fredzone.org/feed": { "categories": ["TECHNOLOGIE"] },
+ "http://www.futura-sciences.com/rss/actualites.xml": { "categories": ["TECHNOLOGIE"] },
+ "https://www-03.ibm.com/press/fr/fr/rssfeed.wss?keyword=null&maxFeed=&feedType=RSS&topic=all": { "categories": ["TECHNOLOGIE"] }
}
}