001 package 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
017 import java.io.*;
018 import java.util.*;
019
020 import com.sun.syndication.feed.synd.*;
021 import com.sun.syndication.io.FeedException;
022 import com.sun.syndication.io.SyndFeedInput;
023 import com.sun.syndication.io.SyndFeedOutput;
024
025 import 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 */
047 public 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 contents = new ArrayList();
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 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 }