001package net.sf.logdistiller.publishers; 002 003/* 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017import java.io.*; 018import java.util.*; 019 020import com.sun.syndication.feed.synd.*; 021import com.sun.syndication.io.FeedException; 022import com.sun.syndication.io.SyndFeedInput; 023import com.sun.syndication.io.SyndFeedOutput; 024 025import net.sf.logdistiller.*; 026 027/** 028 * Adds LogDistillation reports to a feed file (at the beginning). Any feed format supported by Rome can be used. 029 * <p> 030 * Parameters (as direct publisher param or global <code>feed.*</code> param): 031 * <ul> 032 * <li><code>filename</code> (default: <code>feed.xml</code>): the feed file name (relative to output directory)</li> 033 * <li><code>maxEntries</code> (default: 100): maximum entries in the feed file: if new entries are added, oldest ones 034 * are removed</li> 035 * </ul> 036 * <p> 037 * When the feed file must be created, these parameters are used: 038 * <ul> 039 * <li><code>type</code> (default: <code>atom_0.3</code>): the feed type (any value supported by Rome)</li> 040 * <li><code>title</code>: the feed title (default: "LogDistiller [logdistillation id]"</li> 041 * <li><code>link</code>: the feed link (default: LogDistiller's site)</li> 042 * <li><code>description</code>: the feed description (default: "LogDistiller reports for [logdistillation id]"</li> 043 * </ul> 044 * 045 * @since 0.7 046 */ 047public class FeedPublisher 048 extends Publisher 049{ 050 public final static String DEFAULT_FEED_TYPE = "atom_0.3"; 051 052 public String getId() 053 { 054 return "feed"; 055 } 056 057 public void publish( LogDistillation logdistillation, LogDistiller.Report report ) 058 throws IOException, PublishException 059 { 060 // prepare the data for the entry 061 String content = logdistillation.getContent(); 062 String subject = 063 "[logdistiller:" + logdistillation.getDefinition().getId() + "]" 064 + ( ( content == null ) ? "" : ( " " + content ) ) + " global report: " 065 + logdistillation.getEventCount() + " logevents"; 066 ReportFormat format = ReportFormats.getReportFormat( report.getFormat() ); 067 StringWriter sw = new StringWriter(); 068 format.report( logdistillation, sw ); 069 String body = sw.toString(); 070 String url = logdistillation.getDefinition().getOutput().getUrl(); 071 072 // create the new entry 073 SyndEntry entry = createEntry( subject, url, format.getContentType(), body ); 074 075 // add it to the feed (creating it if necessary) 076 addEntry( entry, logdistillation, report ); 077 } 078 079 public void publish( LogDistillation.Group group, LogDistiller.Report report ) 080 throws IOException, PublishException 081 { 082 // prepare the data for the entry 083 LogDistillation logdistillation = group.getLogdistillation(); 084 String content = logdistillation.getContent(); 085 String subject = 086 "[logdistiller:" + logdistillation.getDefinition().getOutput().getId() + "]" 087 + ( ( content == null ) ? "" : ( " " + content ) ) + " report for group " 088 + group.getDefinition().getId() + ": " + group.getEventCount() + " logevents"; 089 ReportFormat format = ReportFormats.getReportFormat( report.getFormat() ); 090 StringWriter sw = new StringWriter(); 091 format.report( group, sw ); 092 String body = sw.toString(); 093 String url = logdistillation.getDefinition().getOutput().getUrl(); 094 095 // create the new entry 096 SyndEntry entry = createEntry( subject, url, format.getContentType(), body ); 097 098 // add it to the feed (creating it if necessary) 099 addEntry( entry, logdistillation, report ); 100 } 101 102 /** 103 * Create a new feed for the corresponding report. 104 * 105 * @param logdistillation 106 * @param report 107 * @return the new feed 108 */ 109 private SyndFeed createFeed( LogDistillation logdistillation, LogDistiller.Report report ) 110 { 111 String type = report.getParam( "type", DEFAULT_FEED_TYPE ); 112 String title = report.getParam( "title", "Logdistiller " + logdistillation.getDefinition().getOutput().getId() ); 113 String url = logdistillation.getDefinition().getOutput().getUrl(); 114 String link = report.getParam( "link", ( url == null ) ? "http://logdistiller.sf.net/" : url ); 115 String description = 116 report.getParam( "description", "LogDistiller reports for " 117 + logdistillation.getDefinition().getOutput().getId() ); 118 119 SyndFeed feed = new SyndFeedImpl(); 120 feed.setFeedType( type ); 121 feed.setTitle( title ); 122 feed.setLink( link ); 123 feed.setDescription( description ); 124 125 return feed; 126 } 127 128 /** 129 * Create a feed entry. 130 * 131 * @param title the title of the entry 132 * @param link the link of the entry (or <code>null</code>) 133 * @param contentType the content-type of the entry 134 * @param contentValue the content of the entry 135 * @return a new feed entry 136 */ 137 private SyndEntry createEntry( String title, String link, String contentType, String contentValue ) 138 { 139 SyndEntry entry = new SyndEntryImpl(); 140 entry.setTitle( title ); 141 if ( link != null ) 142 { 143 entry.setLink( link ); 144 } 145 entry.setPublishedDate( new Date() ); 146 147 SyndContent content = new SyndContentImpl(); 148 content.setType( contentType ); 149 content.setValue( contentValue ); 150 List<SyndContent> contents = new ArrayList<SyndContent>(); 151 contents.add( content ); 152 153 entry.setContents( contents ); 154 return entry; 155 } 156 157 /** 158 * Add an entry to a feed report, creating the feed if necessary. 159 * 160 * @param entry the feed entry 161 * @param logdistillation the current logdistillation 162 * @param report the report configuration 163 * @throws IOException 164 * @throws PublishException 165 */ 166 private void addEntry( SyndEntry entry, LogDistillation logdistillation, LogDistiller.Report report ) 167 throws IOException, PublishException 168 { 169 String filename = report.getParam( "filename", "feed.xml" ); 170 int maxEntries = Integer.parseInt( report.getParam( "maxEntries", "100" ) ); 171 File file = logdistillation.newDestinationFile( filename ); 172 173 // read or create the feed 174 SyndFeed feed; 175 if ( file.canRead() && ( file.length() > 0 ) ) 176 { 177 SyndFeedInput input = new SyndFeedInput(); 178 try 179 { 180 feed = input.build( file ); 181 } 182 catch ( FeedException fe ) 183 { 184 throw new PublishException( "error while reading feed " + filename, fe ); 185 } 186 } 187 else 188 { 189 feed = createFeed( logdistillation, report ); 190 } 191 192 // add the new entry 193 List<SyndEntry> entries = feed.getEntries(); 194 entries.add( 0, entry ); 195 if ( entries.size() > maxEntries ) 196 { 197 entries.remove( entries.size() - 1 ); 198 } 199 feed.setEntries( entries ); 200 201 // write the feed content to the disk 202 SyndFeedOutput output = new SyndFeedOutput(); 203 // write to a temporary file that will be swapped with the current file only on success 204 File tmpFile = logdistillation.newDestinationFile( filename + ".tmp" ); 205 try 206 { 207 output.output( feed, tmpFile ); 208 // ok, we were able to write the whole feed: now we can rotate with the final file 209 file.delete(); 210 tmpFile.renameTo( file ); 211 } 212 catch ( FeedException fe ) 213 { 214 throw new PublishException( "error while writing temporary feed " + filename + ".tmp", fe ); 215 } 216 finally 217 { 218 tmpFile.delete(); 219 } 220 } 221}