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   * @author ltheussl
49   */
50  public class FeedGenerator
51  {
52      private final ResourceBundle rbundle;
53  
54      private final SyndFeed feed;
55  
56      private String link;
57  
58      private String title;
59  
60      private String author;
61  
62      private DateFormat dateFormat;
63  
64      /**
65       * Initialize feedGenerator for a given locale.
66       *
67       * @param locale a locale for i18n.
68       */
69      public FeedGenerator( final Locale locale )
70      {
71          this.feed = new SyndFeedImpl();
72          this.rbundle = ResourceBundle.getBundle( "changes-report", locale, this.getClass().getClassLoader() );
73      }
74  
75      /**
76       * The author of the feed.
77       *
78       * @return the author.
79       */
80      public String getAuthor()
81      {
82          return author;
83      }
84  
85      /**
86       * Set the author of the feed.
87       *
88       * @param author not null.
89       */
90      public void setAuthor( final String author )
91      {
92          this.author = author.trim(); // this also assures that author is not null.
93      }
94  
95      /**
96       * The title of the feed.
97       *
98       * @return the title.
99       */
100     public String getTitle()
101     {
102         return title;
103     }
104 
105     /**
106      * Set the title of the feed.
107      *
108      * @param title not null.
109      */
110     public void setTitle( final String title )
111     {
112         this.title = title.trim(); // this also assures that title is not null.
113     }
114 
115     /**
116      * The DateFormat.
117      *
118      * @return may be null.
119      */
120     public DateFormat getDateFormat()
121     {
122         return dateFormat;
123     }
124 
125     /**
126      * Set the date format. This should match the date format used for the release dates in changes.xml.
127      *
128      * @param dateFormat may be null.
129      */
130     public void setDateFormat( final DateFormat dateFormat )
131     {
132         this.dateFormat = dateFormat;
133     }
134 
135     /**
136      * The main link of the feed.
137      *
138      * @return the link.
139      */
140     public String getLink()
141     {
142         return link;
143     }
144 
145     /**
146      * Set the main link of the feed.
147      *
148      * @param link not null.
149      */
150     public void setLink( final String link )
151     {
152         this.link = link.trim(); // this also assures that link is not null.
153     }
154 
155     /**
156      * Determine if a given feed type is supported. The currently supported values are:
157      * <code>"rss_0.9", "rss_0.91N" (RSS 0.91 Netscape), "rss_0.91U" (RSS 0.91 Userland),
158      * "rss_0.92", "rss_0.93", "rss_0.94", "rss_1.0", "rss_2.0", "atom_0.3", "atom_1.0"</code>.
159      *
160      * @param type the feed type to check. May be null.
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      * @see #isSupportedFeedType(java.lang.String)
173      */
174     @SuppressWarnings( "unchecked" )
175     public List<String> getSupportedFeedTypes()
176     {
177         return feed.getSupportedFeedTypes();
178     }
179 
180     /**
181      * Extract a feed and export it to a Writer.
182      *
183      * @param releases the List of Releases. Only the last release is used in the feed.
184      * @param feedType The type of the feed to generate. See {@link #isSupportedFeedType(java.lang.String)} for
185      *            supported values.
186      * @param writer a Writer. Note that this is not flushed nor closed upon exit.
187      * @throws IOException if an error occurs during export.
188      */
189     public void export( final List<Release> releases, final String feedType, final Writer writer )
190         throws IOException
191     {
192         feed.setFeedType( feedType );
193         feed.setTitle( title );
194         feed.setAuthor( author );
195         feed.setPublishedDate( new Date() );
196         feed.setLink( link );
197         feed.setDescription( rbundle.getString( "report.changes.text.rssfeed.description" ) );
198         feed.setLanguage( rbundle.getLocale().getLanguage() );
199         // feed.setCopyright( );
200         // feed.setEncoding();
201         feed.setEntries( getEntries( releases ) );
202 
203         try
204         {
205             new SyndFeedOutput().output( feed, writer );
206         }
207         catch ( FeedException ex )
208         {
209             IOException ioex = new IOException( ex.getMessage() );
210             ioex.initCause( ex );
211             throw ioex;
212         }
213     }
214 
215     private List<SyndEntry> getEntries( final List<Release> releases )
216     {
217         final List<SyndEntry> entries = new ArrayList<SyndEntry>( 1 );
218 
219         if ( releases.size() > 0 )
220         {
221             final Release release = releases.get( 0 ); // TODO: is this guaranteed to be the latest?
222 
223             final SyndEntry entry = new SyndEntryImpl();
224             entry.setTitle( release.getVersion() );
225             entry.setLink( link + "#" + HtmlTools.encodeId( release.getVersion() ) );
226             entry.setDescription( getSyndContent( release ) );
227             entry.setPublishedDate( getDate( release.getDateRelease(), dateFormat ) );
228 
229             entries.add( entry );
230         }
231 
232         return entries;
233     }
234 
235     private static SyndContent getSyndContent( final Release release )
236     {
237         final SyndContent syndContent = new SyndContentImpl();
238         syndContent.setType( "text/html" );
239 
240         final StringBuilder sb = new StringBuilder( 512 );
241 
242         final String description = release.getDescription();
243 
244         if ( description != null && description.trim().length() > 0 )
245         {
246             sb.append( "<p>" ).append( description ).append( "</p>" );
247         }
248 
249         // TODO: localize?
250         sb.append( "<p>Version " ).append( release.getVersion() ).append( " is available with " );
251         sb.append( release.getActions().size() ).append( " fixed issues.</p>" );
252 
253         syndContent.setValue( sb.toString() );
254 
255         return syndContent;
256     }
257 
258     private static Date getDate( final String dateRelease, final DateFormat dateFormat )
259     {
260         if ( dateFormat == null )
261         {
262             return new Date();
263         }
264 
265         try
266         {
267             return dateFormat.parse( dateRelease );
268         }
269         catch ( ParseException ex )
270         {
271             return new Date();
272         }
273     }
274 }