/* * [RSSFeedExport.java] * * Summary: Convert the rss/temprss.bin binary log of items into RSS2 feeds of form rss/jgloss.xml. * * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.8 2009-02-06 include go package in ZIP bundle. * prepends the rss/prelude/jgloss.xml prelude header. */ package com.mindprod.htmlmacros.support; import com.mindprod.common18.EIO; import com.mindprod.fastcat.FastCat; import com.mindprod.hunkio.HunkIO; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import static com.mindprod.htmlmacros.macro.Global.configuration; import static java.lang.System.*; /** * Convert the rss/temprss.bin binary log of items into RSS2 feeds of form rss/jgloss.xml. * * @author Roedy Green, Canadian Mind Products * @version 1.8 2009-02-06 include go package in ZIP bundle. * prepends the rss/prelude/jgloss.xml prelude header. * @since 2009 */ final class RSSFeedExport { /** * mask for: "Fri, 08 Aug 2008 12:27:08 UTC" must be in English. */ @SuppressWarnings( { "StringWithMistakes" } ) /** format for build date of entire feed */ private static final SimpleDateFormat BUILD_DATE_SDF; private static PrintWriter emit; static { BUILD_DATE_SDF = new SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US ); BUILD_DATE_SDF.setTimeZone( TimeZone.getTimeZone( "GMT" ) );// standard does not support UTC } /** * emit xml need for one item * * @param feedItem rss item to export as XML to the corresponding feed file. */ private static void doFeedItem( RSSSortableItem feedItem ) { emit.println( feedItem.asRSSxml() ); } /** * emit xml needed for end of a feed */ private static void endFeed() { // close off previous group emit.println( postlude() ); emit.close(); } /** * Prepare the various feeds from the combined binary RSS feed log. */ @SuppressWarnings( { "StringEquality" } ) static void exportAllFeeds() { // if whatsnew.html was bypassed by cache mechanism // it will have no items processed. // if it has no items, we will have no items // if processed some subset of the files that did not include // whatsnew.html, we will have no items. // SO, if items we don't export anything. Leave existing XML files // as is. if ( RSSFeedLog.count == 0 ) { return; } try { if ( configuration.isVerbose() ) { out.println( "preparing " + RSSFeedLog.count + " RSS items" ); } ArrayList sortableRSSFeedItems = new ArrayList<>( RSSFeedLog.count ); readAllFeeds( sortableRSSFeedItems ); // sort items by feed/descending date. Collections.sort( sortableRSSFeedItems, new RSSSortableItem.ByFeedByDate() ); emit = null; String prevKey = null; // code works even if no items. for ( RSSSortableItem feedItem : sortableRSSFeedItems ) { // exporting to xml, several different RSS feeds. // feedName is interned so can directly compare with != instead of .equals String thisKey = feedItem.getFeedName(); if ( thisKey != prevKey ) { // starting a new group if ( prevKey != null ) { endFeed(); } startFeed( feedItem ); } // always emit the item itself. doFeedItem( feedItem ); prevKey = thisKey; } // end for // finish off the very last group. if ( prevKey != null ) { endFeed(); } } catch ( IOException e ) { throw new IllegalArgumentException( "Problems preparing the RSS feed files from the binary log. : " + e.getMessage() ); } } /** * get XML to tack on end of XML feed file * * @return xml tail for an RSS feed file */ @SuppressWarnings( { "SameReturnValue" } ) private static String postlude() { return ""; } /** * get XML to tack on front of XML feed file. * * @param feedName name of feed * * @return xml prelude to an RSS feed. */ private static String prelude( String feedName ) { /** * fetch from prelude file. * we need to insert build date with current time between * tags. */ final File preludeFile = new File( configuration.getLocalWebrootWithSlashes() + "/rss/prelude/" + feedName + ".xml" ); try { String preludeText = HunkIO.readEntireFile( preludeFile, EIO.UTF8 ); int fix = preludeText.indexOf( "" ); if ( fix < 0 ) { throw new IllegalArgumentException( "Missing in RSS preludeText file" + " " + preludeFile.toString() ); } // get current time in form Fri, 08 Aug 2008 12:27:08 UTC String buildDate = BUILD_DATE_SDF.format( new Date() );// current time final FastCat sb = new FastCat( 3 ); sb.append( preludeText.substring( 0, fix + "".length() ) ); sb.append( buildDate ); sb.append( preludeText.substring( fix + "".length() ) ); return sb.toString(); } catch ( IOException e ) { throw new IllegalArgumentException( "Trouble reading RSS prelude file " + preludeFile.toString() + " : " + e.getMessage() ); } } /** * read the binary RSS feed item log into an ArrayList * * @param sortableRSSFeedItems ArrayList to add items to. * * @throws IOException if problem reading binary log file. */ @SuppressWarnings( { "InfiniteLoopStatement" } ) private static void readAllFeeds( ArrayList sortableRSSFeedItems ) throws IOException { DataInputStream instream = null; try { instream = EIO.getDataInputStream( RSSFeedLog.rssBinaryLogFile, 1024 * 10 ); while ( true ) { sortableRSSFeedItems.add( RSSSortableItem.read( instream ) ); } } catch ( EOFException e ) { // normal eof } finally { if ( instream != null ) { instream.close(); // no longer need the binary log file. //noinspection ResultOfMethodCallIgnored RSSFeedLog.rssBinaryLogFile.delete(); } } } /** * emit xml needed for start of feed export * * @param feedItem first rss item of a feed. * * @throws java.io.FileNotFoundException if trouble finding the corresponding prelude file. * @throws java.io.UnsupportedEncodingException if ISO-8859-1 not supported. */ private static void startFeed( RSSSortableItem feedItem ) throws UnsupportedEncodingException, FileNotFoundException { // first item in group. final File emitFile = new File( configuration.getLocalWebrootWithSlashes() + "/rss/" + feedItem.getFeedName() + ".xml" ); emit = EIO.getPrintWriter( emitFile, 4 * 1024, EIO.UTF8 ); emit.println( prelude( feedItem.getFeedName() ) ); } }