diff --git a/src/main/java/dev/rsems/feedreader/FeedReaderController.java b/src/main/java/dev/rsems/feedreader/FeedReaderController.java index b4b48fb..cf8eec7 100644 --- a/src/main/java/dev/rsems/feedreader/FeedReaderController.java +++ b/src/main/java/dev/rsems/feedreader/FeedReaderController.java @@ -1,18 +1,220 @@ package dev.rsems.feedreader; +import com.rometools.fetcher.FeedFetcher; +import com.rometools.fetcher.impl.FeedFetcherCache; +import com.rometools.fetcher.impl.HttpURLFeedFetcher; +import com.rometools.fetcher.impl.LinkedHashMapFeedInfoCache; +import dev.rsems.feedreader.fetcher.FetcherEventListenerImpl; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; -@Controller +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +@Controller @Slf4j public class FeedReaderController { @Value("${spring.application.name}") String appName; + private static final Logger logger = log; + + private static final FeedFetcherCache feedInfoCache = LinkedHashMapFeedInfoCache.getInstance(); + public static final FeedFetcher fetcher = new HttpURLFeedFetcher(feedInfoCache); + private static final FetcherEventListenerImpl listener = new FetcherEventListenerImpl(); + + static { + fetcher.addFetcherEventListener(listener); + } + + private static final int MAX_ITEMS_PER_FEED = 20; + private static final DateFormat TIME_FMT = new SimpleDateFormat("HH:mm"); + private static final DateFormat DAY_FMT = new SimpleDateFormat("EEEE',' dd. M. yyyy"); + @GetMapping("/") - public String homePage(Model model) { + public String index(Model model) { model.addAttribute("appName", appName); + +// Stopwatch stw = new Stopwatch(true); +// +// Set feedFetcherTasks = new TreeSet(); +// +// logger.info("[" + "] Reading database and building the feed fetcher tasks list"); +// +// ConnectionSource connectionSource = null; +// try { +// connectionSource = new JdbcConnectionSource("jdbc:mysql://db.rsems.de/feeds?user=feeds&password=fems1211"); +// Dao userFeedDao = DaoManager.createDao(connectionSource, UserFeed.class); +// CloseableIterator ituf = userFeedDao.closeableIterator(); +// try { +// int i = 0; +// while (ituf.hasNext()) { +// UserFeed userFeed = ituf.next(); +// if (userFeed.getVisible()) { +// i++; +// +// feedFetcherTasks.add(new FeedFetcherTask(i, userFeed.getFeed().getName(), userFeed.getFeed().getUrl(), "", userFeed.getFilter())); +// // logger.info("[" + remoteHost + "] #" + new DecimalFormat("00").format(i) + " " + userFeed.getFeed().getName() + " added"); +// } +// } +// } catch (Exception e) { +// logger.error(ExceptionUtils.getMessages(e)); +// logger.error("\n" + ExceptionUtils.getStackTrace(e)); +// throw new FeedException(e); +// } finally { +// ituf.close(); +// } +// } catch (SQLException e) { +// logger.error(ExceptionUtils.getMessages(e)); +// logger.error("\n" + ExceptionUtils.getStackTrace(e)); +// throw new FeedException("Failed to access database", e); +// } finally { +// if (connectionSource != null) { +// try { +// connectionSource.close(); +// } catch (SQLException unhandled) { +// } +// } +// } +// +// logger.info("[" + remoteHost + "] About to invoke " + feedFetcherTasks.size() + " feed retrieval tasks after " +// + stw.getTimeElapsed() + " ms"); +// +// List> feedFutures = null; +// ExecutorService executorService = Executors.newCachedThreadPool(); +// try { +// feedFutures = executorService.invokeAll(feedFetcherTasks); +// } catch (InterruptedException e) { +// logger.error(ExceptionUtils.getMessages(e)); +// logger.error("\n" + ExceptionUtils.getStackTrace(e)); +// throw new FeedException(e); +// } +// +// logger.info("[" + remoteHost + "] About to extract retrieved data from task results after " + stw.getTimeElapsed() + " ms"); +// +// ArrayList feeds = new ArrayList(); +// try { +// for (Future ff : feedFutures) { +// feeds.add(ff.get()); +// } +// } catch (Exception e) { +// logger.error(ExceptionUtils.getMessages(e)); +// logger.error("\n" + ExceptionUtils.getStackTrace(e)); +// throw new FeedException(e); +// } finally { +// executorService.shutdown(); +// } +// +// logger.info("[" + remoteHost + "] About to render retrieved data after " + stw.getTimeElapsed() + " ms"); +// +// add(new Label("head.title", Globals.TITLE)); +// RepeatingView feedRv = new RepeatingView("feed"); +// add(feedRv); +// +// int fc = 0; +// for (IFeed feed : feeds) { +// fc++; +// +// long lap = stw.getTimeElapsed(); +// +// WebMarkupContainer feedMarkup = new WebMarkupContainer(feedRv.newChildId()); +// feedRv.add(feedMarkup); +// String errorStatus = feed.getErrorStatus(); +// +// feedMarkup.add(new ExternalLink("feedtitle", (feed.getLink() == null ? "" : feed.getLink()), feed.getName())); +// +// if (errorStatus.equals("")) { +// feedMarkup.add(new ExternalLink("feedurl", feed.getUrl().toExternalForm(), feed.getTitle())); +// feedMarkup +// .add(new Label("feeddate", feed.getDate() != null ? Globals.DEFAULT_DISPLAY_DATE_FORMAT.format(feed.getDate()) : " ")); // this is ANSI 160, not space +// } else { +// feedMarkup.add(new ExternalLink("feedurl", feed.getUrl().toExternalForm(), "Error retrieving feed").add(new Behavior() { +// @Override +// public void beforeRender(Component component) { +// component.getResponse().write(""); +// super.beforeRender(component); +// } +// +// @Override +// public void afterRender(Component component) { +// super.afterRender(component); +// component.getResponse().write(""); +// } +// })); +// feedMarkup.add(new Label("feeddate", errorStatus)); +// } +// +// RepeatingView itemRv = new RepeatingView("item"); +// feedMarkup.add(itemRv); +// String lastDay = null; +// ArrayList items = feed.getFeedItems(); +// +// if (feed.getErrorStatus() != "") { +// logger.info("[Client " + remoteHost + "] " + feed.getErrorStatus() + "\n" + feed.getStackTrace()); +// } +// +// Collections.sort(items, FeedItem.LATEST_FIRST); +// int count = 0; +// for (Iterator it = items.iterator(); it.hasNext(); ) { +// FeedItem item = it.next(); +// +// String itemlabel = item.getTitle() == null ? "—" : StringUtils.cleanHtml(item.getTitle(), feed.getUrl().getPath()); +// +// if (!item.getTitle().isEmpty() && !feed.getFilter().matches(itemlabel)) { +// +// WebMarkupContainer itemMarkup = new WebMarkupContainer(itemRv.newChildId()); +// itemRv.add(itemMarkup); +// +// Date itemDate = item.getDate(); +// String day = itemDate == null ? " " : DAY_FMT.format(itemDate); //   not space +// final boolean dayEqualsLastDay = day.equals(lastDay); +// itemMarkup.add(new Label("date", day) { +// @Override +// public boolean isVisible() { +// return !dayEqualsLastDay; +// } +// }); +// if (!dayEqualsLastDay) { +// lastDay = day; +// } +// itemMarkup.add(new Label("itemdate", itemDate == null ? "—" : TIME_FMT.format(itemDate))); +// +// String itemlink = item.getLink() == null ? "" : item.getLink(); +// +// String itemsummary = item.getSummary() == null ? "" : StringUtils.cleanHtml(item.getSummary(), feed.getUrl().getPath()); +// itemMarkup.add(new ExternalLink("itemlink", itemlink, itemlabel).add(new AttributeModifier("title", itemsummary))); +// +// String itemAuthor = item.getAuthor() == null || item.getAuthor().equals("") ? "" +// : " (" + item.getAuthor().replaceFirst("(.*?)<(.*?)@(.*?)>", "$1").trim() + ")"; +// itemMarkup.add(new Label("itemauthor", StringUtils.unquote(itemAuthor))); +// +// count++; +// if (count >= MAX_ITEMS_PER_FEED) { +// break; +// } +// +// } +// +// } +// +// logger.info("[" + remoteHost + "] #" + fc + ": " + count + " feed items processed (" + (stw.getTimeElapsed() - lap) + " ms)"); +// +// } +// +// add(new Label("foot", Globals.TITLE + " " + Version.VERSION + " " + Globals.DEFAULT_DISPLAY_DATE_FORMAT.format(new Date()))); +// +// logger.info("[" + remoteHost + "] Finished processing feeds after " + stw.getTimeElapsed() + " ms"); + return "index"; } + + @GetMapping("/about") + public String about(Model model) { + model.addAttribute("appName", appName); + return "about"; + } + } \ No newline at end of file diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/DateParser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/DateParser.java similarity index 99% rename from src/main/java/dev/rsems/syndication/rome/io/impl/DateParser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/DateParser.java index 3c50b90..8969121 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/DateParser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/DateParser.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; import com.rometools.rome.io.impl.PropertiesLoader; diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS090Parser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS090Parser.java similarity index 99% rename from src/main/java/dev/rsems/syndication/rome/io/impl/RSS090Parser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/RSS090Parser.java index 53ddd17..fa14426 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS090Parser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS090Parser.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; import com.rometools.rome.feed.WireFeed; import com.rometools.rome.feed.rss.Channel; diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS091UserlandParser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS091UserlandParser.java similarity index 99% rename from src/main/java/dev/rsems/syndication/rome/io/impl/RSS091UserlandParser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/RSS091UserlandParser.java index c25200f..958e127 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS091UserlandParser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS091UserlandParser.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; import com.rometools.rome.feed.WireFeed; import com.rometools.rome.feed.rss.*; diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS092Parser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS092Parser.java similarity index 99% rename from src/main/java/dev/rsems/syndication/rome/io/impl/RSS092Parser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/RSS092Parser.java index e0a3cf4..18ebbed 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS092Parser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS092Parser.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; import com.rometools.rome.feed.WireFeed; import com.rometools.rome.feed.rss.*; diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS093Parser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS093Parser.java similarity index 97% rename from src/main/java/dev/rsems/syndication/rome/io/impl/RSS093Parser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/RSS093Parser.java index 136e1d7..cbfb14d 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS093Parser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS093Parser.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; import com.rometools.rome.feed.rss.Item; import org.jdom2.Element; diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS094Parser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS094Parser.java similarity index 98% rename from src/main/java/dev/rsems/syndication/rome/io/impl/RSS094Parser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/RSS094Parser.java index 9f93ffb..0e632bb 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS094Parser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS094Parser.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; import com.rometools.rome.feed.WireFeed; import com.rometools.rome.feed.rss.Channel; diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS10Parser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS10Parser.java similarity index 98% rename from src/main/java/dev/rsems/syndication/rome/io/impl/RSS10Parser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/RSS10Parser.java index e66782f..562652b 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS10Parser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS10Parser.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; import com.rometools.rome.feed.WireFeed; import com.rometools.rome.feed.rss.Channel; diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS20Parser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS20Parser.java similarity index 97% rename from src/main/java/dev/rsems/syndication/rome/io/impl/RSS20Parser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/RSS20Parser.java index e645ca2..95c65c5 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS20Parser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS20Parser.java @@ -1,4 +1,4 @@ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; /* * Copyright 2004 Sun Microsystems, Inc. diff --git a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS20wNSParser.java b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS20wNSParser.java similarity index 98% rename from src/main/java/dev/rsems/syndication/rome/io/impl/RSS20wNSParser.java rename to src/main/java/dev/rsems/rometools/rome/io/impl/RSS20wNSParser.java index db6f016..9b1c248 100644 --- a/src/main/java/dev/rsems/syndication/rome/io/impl/RSS20wNSParser.java +++ b/src/main/java/dev/rsems/rometools/rome/io/impl/RSS20wNSParser.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package dev.rsems.syndication.rome.io.impl; +package dev.rsems.rometools.rome.io.impl; import com.rometools.rome.feed.WireFeed; import org.jdom2.Document; diff --git a/src/main/resources/rome.properties b/src/main/resources/rome.properties index 0519ed2..a841936 100644 --- a/src/main/resources/rome.properties +++ b/src/main/resources/rome.properties @@ -1,13 +1,13 @@ # Feed Parser implementation classes # -WireFeedParser.classes=dev.rsems.syndication.rome.io.impl.RSS090Parser \ - com.sun.syndication.io.impl.RSS091NetscapeParser \ - com.sun.syndication.io.impl.RSS091UserlandParser \ - com.sun.syndication.io.impl.RSS092Parser \ - dev.rsems.syndication.rome.io.impl.RSS093Parser \ - dev.rsems.syndication.rome.io.impl.RSS094Parser \ - dev.rsems.syndication.rome.io.impl.RSS10Parser \ - dev.rsems.syndication.rome.io.impl.RSS20wNSParser \ - dev.rsems.syndication.rome.io.impl.RSS20Parser \ - com.sun.syndication.io.impl.Atom10Parser \ - com.sun.syndication.io.impl.Atom03Parser +WireFeedParser.classes=dev.rsems.rometools.rome.io.impl.RSS090Parser \ + com.rometools.rome.io.impl.RSS091NetscapeParser \ + com.rometools.rome.io.impl.RSS091UserlandParser \ + com.rometools.rome.io.impl.RSS092Parser \ + dev.rsems.rometools.rome.io.impl.RSS093Parser \ + dev.rsems.rometools.rome.io.impl.RSS094Parser \ + dev.rsems.rometools.rome.io.impl.RSS10Parser \ + dev.rsems.rometools.rome.io.impl.RSS20wNSParser \ + dev.rsems.rometools.rome.io.impl.RSS20Parser \ + com.rometools.rome.io.impl.Atom10Parser \ + com.rometools.rome.io.impl.Atom03Parser \ No newline at end of file diff --git a/src/main/resources/templates/about.html b/src/main/resources/templates/about.html new file mode 100644 index 0000000..af36b65 --- /dev/null +++ b/src/main/resources/templates/about.html @@ -0,0 +1,13 @@ + + + + + + + +

About

+

This is a feed aggregator & feed reader application

+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 1661b03..b2378d4 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -5,6 +5,7 @@ +

About