From c583a8cfee9cc3f49029f69b23692577ba99eb68 Mon Sep 17 00:00:00 2001 From: ulrich <undisclosed> Date: Sun, 01 Apr 2018 10:57:18 +0000 Subject: [PATCH] Feed-Servlet hinzugefuegt --- src/de/vogella/rss/model/FeedMessage.java | 61 +++++ src/de/uhilger/wbx/web/FeedStreamWriter.java | 119 +++++++++ src/de/vogella/rss/model/Feed.java | 65 +++++ src/de/uhilger/wbx/web/FeedServlet.java | 293 ++++++++++++++++++++++++ src/de/uhilger/wbx/web/TestServlet.java | 143 +++++++++++ 5 files changed, 681 insertions(+), 0 deletions(-) diff --git a/src/de/uhilger/wbx/web/FeedServlet.java b/src/de/uhilger/wbx/web/FeedServlet.java new file mode 100644 index 0000000..07d132a --- /dev/null +++ b/src/de/uhilger/wbx/web/FeedServlet.java @@ -0,0 +1,293 @@ + +package de.uhilger.wbx.web; + +import de.uhilger.wbx.web.FeedStreamWriter; +import de.vogella.rss.model.Feed; +import de.vogella.rss.model.FeedMessage; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Das FeedServlet erstellt Feeds von Ordnern der WebBox + * + * Eine Maximaltiefe als Parameter soll regeln, wie viele Ordner tief + * Dateien gesucht werden + * + */ +public class FeedServlet extends HttpServlet { + + private static final Logger logger = Logger.getLogger(FeedServlet.class.getName()); + + public static final String JNDI_CTX_NAME = "java:comp/env"; + public static final String WBX_FILE_BASE = "wbxFileBase"; + public static final String WBX_MAX_FEED_DEPTH = "wbxMaxFeedDepth"; + public static final String WBX_MAX_FEED_ENTRIES = "wbxMaxFeedEntries"; + + public static final int WBX_DEF_MAX_FEED_DEPTH = 3; + public static final int WBX_DEF_MAX_FEED_ENTRIES = 5; + + public static final String NOT_FOUND = " nicht gefunden"; + public static final String NO_STRING = " ist kein String"; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + ServletOutputStream out = response.getOutputStream(); + response.setContentType("text/xml"); + String url = request.getRequestURL().toString(); + logger.fine("requestURL: " + url); + String dataUrl = url.replace("feed/", "data/"); + logger.fine("dataUrl: " + dataUrl); + int pos = dataUrl.indexOf("data/"); + String zielPfad = dataUrl.substring(pos); + logger.fine(zielPfad); + //ServletContext ctx = request.getServletContext(); + //Object o = ctx.getAttribute(FILE_BASE); + String basis = getJNDIParameter(WBX_FILE_BASE); + //if(o instanceof String) { + //String basis = o.toString(); + logger.fine("basis: " + basis); + StringBuffer pfad = new StringBuffer(); + pfad.append(basis); + pfad.append(zielPfad.replace("data/", "/www/")); + logger.fine("pfad: " + pfad); + String dirStr = pfad.toString().substring(0, pfad.lastIndexOf("/")); + logger.fine("dirStr: " + dirStr); + File dir = new File(dirStr); + if(dir.isDirectory()) { + List beitraege = new ArrayList(); + int maxBeitraege = getJNDIInt(WBX_MAX_FEED_ENTRIES, WBX_DEF_MAX_FEED_ENTRIES); + int maxTiefe = getJNDIInt(WBX_MAX_FEED_DEPTH, WBX_DEF_MAX_FEED_DEPTH); + collectFiles(dir, 0, beitraege, maxTiefe, maxBeitraege); + Iterator i = beitraege.iterator(); + while(i.hasNext()) { + File f = (File) i.next(); + logger.fine(f.getAbsolutePath() + " " + f.lastModified()); + } + writeFeed("Newsfeed", "Neueste Inhalte von Ulrich Hilger", out, beitraege, basis, pfad.toString()); + } else { + logger.fine(dir.getAbsolutePath() + " ist kein Ordner."); + } + //} + } + + /** + * Diese Methode funktioniert nur, wenn entweder ein Ordner uebergeben + * wird, der keine Unterordner enthaelt wie zum Beispiel der Ordner 'neu' + * der Bildersammlung oder ein Ordner, dessen Unterordner + * nach dem Schema Jahr, Monat benannt sind wie bei einem Journal, das + * die Beitraege wie folgt enthaelt: + * Journal-Ordner + * 2018 + * 12 + * 11 + * 10 + * usw. + * 2017 + * 12 + * 11 + * 10 + * usw. + * + * @param out + * @param dir + * @param tiefe + * @param dateizaehler + */ + private void collectFiles(File dir, int tiefe, List beitraege, int maxTiefe, int maxBeitraege) { + List dirs = new ArrayList(); + List beitraegeHier = new ArrayList(); + File[] files = dir.listFiles(); + for(int i = 0; i < files.length; i++) { + if(files[i].isDirectory()) { + if(tiefe < maxTiefe) { + dirs.add(files[i]); + } + } else { + beitraegeHier.add(files[i]); + } + } + + if(dirs.size() > 0) { + // hier zuvor die Verzeichnissse absteigend nach Name sortieren + Collections.sort(dirs, new Comparator<File>() { + @Override + public int compare(File o1, File o2) { + return o2.getName().compareTo(o1.getName()); + } + }); + + Iterator i = dirs.iterator(); + while(i.hasNext() && beitraege.size() < maxBeitraege) { + collectFiles((File) i.next(), tiefe+1, beitraege, maxTiefe, maxBeitraege); + } + } + if(beitraegeHier.size() > 0) { + // hier zuvor die Liste der Beitraege dieses Ordners nach lastModified absteigend sortieren + // dann die neuesten in beitraege aufnehmen, bis die maximale Zahl gesuchter + // neuer Beitraege erreicht ist. + + Collections.sort(beitraegeHier, new Comparator<File>() { + @Override + public int compare(File o1, File o2) { + int ergebnis; + if(o1.lastModified() > o2.lastModified()) { + ergebnis = -1; + } else if(o2.lastModified() > o1.lastModified()) { + ergebnis = 1; + } else { + ergebnis = 0; + } + return ergebnis; + } + }); + + Iterator i = beitraegeHier.iterator(); + while(i.hasNext() && beitraege.size() < maxBeitraege) { + File bf = (File) i.next(); + String nm = bf.getName().toLowerCase(); + if(nm.endsWith(".htmi") || nm.endsWith(".html") || nm.endsWith(".htm") || + nm.endsWith(".jpg") || nm.endsWith(".jpeg") || nm.endsWith(".png") || + nm.endsWith(".txt")) { + beitraege.add(bf); + } + } + + } + } + + public void writeFeed(String feedTitel, String beschr, ServletOutputStream s, List beitraege, String basis, String pfad) { + String copyright = "Copyright (c) 2018 Ulrich Hilger"; + String title = feedTitel; + String description = beschr; + String language = "de"; + String link = "https://www.uhilger.de"; + Calendar cal = new GregorianCalendar(); + Date creationDate = cal.getTime(); + SimpleDateFormat date_format = new SimpleDateFormat( + "EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US); + String pubdate = date_format.format(creationDate); + Feed rssFeed = new Feed(title, link, description, language, + copyright, pubdate); + + Iterator i = beitraege.iterator(); + while (i.hasNext()) { + File f = (File) i.next(); + FeedMessage feedEintrag = new FeedMessage(); + feedEintrag.setTitle(f.getName()); + //feedEintrag.setDescription("Beschreibung hier"); + feedEintrag.setAuthor("ulrich Punkt hilger bei web Punkt de (Ulrich Hilger)"); + + String urlStr = f.getAbsolutePath(); + urlStr = urlStr.replace(basis, "https://uhilger.de"); + urlStr = urlStr.replace("www/", "data/"); + + logger.fine(urlStr); + + feedEintrag.setGuid(urlStr); + feedEintrag.setLink(urlStr); + logger.fine(f.getName()); + feedEintrag.setDescription(readFilePart(f, urlStr)); + rssFeed.getMessages().add(feedEintrag); + } + + FeedStreamWriter writer = new FeedStreamWriter(rssFeed, s); + //RSSFeedWriter writer = new RSSFeedWriter(rssFeed, pfad + "/articles.rss"); + //ByteArrayOutputStream bs = new ByteArrayOutputStream(); + //RSSByteFeedWriter wr = new RSSByteFeedWriter(rssFeed, bs); + try { + writer.write(); + //s.print(bs.toString()); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + } + } + + private String readFilePart(File f, String urlStr) { + StringBuffer buf = new StringBuffer(); + Reader reader = null; + try { + String fn = f.getName().toLowerCase(); + if(fn.endsWith(".jpg") || fn.endsWith(".jpeg") || fn.endsWith(".png")) { + String noExt; + String ext; + int dotpos = urlStr.lastIndexOf('.'); + if(dotpos > -1) { + noExt = urlStr.substring(0, dotpos); + ext = urlStr.substring(dotpos); + } else { + noExt = ""; + ext = ""; + } + buf.append("<a href='"); + buf.append(urlStr); + buf.append("'><img src='"); + buf.append(noExt); + buf.append("_kl"); + buf.append(ext); + buf.append("'></a>"); + } else { + reader = new FileReader(f); + char[] readBuffer = new char[1024]; + int charsRead = reader.read(readBuffer); + buf.append(readBuffer); + reader.close(); + } + return buf.toString(); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + return buf.toString(); + } + } + + private int getJNDIInt(String paramName, int defaultVal) { + String jndiStr = getJNDIParameter(paramName); + try { + return Integer.parseInt(jndiStr); + } catch(NumberFormatException ex) { + return defaultVal; + } + } + + private String getJNDIParameter(String pname) { + try { + // unseren environment naming context ermitteln + Context initCtx = new InitialContext(); + Context envCtx = (Context) initCtx.lookup(JNDI_CTX_NAME); + + // unseren Parameter lesen + Object o = envCtx.lookup(pname); + if(o instanceof String) { + return o.toString(); + } else { + return NO_STRING; + } + } catch (NamingException ex) { + logger.log(Level.SEVERE, ex.getMessage()); + return NOT_FOUND; + } + } + +} diff --git a/src/de/uhilger/wbx/web/FeedStreamWriter.java b/src/de/uhilger/wbx/web/FeedStreamWriter.java new file mode 100644 index 0000000..6708c7b --- /dev/null +++ b/src/de/uhilger/wbx/web/FeedStreamWriter.java @@ -0,0 +1,119 @@ +package de.uhilger.wbx.web; + +import java.io.FileOutputStream; + +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartDocument; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import de.vogella.rss.model.Feed; +import de.vogella.rss.model.FeedMessage; +import java.io.OutputStream; + +public class FeedStreamWriter { + + //private String outputFile; + private Feed rssfeed; + private OutputStream out; + + public FeedStreamWriter(Feed rssfeed, OutputStream s) { + this.rssfeed = rssfeed; + this.out = s; + } + + public void write() throws Exception { + + // create a XMLOutputFactory + XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); + + // create XMLEventWriter + XMLEventWriter eventWriter = outputFactory + .createXMLEventWriter(out); + + // create a EventFactory + + XMLEventFactory eventFactory = XMLEventFactory.newInstance(); + XMLEvent end = eventFactory.createDTD("\n"); + + // create and write Start Tag + + StartDocument startDocument = eventFactory.createStartDocument(); + + eventWriter.add(startDocument); + + // create open tag + eventWriter.add(end); + + StartElement rssStart = eventFactory.createStartElement("", "", "rss"); + eventWriter.add(rssStart); + eventWriter.add(eventFactory.createAttribute("version", "2.0")); + eventWriter.add(end); + + eventWriter.add(eventFactory.createStartElement("", "", "channel")); + eventWriter.add(end); + + // Write the different nodes + + createNode(eventWriter, "title", rssfeed.getTitle()); + + createNode(eventWriter, "link", rssfeed.getLink()); + + createNode(eventWriter, "description", rssfeed.getDescription()); + + createNode(eventWriter, "language", rssfeed.getLanguage()); + + createNode(eventWriter, "copyright", rssfeed.getCopyright()); + + createNode(eventWriter, "pubdate", rssfeed.getPubDate()); + + for (FeedMessage entry : rssfeed.getMessages()) { + eventWriter.add(eventFactory.createStartElement("", "", "item")); + eventWriter.add(end); + createNode(eventWriter, "title", entry.getTitle()); + createNode(eventWriter, "description", entry.getDescription()); + createNode(eventWriter, "link", entry.getLink()); + createNode(eventWriter, "author", entry.getAuthor()); + createNode(eventWriter, "guid", entry.getGuid()); + eventWriter.add(end); + eventWriter.add(eventFactory.createEndElement("", "", "item")); + eventWriter.add(end); + + } + + eventWriter.add(end); + eventWriter.add(eventFactory.createEndElement("", "", "channel")); + eventWriter.add(end); + eventWriter.add(eventFactory.createEndElement("", "", "rss")); + + eventWriter.add(end); + + eventWriter.add(eventFactory.createEndDocument()); + + eventWriter.close(); + } + + private void createNode(XMLEventWriter eventWriter, String name, + + String value) throws XMLStreamException { + XMLEventFactory eventFactory = XMLEventFactory.newInstance(); + XMLEvent end = eventFactory.createDTD("\n"); + XMLEvent tab = eventFactory.createDTD("\t"); + // create Start node + StartElement sElement = eventFactory.createStartElement("", "", name); + eventWriter.add(tab); + eventWriter.add(sElement); + // create Content + Characters characters = eventFactory.createCharacters(value); + eventWriter.add(characters); + // create End node + EndElement eElement = eventFactory.createEndElement("", "", name); + eventWriter.add(eElement); + eventWriter.add(end); + } +} \ No newline at end of file diff --git a/src/de/uhilger/wbx/web/TestServlet.java b/src/de/uhilger/wbx/web/TestServlet.java new file mode 100644 index 0000000..9580778 --- /dev/null +++ b/src/de/uhilger/wbx/web/TestServlet.java @@ -0,0 +1,143 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package de.uhilger.wbx.web; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + */ +public class TestServlet extends HttpServlet { + + private static final Logger logger = Logger.getLogger(TestServlet.class.getName()); + + public static final String JNDI_CTX_NAME = "java:comp/env"; + public static final String PARAM_NAME = "wbxFileBase"; + public static final String NOT_FOUND = " nicht gefunden"; + public static final String NO_STRING = " ist kein String"; + + /** + * Processes requests for both HTTP <code>GET</code> and <code>POST</code> + * methods. + * + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + protected void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + try (PrintWriter out = response.getWriter()) { + out.println("<!DOCTYPE html>"); + out.println("<html>"); + out.println("<head>"); + out.println("<title>Servlet TestServlet</title>"); + out.println("</head>"); + out.println("<body>"); + out.println("<h1>Servlet TestServlet at " + request.getContextPath() + "</h1>"); + + // hier kommt veraenderlicher Inhalt + ServletContext ctx = request.getServletContext(); + Object o = ctx.getAttribute("filebase"); + String base; + if(o instanceof String) { + base = o.toString(); + } else { + base = "unbekannt"; + } + out.print("<p>filebase: "); + out.print(base); + out.print("</p>\n"); + + out.print("<p>"); + out.print(PARAM_NAME); + out.print(": "); + out.print(getJNDIParameter(PARAM_NAME)); + out.print("</p>\n"); + + out.print("<p>"); + out.print("Request URL: "); + out.print(request.getRequestURL()); + out.print("</p>\n"); + // Ende des veraenderlichen Inhalts + + out.println("</body>"); + out.println("</html>"); + } + } + + private String getJNDIParameter(String pname) { + try { + // unseren environment naming context ermitteln + Context initCtx = new InitialContext(); + Context envCtx = (Context) initCtx.lookup(JNDI_CTX_NAME); + + // unseren Parameter lesen + Object o = envCtx.lookup(pname); + if(o instanceof String) { + return o.toString(); + } else { + return NO_STRING; + } + } catch (NamingException ex) { + logger.log(Level.SEVERE, ex.getMessage()); + return NOT_FOUND; + } + } + + + // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> + /** + * Handles the HTTP <code>GET</code> method. + * + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Handles the HTTP <code>POST</code> method. + * + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Returns a short description of the servlet. + * + * @return a String containing servlet description + */ + @Override + public String getServletInfo() { + return "Short description"; + }// </editor-fold> + +} diff --git a/src/de/vogella/rss/model/Feed.java b/src/de/vogella/rss/model/Feed.java new file mode 100644 index 0000000..e124ee1 --- /dev/null +++ b/src/de/vogella/rss/model/Feed.java @@ -0,0 +1,65 @@ +package de.vogella.rss.model; + +import java.util.ArrayList; +import java.util.List; + +/* + * Stores an RSS feed + */ +public class Feed { + + final String title; + final String link; + final String description; + final String language; + final String copyright; + final String pubDate; + + final List<FeedMessage> entries = new ArrayList<FeedMessage>(); + + public Feed(String title, String link, String description, String language, + String copyright, String pubDate) { + this.title = title; + this.link = link; + this.description = description; + this.language = language; + this.copyright = copyright; + this.pubDate = pubDate; + } + + public List<FeedMessage> getMessages() { + return entries; + } + + public String getTitle() { + return title; + } + + public String getLink() { + return link; + } + + public String getDescription() { + return description; + } + + public String getLanguage() { + return language; + } + + public String getCopyright() { + return copyright; + } + + public String getPubDate() { + return pubDate; + } + + @Override + public String toString() { + return "Feed [copyright=" + copyright + ", description=" + description + + ", language=" + language + ", link=" + link + ", pubDate=" + + pubDate + ", title=" + title + "]"; + } + +} \ No newline at end of file diff --git a/src/de/vogella/rss/model/FeedMessage.java b/src/de/vogella/rss/model/FeedMessage.java new file mode 100644 index 0000000..6cb9b45 --- /dev/null +++ b/src/de/vogella/rss/model/FeedMessage.java @@ -0,0 +1,61 @@ +package de.vogella.rss.model; + +/* + * Represents one RSS message + */ +public class FeedMessage { + + String title; + String description; + String link; + String author; + String guid; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getLink() { + return link; + } + + public void setLink(String link) { + this.link = link; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getGuid() { + return guid; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + @Override + public String toString() { + return "FeedMessage [title=" + title + ", description=" + description + + ", link=" + link + ", author=" + author + ", guid=" + guid + + "]"; + } + +} -- Gitblit v1.9.3