Added experimental about page, updated more Rome code, first preparations to adapt feed fetcher code
This commit is contained in:
@@ -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<FeedFetcherTask> feedFetcherTasks = new TreeSet<FeedFetcherTask>();
|
||||
//
|
||||
// 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<UserFeed, Integer> userFeedDao = DaoManager.createDao(connectionSource, UserFeed.class);
|
||||
// CloseableIterator<UserFeed> 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<Future<IFeed>> 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<IFeed> feeds = new ArrayList<IFeed>();
|
||||
// try {
|
||||
// for (Future<IFeed> 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("<strong>");
|
||||
// super.beforeRender(component);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void afterRender(Component component) {
|
||||
// super.afterRender(component);
|
||||
// component.getResponse().write("</strong>");
|
||||
// }
|
||||
// }));
|
||||
// feedMarkup.add(new Label("feeddate", errorStatus));
|
||||
// }
|
||||
//
|
||||
// RepeatingView itemRv = new RepeatingView("item");
|
||||
// feedMarkup.add(itemRv);
|
||||
// String lastDay = null;
|
||||
// ArrayList<FeedItem> 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<FeedItem> 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";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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.*;
|
||||
@@ -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.*;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -1,4 +1,4 @@
|
||||
package dev.rsems.syndication.rome.io.impl;
|
||||
package dev.rsems.rometools.rome.io.impl;
|
||||
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc.
|
||||
@@ -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;
|
||||
@@ -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
|
||||
13
src/main/resources/templates/about.html
Normal file
13
src/main/resources/templates/about.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title th:text="'About ' + ${appName}"></title>
|
||||
<link th:href="@{/styles/stylesheet.css}" rel="stylesheet" />
|
||||
<link th:href="@{/favicon.ico}" rel="shortcut icon" type="image/x-icon" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>About <a href="/" th:text="${appName}"></a></h1>
|
||||
<p>This is a feed aggregator & feed reader application</p>
|
||||
<hr />
|
||||
<div class="foot" th:text="${appName}"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,6 +5,7 @@
|
||||
<link th:href="@{/favicon.ico}" rel="shortcut icon" type="image/x-icon" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 th:text="${appName}"></h1><h2><a href="/about">About</a></h2>
|
||||
<div class="page">
|
||||
<div class="feeds">
|
||||
<div class="feed">
|
||||
|
||||
Reference in New Issue
Block a user