View Javadoc
1   package net.sf.logdistiller.publishers;
2   
3   /*
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  import java.io.*;
18  import java.util.*;
19  
20  import com.sun.syndication.feed.synd.*;
21  import com.sun.syndication.io.FeedException;
22  import com.sun.syndication.io.SyndFeedInput;
23  import com.sun.syndication.io.SyndFeedOutput;
24  
25  import net.sf.logdistiller.*;
26  
27  /**
28   * Adds LogDistillation reports to a feed file (at the beginning). Any feed format supported by Rome can be used.
29   * <p>
30   * Parameters (as direct publisher param or global <code>feed.*</code> param):
31   * <ul>
32   * <li><code>filename</code> (default: <code>feed.xml</code>): the feed file name (relative to output directory)</li>
33   * <li><code>maxEntries</code> (default: 100): maximum entries in the feed file: if new entries are added, oldest ones
34   * are removed</li>
35   * </ul>
36   * <p>
37   * When the feed file must be created, these parameters are used:
38   * <ul>
39   * <li><code>type</code> (default: <code>atom_0.3</code>): the feed type (any value supported by Rome)</li>
40   * <li><code>title</code>: the feed title (default: "LogDistiller [logdistillation id]"</li>
41   * <li><code>link</code>: the feed link (default: LogDistiller's site)</li>
42   * <li><code>description</code>: the feed description (default: "LogDistiller reports for [logdistillation id]"</li>
43   * </ul>
44   *
45   * @since 0.7
46   */
47  public class FeedPublisher
48      extends Publisher
49  {
50      public final static String DEFAULT_FEED_TYPE = "atom_0.3";
51  
52      public String getId()
53      {
54          return "feed";
55      }
56  
57      public void publish( LogDistillation logdistillation, LogDistiller.Report report )
58          throws IOException, PublishException
59      {
60          // prepare the data for the entry
61          String content = logdistillation.getContent();
62          String subject =
63              "[logdistiller:" + logdistillation.getDefinition().getId() + "]"
64                  + ( ( content == null ) ? "" : ( " " + content ) ) + " global report: "
65                  + logdistillation.getEventCount() + " logevents";
66          ReportFormat format = ReportFormats.getReportFormat( report.getFormat() );
67          StringWriter sw = new StringWriter();
68          format.report( logdistillation, sw );
69          String body = sw.toString();
70          String url = logdistillation.getDefinition().getOutput().getUrl();
71  
72          // create the new entry
73          SyndEntry entry = createEntry( subject, url, format.getContentType(), body );
74  
75          // add it to the feed (creating it if necessary)
76          addEntry( entry, logdistillation, report );
77      }
78  
79      public void publish( LogDistillation.Group group, LogDistiller.Report report )
80          throws IOException, PublishException
81      {
82          // prepare the data for the entry
83          LogDistillation logdistillation = group.getLogdistillation();
84          String content = logdistillation.getContent();
85          String subject =
86              "[logdistiller:" + logdistillation.getDefinition().getOutput().getId() + "]"
87                  + ( ( content == null ) ? "" : ( " " + content ) ) + " report for group "
88                  + group.getDefinition().getId() + ": " + group.getEventCount() + " logevents";
89          ReportFormat format = ReportFormats.getReportFormat( report.getFormat() );
90          StringWriter sw = new StringWriter();
91          format.report( group, sw );
92          String body = sw.toString();
93          String url = logdistillation.getDefinition().getOutput().getUrl();
94  
95          // create the new entry
96          SyndEntry entry = createEntry( subject, url, format.getContentType(), body );
97  
98          // add it to the feed (creating it if necessary)
99          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 }