Coverage Report - org.apache.maven.plugin.changes.ChangesMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
ChangesMojo
0%
0/83
0%
0/24
2,9
 
 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 java.io.File;
 23  
 import java.io.IOException;
 24  
 import java.net.URL;
 25  
 import java.text.SimpleDateFormat;
 26  
 import java.util.Collections;
 27  
 import java.util.Date;
 28  
 import java.util.Iterator;
 29  
 import java.util.Locale;
 30  
 import java.util.Map;
 31  
 import java.util.Properties;
 32  
 import java.util.ResourceBundle;
 33  
 
 34  
 import org.apache.commons.collections.map.CaseInsensitiveMap;
 35  
 import org.apache.maven.execution.MavenSession;
 36  
 import org.apache.maven.reporting.MavenReportException;
 37  
 import org.apache.maven.shared.filtering.MavenFileFilter;
 38  
 import org.apache.maven.shared.filtering.MavenFileFilterRequest;
 39  
 import org.apache.maven.shared.filtering.MavenFilteringException;
 40  
 import org.codehaus.plexus.util.FileUtils;
 41  
 import org.codehaus.plexus.util.IOUtil;
 42  
 import org.codehaus.plexus.util.ReaderFactory;
 43  
 import org.codehaus.plexus.util.StringUtils;
 44  
 import org.codehaus.plexus.util.xml.XmlStreamReader;
 45  
 
 46  
 /**
 47  
  * Goal which creates a nicely formatted Changes Report in html format from a changes.xml file.
 48  
  *
 49  
  * @goal changes-report
 50  
  * @author <a href="mailto:jruiz@exist.com">Johnny R. Ruiz III</a>
 51  
  * @version $Id: org.apache.maven.plugin.changes.ChangesMojo.html 816598 2012-05-08 12:46:49Z hboutemy $
 52  
  * @threadSafe
 53  
  */
 54  0
 public class ChangesMojo
 55  
     extends AbstractChangesReport
 56  
 {
 57  
     /**
 58  
      * A flag whether the report should also include the dates of individual actions. If set to <code>false</code>, only
 59  
      * the dates of releases will be written to the report.
 60  
      *
 61  
      * @parameter expression="${changes.addActionDate}" default-value="false"
 62  
      * @since 2.1
 63  
      */
 64  
     private boolean addActionDate;
 65  
 
 66  
     /**
 67  
      * Whether HTML code within an action should be escaped. By changing this to
 68  
      * <code>false</code> you can restore the behavior that was in version 2.2
 69  
      * of this plugin, allowing you to use HTML code to format the content of an
 70  
      * action.
 71  
      * <p>
 72  
      * <strong>Note:</strong> If you use HTML code in an action you need to
 73  
      * place it inside a CDATA section.
 74  
      * </p>
 75  
      * <strong>Note:</strong> Putting any kind of markup inside a CDATA section
 76  
      * might mess up the Changes Report or other generated documents, such as
 77  
      * PDFs, that are based on your <code>changes.xml</code> file if you are not
 78  
      * careful.
 79  
      *
 80  
      * @parameter default-value="true"
 81  
      * @since 2.4
 82  
      * @deprecated using markup inside CDATA sections does not work for all output formats!
 83  
      */
 84  
     private boolean escapeHTML;
 85  
 
 86  
     /**
 87  
      * The directory for interpolated changes.xml.
 88  
      *
 89  
      * @parameter expression="${project.build.directory}/changes"
 90  
      * @required
 91  
      * @readonly
 92  
      * @since 2.2
 93  
      */
 94  
     private File filteredOutputDirectory;
 95  
 
 96  
     /**
 97  
      * applying filtering filtering "a la" resources plugin
 98  
      *
 99  
      * @parameter default-value="false"
 100  
      * @since 2.2
 101  
      */
 102  
     private boolean filteringChanges;
 103  
 
 104  
     /**
 105  
      * Template string that is used to discover the URL to use to display an issue report.
 106  
      * There are 2 template tokens you can use. <code>%URL%</code>: this is computed by getting the
 107  
      * <code>&lt;issueManagement&gt;/&lt;url&gt;</code> value from the POM, and removing the last '/'
 108  
      * and everything that comes after it. <code>%ISSUE%</code>: this is the issue number.
 109  
      * <p>
 110  
      * <strong>Note:</strong> In versions of this plugin prior to 2.0-beta-2 this parameter was called
 111  
      * <code>link_template</code>.
 112  
      * </p>
 113  
      *
 114  
      * @parameter expression="${changes.issueLinkTemplate}" default-value="%URL%/ViewIssue.jspa?key=%ISSUE%"
 115  
      * @since 2.0-beta-2
 116  
      * @deprecated As of 2.1 use issueLinkTemplatePerSystem : this one will be with system default
 117  
      */
 118  
     private String issueLinkTemplate;
 119  
 
 120  
     /**
 121  
      * Template strings per system that is used to discover the URL to use to display an issue report. Each key in this
 122  
      * map denotes the (case-insensitive) identifier of the issue tracking system and its value gives the URL template.
 123  
      * <p>
 124  
      * There are 2 template tokens you can use. <code>%URL%</code>: this is computed by getting the
 125  
      * <code>&lt;issueManagement&gt;/&lt;url&gt;</code> value from the POM, and removing the last '/'
 126  
      * and everything that comes after it. <code>%ISSUE%</code>: this is the issue number.
 127  
      * </p>
 128  
      * <p>
 129  
      * <strong>Note:</strong> The deprecated issueLinkTemplate will be used for a system called "default".
 130  
      * </p>
 131  
      * <p>
 132  
      * <strong>Note:</strong> Starting with version 2.4 you usually don't need
 133  
      * to specify this, unless you need to link to an issue management system in
 134  
      * your Changes report that isn't supported out of the box. See the
 135  
      * <a href="./usage.html">Usage page</a> for more
 136  
      * information.
 137  
      * </p>
 138  
      *
 139  
      * @parameter
 140  
      * @since 2.1
 141  
      */
 142  
     private Map issueLinkTemplatePerSystem;
 143  
 
 144  
     /**
 145  
      * @component
 146  
      * @since 2.2
 147  
      */
 148  
     private MavenFileFilter mavenFileFilter;
 149  
 
 150  
     /**
 151  
      * Format to use for publishDate. The value will be available with the following expression ${publishDate}
 152  
      *
 153  
      * @see SimpleDateFormat
 154  
      * @parameter default-value="yyyy-MM-dd"
 155  
      * @since 2.2
 156  
      */
 157  
     private String publishDateFormat;
 158  
 
 159  
    /**
 160  
     * Locale to use for publishDate when formatting
 161  
     *
 162  
     * @see Locale
 163  
     * @parameter default-value="en"
 164  
     * @since 2.2
 165  
     */
 166  
     private String publishDateLocale;
 167  
 
 168  
     /**
 169  
      * @parameter expression="${session}"
 170  
      * @readonly
 171  
      * @required
 172  
      * @since 2.2
 173  
      */
 174  
     protected MavenSession session;
 175  
 
 176  
     /**
 177  
      * @parameter default-value="${project.issueManagement.system}"
 178  
      * @readonly
 179  
      * @since 2.4
 180  
      */
 181  
     private String system;
 182  
 
 183  
     /**
 184  
      * The URI of a file containing all the team members. If this is set to the
 185  
      * special value "none", no links will be generated for the team members.
 186  
      *
 187  
      * @parameter default-value="team-list.html"
 188  
      * @since 2.4
 189  
      */
 190  
     private String teamlist;
 191  
 
 192  
     /**
 193  
      * @parameter default-value="${project.issueManagement.url}"
 194  
      * @readonly
 195  
      */
 196  
     private String url;
 197  
 
 198  
     /**
 199  
      * The path of the <code>changes.xml</code> file that will be converted into an HTML report.
 200  
      *
 201  
      * @parameter expression="${changes.xmlPath}" default-value="src/changes/changes.xml"
 202  
      */
 203  
     private File xmlPath;
 204  
 
 205  
     private CaseInsensitiveMap caseInsensitiveIssueLinkTemplatePerSystem;
 206  
 
 207  
     /* --------------------------------------------------------------------- */
 208  
     /* Public methods                                                        */
 209  
     /* --------------------------------------------------------------------- */
 210  
 
 211  
     public boolean canGenerateReport()
 212  
     {
 213  0
         return xmlPath.isFile();
 214  
     }
 215  
 
 216  
     public void executeReport( Locale locale )
 217  
         throws MavenReportException
 218  
     {
 219  
 
 220  0
         if ( !xmlPath.exists() )
 221  
         {
 222  0
             getLog().warn( "changes.xml file " + xmlPath.getAbsolutePath() + " does not exist." );
 223  0
             return;
 224  
         }
 225  0
         if ( filteringChanges )
 226  
         {
 227  0
             if ( !filteredOutputDirectory.exists() )
 228  
             {
 229  0
                 filteredOutputDirectory.mkdirs();
 230  
             }
 231  0
             XmlStreamReader xmlStreamReader = null;
 232  
             try
 233  
             {
 234  
                 // so we get encoding from the file itself
 235  0
                 xmlStreamReader = ReaderFactory.newXmlReader( xmlPath );
 236  0
                 String encoding = xmlStreamReader.getEncoding();
 237  0
                 File resultFile = new File( filteredOutputDirectory, "changes.xml" );
 238  0
                 Date now = new Date();
 239  0
                 SimpleDateFormat simpleDateFormat =
 240  
                     new SimpleDateFormat( publishDateFormat, new Locale( publishDateLocale ) );
 241  0
                 Properties additionalProperties = new Properties();
 242  0
                 additionalProperties.put( "publishDate", simpleDateFormat.format( now ) );
 243  0
                 MavenFileFilterRequest mavenFileFilterRequest =
 244  
                     new MavenFileFilterRequest( xmlPath, resultFile, true, project, Collections.EMPTY_LIST, false,
 245  
                                                 encoding, session, additionalProperties );
 246  0
                 mavenFileFilter.copyFile( mavenFileFilterRequest );
 247  0
                 xmlPath = resultFile;
 248  
             }
 249  0
             catch ( IOException e )
 250  
             {
 251  0
                 throw new MavenReportException( "Exception during filtering changes file : " + e.getMessage(), e );
 252  
             }
 253  0
             catch ( MavenFilteringException e )
 254  
             {
 255  0
                 throw new MavenReportException( "Exception during filtering changes file : " + e.getMessage(), e );
 256  
             }
 257  
             finally
 258  
             {
 259  0
                 if ( xmlStreamReader != null )
 260  
                 {
 261  0
                     IOUtil.close( xmlStreamReader );
 262  
                 }
 263  
             }
 264  
 
 265  
         }
 266  
 
 267  0
         ChangesXML changesXml = new ChangesXML( xmlPath, getLog() );
 268  0
         ChangesReportGenerator report = new ChangesReportGenerator( changesXml.getReleaseList() );
 269  
 
 270  0
         report.setAuthor( changesXml.getAuthor() );
 271  0
         report.setTitle( changesXml.getTitle() );
 272  
 
 273  0
         report.setEscapeHTML ( escapeHTML );
 274  
 
 275  
         // Create a case insensitive version of issueLinkTemplatePerSystem
 276  
         // We need something case insensitive to maintain backward compatibility
 277  0
         if ( issueLinkTemplatePerSystem == null )
 278  
         {
 279  0
             caseInsensitiveIssueLinkTemplatePerSystem = new CaseInsensitiveMap();
 280  
         }
 281  
         else
 282  
         {
 283  0
             caseInsensitiveIssueLinkTemplatePerSystem = new CaseInsensitiveMap( issueLinkTemplatePerSystem );
 284  
         }
 285  
 
 286  
         // Set good default values for issue management systems here, but only
 287  
         // if they have not been configured already by the user
 288  0
         addIssueLinkTemplate( ChangesReportGenerator.DEFAULT_ISSUE_SYSTEM_KEY, issueLinkTemplate );
 289  0
         addIssueLinkTemplate( "Bugzilla", "%URL%/show_bug.cgi?id=%ISSUE%" );
 290  0
         addIssueLinkTemplate( "GoogleCode", "%URL%/detail?id=%ISSUE%" );
 291  0
         addIssueLinkTemplate( "JIRA", "%URL%/%ISSUE%" );
 292  0
         addIssueLinkTemplate( "Mantis", "%URL%/view.php?id=%ISSUE%" );
 293  0
         addIssueLinkTemplate( "Redmine", "%URL%/issues/show/%ISSUE%" );
 294  0
         addIssueLinkTemplate( "Scarab", "%URL%/issues/id/%ISSUE%" );
 295  0
         addIssueLinkTemplate( "SourceForge", "http://sourceforge.net/support/tracker.php?aid=%ISSUE%" );
 296  0
         addIssueLinkTemplate( "Trac", "%URL%/ticket/%ISSUE%" );
 297  0
         addIssueLinkTemplate( "YouTrack", "%URL%/issue/%ISSUE%" );
 298  
         // @todo Add more issue management systems here
 299  
 
 300  
         // Show the current issueLinkTemplatePerSystem configuration
 301  0
         logIssueLinkTemplatePerSystem( caseInsensitiveIssueLinkTemplatePerSystem );
 302  
 
 303  0
         report.setIssueLinksPerSystem( caseInsensitiveIssueLinkTemplatePerSystem );
 304  
 
 305  0
         report.setSystem( system );
 306  
 
 307  0
         report.setTeamlist ( teamlist );
 308  
 
 309  0
         report.setUrl( url );
 310  
 
 311  0
         report.setAddActionDate( addActionDate );
 312  
 
 313  0
         if ( StringUtils.isEmpty( url ) )
 314  
         {
 315  0
             getLog().warn( "No issue management URL defined in POM. Links to your issues will not work correctly." );
 316  
         }
 317  
 
 318  0
         report.doGenerateReport( getBundle( locale ), getSink() );
 319  
 
 320  
         // Copy the images
 321  0
         copyStaticResources();
 322  0
     }
 323  
 
 324  
     public String getDescription( Locale locale )
 325  
     {
 326  0
         return getBundle( locale ).getString( "report.issues.description" );
 327  
     }
 328  
 
 329  
     public String getName( Locale locale )
 330  
     {
 331  0
         return getBundle( locale ).getString( "report.issues.name" );
 332  
     }
 333  
 
 334  
     public String getOutputName()
 335  
     {
 336  0
         return "changes-report";
 337  
     }
 338  
 
 339  
     /* --------------------------------------------------------------------- */
 340  
     /* Private methods                                                       */
 341  
     /* --------------------------------------------------------------------- */
 342  
 
 343  
     /**
 344  
      * Add the issue link template for the given issue management system,
 345  
      * but only if it has not already been configured.
 346  
      *
 347  
      * @param system The issue management system
 348  
      * @param issueLinkTemplate The issue link template to use
 349  
      * @since 2.4
 350  
      */
 351  
     private void addIssueLinkTemplate( String system, String issueLinkTemplate )
 352  
     {
 353  0
         if ( caseInsensitiveIssueLinkTemplatePerSystem == null )
 354  
         {
 355  0
             caseInsensitiveIssueLinkTemplatePerSystem = new CaseInsensitiveMap();
 356  
         }
 357  0
         if ( !caseInsensitiveIssueLinkTemplatePerSystem.containsKey( system ) )
 358  
         {
 359  0
             caseInsensitiveIssueLinkTemplatePerSystem.put( system, issueLinkTemplate );
 360  
         }
 361  0
     }
 362  
 
 363  
     private void copyStaticResources()
 364  
         throws MavenReportException
 365  
     {
 366  0
         final String pluginResourcesBase = "org/apache/maven/plugin/changes";
 367  0
         String resourceNames[] = {
 368  
             "images/add.gif",
 369  
             "images/fix.gif",
 370  
             "images/icon_help_sml.gif",
 371  
             "images/remove.gif",
 372  
             "images/rss.png",
 373  
             "images/update.gif" };
 374  
         try
 375  
         {
 376  0
             getLog().debug( "Copying static resources." );
 377  0
             for ( int i = 0; i < resourceNames.length; i++ )
 378  
             {
 379  0
                 URL url = this.getClass().getClassLoader().getResource( pluginResourcesBase + "/" + resourceNames[i] );
 380  0
                 FileUtils.copyURLToFile( url, new File( getReportOutputDirectory(), resourceNames[i] ) );
 381  
             }
 382  
         }
 383  0
         catch ( IOException e )
 384  
         {
 385  0
             throw new MavenReportException( "Unable to copy static resources." );
 386  0
         }
 387  0
     }
 388  
 
 389  
     private ResourceBundle getBundle( Locale locale )
 390  
     {
 391  0
         return ResourceBundle.getBundle( "changes-report", locale, this.getClass().getClassLoader() );
 392  
     }
 393  
 
 394  
     protected String getTeamlist()
 395  
     {
 396  0
         return teamlist;
 397  
     }
 398  
 
 399  
     private void logIssueLinkTemplatePerSystem( Map issueLinkTemplatePerSystem )
 400  
     {
 401  0
         if ( getLog().isDebugEnabled() )
 402  
         {
 403  0
             if ( issueLinkTemplatePerSystem == null )
 404  
             {
 405  0
                 getLog().debug( "No issueLinkTemplatePerSystem configuration was found" );
 406  
             }
 407  
             else
 408  
             {
 409  0
                 Iterator iterator = issueLinkTemplatePerSystem.entrySet().iterator();
 410  0
                 while ( iterator.hasNext() )
 411  
                 {
 412  0
                     Map.Entry entry = (Map.Entry) iterator.next();
 413  0
                     getLog().debug( "issueLinkTemplatePerSystem[" + entry.getKey() + "] = " + entry.getValue() );
 414  0
                 }
 415  
             }
 416  
         }
 417  0
     }
 418  
 }