View Javadoc

1   package org.apache.maven.plugin.changes;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import com.sun.syndication.feed.synd.SyndContent;
23  import com.sun.syndication.feed.synd.SyndContentImpl;
24  import com.sun.syndication.feed.synd.SyndEntry;
25  import com.sun.syndication.feed.synd.SyndEntryImpl;
26  import com.sun.syndication.feed.synd.SyndFeed;
27  import com.sun.syndication.feed.synd.SyndFeedImpl;
28  import com.sun.syndication.io.FeedException;
29  import com.sun.syndication.io.SyndFeedOutput;
30  
31  import java.io.IOException;
32  import java.io.Writer;
33  
34  import java.text.DateFormat;
35  import java.text.ParseException;
36  
37  import java.util.ArrayList;
38  import java.util.Date;
39  import java.util.List;
40  import java.util.Locale;
41  import java.util.ResourceBundle;
42  
43  import org.apache.maven.doxia.util.HtmlTools;
44  
45  import org.apache.maven.plugins.changes.model.Release;
46  
47  
48  /**
49   *
50   * @author ltheussl
51   */
52  public class FeedGenerator
53  {
54      private final ResourceBundle rbundle;
55      private final SyndFeed feed;
56  
57      private String link;
58      private String title;
59      private String author;
60      private DateFormat dateFormat;
61  
62      /**
63       * Initialize feedGenerator for a given locale.
64       *
65       * @param locale a locale for i18n.
66       */
67      public FeedGenerator( final Locale locale )
68      {
69          this.feed = new SyndFeedImpl();
70          this.rbundle = ResourceBundle.getBundle( "changes-report", locale, this.getClass().getClassLoader() );
71      }
72  
73      /**
74       * The author of the feed.
75       *
76       * @return the author.
77       */
78      public String getAuthor()
79      {
80          return author;
81      }
82  
83      /**
84       * Set the author of the feed.
85       *
86       * @param author not null.
87       */
88      public void setAuthor( final String author )
89      {
90          this.author = author.trim(); // this also assures that author is not null.
91      }
92  
93      /**
94       * The title of the feed.
95       *
96       * @return the title.
97       */
98      public String getTitle()
99      {
100         return title;
101     }
102 
103     /**
104      * Set the title of the feed.
105      *
106      * @param title not null.
107      */
108     public void setTitle( final String title )
109     {
110         this.title = title.trim(); // this also assures that title is not null.
111     }
112 
113     /**
114      * The DateFormat.
115      *
116      * @return may be null.
117      */
118     public DateFormat getDateFormat()
119     {
120         return dateFormat;
121     }
122 
123     /**
124      * Set the date format.
125      * This should match the date format used for the release dates in changes.xml.
126      *
127      * @param dateFormat may be null.
128      */
129     public void setDateFormat( final DateFormat dateFormat )
130     {
131         this.dateFormat = dateFormat;
132     }
133 
134     /**
135      * The main link of the feed.
136      *
137      * @return the link.
138      */
139     public String getLink()
140     {
141         return link;
142     }
143 
144     /**
145      * Set the main link of the feed.
146      *
147      * @param link not null.
148      */
149     public void setLink( final String link )
150     {
151         this.link = link.trim(); // this also assures that link is not null.
152     }
153 
154     /**
155      * Determine if a given feed type is supported. The currently supported values are:
156      * <code>"rss_0.9", "rss_0.91N" (RSS 0.91 Netscape), "rss_0.91U" (RSS 0.91 Userland),
157      * "rss_0.92", "rss_0.93", "rss_0.94", "rss_1.0", "rss_2.0", "atom_0.3", "atom_1.0"</code>.
158      *
159      * @param type the feed type to check. May be null.
160      *
161      * @return true if if the given type is supported by the rome library, false otherwise.
162      */
163     public boolean isSupportedFeedType( final String type )
164     {
165         return getSupportedFeedTypes().contains( type );
166     }
167 
168     /**
169      * A List of supported feed types.
170      *
171      * @return a List of supported feed types.
172      *
173      * @see #isSupportedFeedType(java.lang.String)
174      */
175     @SuppressWarnings( "unchecked" )
176     public List<String> getSupportedFeedTypes()
177     {
178         return feed.getSupportedFeedTypes();
179     }
180 
181     /**
182      * Extract a feed and export it to a Writer.
183      *
184      * @param releases the List of Releases. Only the last release is used in the feed.
185      * @param feedType The type of the feed to generate.
186      *      See {@link #isSupportedFeedType(java.lang.String)} for supported values.
187      *
188      * @param writer a Writer. Note that this is not flushed nor closed upon exit.
189      *
190      * @throws IOException if an error occurs during export.
191      */
192     public void export( final List<Release> releases, final String feedType, final Writer writer )
193         throws IOException
194     {
195         feed.setFeedType( feedType );
196         feed.setTitle( title );
197         feed.setAuthor( author );
198         feed.setPublishedDate( new Date() );
199         feed.setLink( link );
200         feed.setDescription( rbundle.getString( "report.changes.text.rssfeed.description" ) );
201         feed.setLanguage( rbundle.getLocale().getLanguage() );
202         //feed.setCopyright(  );
203         //feed.setEncoding();
204         feed.setEntries( getEntries( releases ) );
205 
206         try
207         {
208             new SyndFeedOutput().output( feed, writer );
209         }
210         catch ( FeedException ex )
211         {
212             IOException ioex = new IOException( ex.getMessage() );
213             ioex.initCause( ex );
214             throw ioex;
215         }
216     }
217 
218     private List<SyndEntry> getEntries( final List<Release> releases )
219     {
220         final List<SyndEntry> entries = new ArrayList<SyndEntry>( 1 );
221 
222         if ( releases.size() > 0 )
223         {
224             final Release release = releases.get( 0 ); // TODO: is this guaranteed to be the latest?
225 
226             final SyndEntry entry = new SyndEntryImpl();
227             entry.setTitle( release.getVersion() );
228             entry.setLink( link + "#" + HtmlTools.encodeId( release.getVersion() ) );
229             entry.setDescription( getSyndContent( release ) );
230             entry.setPublishedDate( getDate( release.getDateRelease(), dateFormat ) );
231 
232             entries.add( entry );
233         }
234 
235         return entries;
236     }
237 
238     private static SyndContent getSyndContent( final Release release )
239     {
240         final SyndContent syndContent = new SyndContentImpl();
241         syndContent.setType( "text/html" );
242 
243         final StringBuilder sb = new StringBuilder( 512 );
244 
245         final String description = release.getDescription();
246 
247         if ( description != null && description.trim().length() > 0 )
248         {
249             sb.append( "<p>" ).append( description ).append( "</p>" );
250         }
251 
252         // TODO: localize?
253         sb.append( "<p>Version " )
254             .append( release.getVersion() ).append( " is available with " )
255             .append( release.getActions().size() ).append( " fixed issues.</p>" );
256 
257         syndContent.setValue( sb.toString() );
258 
259         return syndContent;
260     }
261 
262     private static Date getDate( final String dateRelease, final DateFormat dateFormat )
263     {
264         if ( dateFormat == null )
265         {
266             return new Date();
267         }
268 
269         try
270         {
271             return dateFormat.parse( dateRelease );
272         }
273         catch ( ParseException ex )
274         {
275             return new Date();
276         }
277     }
278 }