Coverage Report - org.apache.maven.plugin.jxr.AbstractJxrReport
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractJxrReport
73%
93/128
59%
53/90
2,714
 
 1  
 package org.apache.maven.plugin.jxr;
 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.util.ArrayList;
 26  
 import java.util.Calendar;
 27  
 import java.util.Collection;
 28  
 import java.util.Iterator;
 29  
 import java.util.List;
 30  
 import java.util.Locale;
 31  
 import java.util.ResourceBundle;
 32  
 
 33  
 import org.apache.maven.doxia.siterenderer.Renderer;
 34  
 import org.apache.maven.jxr.JXR;
 35  
 import org.apache.maven.jxr.JxrException;
 36  
 import org.apache.maven.model.Organization;
 37  
 import org.apache.maven.model.ReportPlugin;
 38  
 import org.apache.maven.project.MavenProject;
 39  
 import org.apache.maven.reporting.AbstractMavenReport;
 40  
 import org.apache.maven.reporting.MavenReportException;
 41  
 import org.codehaus.plexus.util.FileUtils;
 42  
 import org.codehaus.plexus.util.ReaderFactory;
 43  
 import org.codehaus.plexus.util.StringUtils;
 44  
 
 45  
 /**
 46  
  * Base class for the JXR reports.
 47  
  *
 48  
  * @author <a href="mailto:bellingard.NO-SPAM@gmail.com">Fabrice Bellingard</a>
 49  
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 50  
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 51  
  * @version $Id: AbstractJxrReport.java 710182 2008-11-03 21:53:34Z hboutemy $
 52  
  */
 53  9
 public abstract class AbstractJxrReport
 54  
     extends AbstractMavenReport
 55  
 {
 56  
     /**
 57  
      * @parameter expression="${project}"
 58  
      * @required
 59  
      * @readonly
 60  
      */
 61  
     private MavenProject project;
 62  
 
 63  
     /**
 64  
      * @component
 65  
      */
 66  
     private Renderer siteRenderer;
 67  
 
 68  
     /**
 69  
      * Output folder where the main page of the report will be generated. Note that this parameter is only relevant if
 70  
      * the goal is run directly from the command line or from the default lifecycle. If the goal is run indirectly as
 71  
      * part of a site generation, the output directory configured in the Maven Site Plugin will be used instead.
 72  
      *
 73  
      * @parameter expression="${project.reporting.outputDirectory}"
 74  
      * @required
 75  
      */
 76  
     private File outputDirectory;
 77  
 
 78  
     /**
 79  
      * File input encoding.
 80  
      *
 81  
      * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
 82  
      */
 83  
     private String inputEncoding;
 84  
 
 85  
     /**
 86  
      * File output encoding.
 87  
      *
 88  
      * @parameter expression="${outputEncoding}" default-value="${project.reporting.outputEncoding}"
 89  
      */
 90  
     private String outputEncoding;
 91  
 
 92  
     /**
 93  
      * Title of window of the Xref HTML files.
 94  
      *
 95  
      * @parameter expression="${project.name} ${project.version} Reference"
 96  
      */
 97  
     private String windowTitle;
 98  
 
 99  
     /**
 100  
      * Title of main page of the Xref HTML files.
 101  
      *
 102  
      * @parameter expression="${project.name} ${project.version} Reference"
 103  
      */
 104  
     private String docTitle;
 105  
 
 106  
     /**
 107  
      * String uses at the bottom of the Xref HTML files.
 108  
      *
 109  
      * @parameter expression="${bottom}" default-value="Copyright &#169; {inceptionYear}-{currentYear} {projectOrganizationName}. All Rights Reserved."
 110  
      */
 111  
     private String bottom;
 112  
 
 113  
     /**
 114  
      * Directory where Velocity templates can be found to generate overviews,
 115  
      * frames and summaries.
 116  
      * Should not be used. If used, should be an absolute path, like <code>"${basedir}/myTemplates"</code>.
 117  
      *
 118  
      * @parameter default-value="templates"
 119  
      */
 120  
     private String templateDir;
 121  
 
 122  
     /**
 123  
      * Style sheet used for the Xref HTML files.
 124  
      * Should not be used. If used, should be an absolute path, like <code>"${basedir}/myStyles.css"</code>.
 125  
      *
 126  
      * @parameter default-value="stylesheet.css"
 127  
      */
 128  
     private String stylesheet;
 129  
 
 130  
     /**
 131  
      * A list of exclude patterns to use. By default no files are excluded.
 132  
      *
 133  
      * @parameter expression="${excludes}"
 134  
      * @since 2.1
 135  
      */
 136  
     private ArrayList excludes;
 137  
 
 138  
     /**
 139  
      * A list of include patterns to use. By default all .java files are included.
 140  
      *
 141  
      * @parameter expression="${includes}"
 142  
      * @since 2.1
 143  
      */
 144  
     private ArrayList includes;
 145  
 
 146  
     /**
 147  
      * The projects in the reactor for aggregation report.
 148  
      *
 149  
      * @parameter expression="${reactorProjects}"
 150  
      * @readonly
 151  
      */
 152  
     protected List reactorProjects;
 153  
 
 154  
     /**
 155  
      * Whether to build an aggregated report at the root, or build individual reports.
 156  
      *
 157  
      * @parameter expression="${aggregate}" default-value="false"
 158  
      */
 159  
     protected boolean aggregate;
 160  
 
 161  
     /**
 162  
      * Link the Javadoc from the Source XRef. Defaults to true and will link
 163  
      * automatically if javadoc plugin is being used.
 164  
      *
 165  
      * @parameter expression="${linkJavadoc}" default-value="true"
 166  
      */
 167  
     private boolean linkJavadoc;
 168  
 
 169  
     /**
 170  
      * Gets the effective reporting output files encoding.
 171  
      *
 172  
      * @return The effective reporting output file encoding, never <code>null</code>: defaults to
 173  
      * <code>UTF-8</code> instead.
 174  
      */
 175  
     protected String getOutputEncoding()
 176  
     {
 177  8
         return ( outputEncoding == null ) ? ReaderFactory.UTF_8 : outputEncoding;
 178  
     }
 179  
 
 180  
     /**
 181  
      * Compiles the list of directories which contain source files that will be included in the JXR report generation.
 182  
      *
 183  
      * @param sourceDirs the List of the source directories
 184  
      * @return a List of the directories that will be included in the JXR report generation
 185  
      */
 186  
     protected List pruneSourceDirs( List sourceDirs )
 187  
     {
 188  9
         List pruned = new ArrayList( sourceDirs.size() );
 189  9
         for ( Iterator i = sourceDirs.iterator(); i.hasNext(); )
 190  
         {
 191  11
             String dir = (String) i.next();
 192  11
             if ( !pruned.contains( dir ) && hasSources( new File( dir ) ) )
 193  
             {
 194  11
                 pruned.add( dir );
 195  
             }
 196  11
         }
 197  9
         return pruned;
 198  
     }
 199  
 
 200  
     /**
 201  
      * Initialize some attributes required during the report generation
 202  
      */
 203  
     protected void init()
 204  
     {
 205  
         // wanna know if Javadoc is being generated
 206  
         // TODO: what if it is not part of the site though, and just on the command line?
 207  8
         Collection plugin = project.getReportPlugins();
 208  8
         if ( plugin != null )
 209  
         {
 210  8
             for ( Iterator iter = plugin.iterator(); iter.hasNext(); )
 211  
             {
 212  7
                 ReportPlugin reportPlugin = (ReportPlugin) iter.next();
 213  7
                 if ( "maven-javadoc-plugin".equals( reportPlugin.getArtifactId() ) )
 214  
                 {
 215  7
                     break;
 216  
                 }
 217  0
             }
 218  
         }
 219  8
     }
 220  
 
 221  
     /**
 222  
      * Checks whether the given directory contains Java files.
 223  
      *
 224  
      * @param dir the source directory
 225  
      * @return true if the folder or one of its subfolders contains at least 1 Java file
 226  
      */
 227  
     private boolean hasSources( File dir )
 228  
     {
 229  279
         boolean found = false;
 230  279
         if ( dir.exists() && dir.isDirectory() )
 231  
         {
 232  279
             File[] files = dir.listFiles();
 233  684
             for ( int i = 0; i < files.length && !found; i++ )
 234  
             {
 235  405
                 File currentFile = files[i];
 236  405
                 if ( currentFile.isFile() && currentFile.getName().endsWith( ".java" ) )
 237  
                 {
 238  11
                     found = true;
 239  
                 }
 240  394
                 else if ( currentFile.isDirectory() )
 241  
                 {
 242  268
                     boolean hasSources = hasSources( currentFile );
 243  268
                     if ( hasSources )
 244  
                     {
 245  20
                         found = true;
 246  
                     }
 247  
                 }
 248  
             }
 249  
         }
 250  279
         return found;
 251  
     }
 252  
 
 253  
     /**
 254  
      * Creates the Xref for the Java files found in the given source directory and puts
 255  
      * them in the given destination directory.
 256  
      *
 257  
      * @param locale               The user locale to use for the Xref generation
 258  
      * @param destinationDirectory The output folder
 259  
      * @param sourceDirs           The source directories
 260  
      * @throws java.io.IOException
 261  
      * @throws org.apache.maven.jxr.JxrException
 262  
      *
 263  
      */
 264  
     private void createXref( Locale locale, String destinationDirectory, List sourceDirs )
 265  
         throws IOException, JxrException
 266  
     {
 267  8
         JXR jxr = new JXR();
 268  8
         jxr.setDest( destinationDirectory );
 269  8
         if ( StringUtils.isEmpty( inputEncoding ) )
 270  
         {
 271  0
             String platformEncoding = System.getProperty( "file.encoding" );
 272  0
             getLog().warn( "File encoding has not been set, using platform encoding " + platformEncoding
 273  
                            + ", i.e. build is platform dependent!" );
 274  
         }
 275  8
         jxr.setInputEncoding( inputEncoding );
 276  8
         jxr.setLocale( locale );
 277  8
         jxr.setLog( new PluginLogAdapter( getLog() ) );
 278  8
         jxr.setOutputEncoding( getOutputEncoding() );
 279  8
         jxr.setRevision( "HEAD" );
 280  8
         jxr.setJavadocLinkDir( getJavadocLocation() );
 281  
         // Set include/exclude patterns on the jxr instance
 282  8
         if ( excludes != null && !excludes.isEmpty() )
 283  
         {
 284  1
             jxr.setExcludes( (String[]) excludes.toArray( new String[0] ) );
 285  
         }
 286  8
         if ( includes != null && !includes.isEmpty() )
 287  
         {
 288  1
             jxr.setIncludes( (String[]) includes.toArray( new String[0] ) );
 289  
         }
 290  
 
 291  8
         jxr.xref( sourceDirs, templateDir, windowTitle, docTitle, getBottomText( project.getInceptionYear(), project
 292  
             .getOrganization() ) );
 293  
 
 294  
         // and finally copy the stylesheet
 295  7
         copyRequiredResources( destinationDirectory );
 296  7
     }
 297  
 
 298  
     /**
 299  
      * Get the bottom text to be displayed at the lower part of the generated JXR reports.
 300  
      *
 301  
      * @param inceptionYear the year when the project was started
 302  
      * @param organization the organization for the project
 303  
      * @return  a String that contains the bottom text to be displayed in the lower part of the generated JXR reports
 304  
      */
 305  
     private String getBottomText( String inceptionYear, Organization organization )
 306  
     {
 307  8
         int actualYear = Calendar.getInstance().get( Calendar.YEAR );
 308  8
         String year = String.valueOf( actualYear );
 309  
 
 310  8
         String bottom = StringUtils.replace( this.bottom, "{currentYear}", year );
 311  
 
 312  8
         if ( inceptionYear == null )
 313  
         {
 314  0
             bottom = StringUtils.replace( bottom, "{inceptionYear}-", "" );
 315  
         }
 316  
         else
 317  
         {
 318  8
             if ( inceptionYear.equals( year ) )
 319  
             {
 320  0
                 bottom = StringUtils.replace( bottom, "{inceptionYear}-", "" );
 321  
             }
 322  
             else
 323  
             {
 324  8
                 bottom = StringUtils.replace( bottom, "{inceptionYear}", inceptionYear );
 325  
             }
 326  
         }
 327  
 
 328  8
         if ( organization != null && StringUtils.isNotEmpty( organization.getName() ) )
 329  
         {
 330  0
             bottom = StringUtils.replace( bottom, "{projectOrganizationName}", organization.getName() );
 331  
         }
 332  
         else
 333  
         {
 334  8
             bottom = StringUtils.replace( bottom, " {projectOrganizationName}", "" );
 335  
         }
 336  
 
 337  8
         return bottom;
 338  
     }
 339  
 
 340  
     /**
 341  
      * Copy some required resources (like the stylesheet) to the
 342  
      * given directory
 343  
      *
 344  
      * @param dir the directory to copy the resources to
 345  
      */
 346  
     private void copyRequiredResources( String dir )
 347  
     {
 348  7
         File stylesheetFile = new File( stylesheet );
 349  7
         File destStylesheetFile = new File( dir, "stylesheet.css" );
 350  
 
 351  
         try
 352  
         {
 353  7
             if ( stylesheetFile.isAbsolute() )
 354  
             {
 355  0
                 FileUtils.copyFile( stylesheetFile, destStylesheetFile );
 356  
             }
 357  
             else
 358  
             {
 359  7
                 URL stylesheetUrl = this.getClass().getClassLoader().getResource( stylesheet );
 360  7
                 FileUtils.copyURLToFile( stylesheetUrl, destStylesheetFile );
 361  
             }
 362  
         }
 363  0
         catch ( IOException e )
 364  
         {
 365  0
             getLog().warn( "An error occured while copying the stylesheet to the target directory", e );
 366  7
         }
 367  
 
 368  7
     }
 369  
 
 370  
     /**
 371  
      * @see org.apache.maven.reporting.AbstractMavenReport#getSiteRenderer()
 372  
      */
 373  
     protected Renderer getSiteRenderer()
 374  
     {
 375  9
         return siteRenderer;
 376  
     }
 377  
 
 378  
     /**
 379  
      * @see org.apache.maven.reporting.AbstractMavenReport#getOutputDirectory()
 380  
      */
 381  
     protected String getOutputDirectory()
 382  
     {
 383  9
         return outputDirectory.getAbsolutePath();
 384  
     }
 385  
 
 386  
     /**
 387  
      * @see org.apache.maven.reporting.AbstractMavenReport#getProject()
 388  
      */
 389  
     public MavenProject getProject()
 390  
     {
 391  18
         return project;
 392  
     }
 393  
 
 394  
     /**
 395  
      * Returns the correct resource bundle according to the locale
 396  
      *
 397  
      * @param locale the locale of the user
 398  
      * @return the bundle corresponding to the locale
 399  
      */
 400  
     protected ResourceBundle getBundle( Locale locale )
 401  
     {
 402  1
         return ResourceBundle.getBundle( "jxr-report", locale, this.getClass().getClassLoader() );
 403  
     }
 404  
 
 405  
     /**
 406  
      * @param sourceDirs
 407  
      * @return true if the report could be generated
 408  
      */
 409  
     protected boolean canGenerateReport( List sourceDirs )
 410  
     {
 411  9
         boolean canGenerate = !sourceDirs.isEmpty();
 412  
 
 413  9
         if ( aggregate && !project.isExecutionRoot() )
 414  
         {
 415  0
             canGenerate = false;
 416  
         }
 417  9
         return canGenerate;
 418  
     }
 419  
 
 420  
     /**
 421  
      * @see org.apache.maven.reporting.AbstractMavenReport#executeReport(java.util.Locale)
 422  
      */
 423  
     protected void executeReport( Locale locale )
 424  
         throws MavenReportException
 425  
     {
 426  9
         List sourceDirs = constructSourceDirs();
 427  9
         if ( canGenerateReport( sourceDirs ) )
 428  
         {
 429  
             // init some attributes -- TODO (javadoc)
 430  8
             init();
 431  
 
 432  
             try
 433  
             {
 434  8
                 createXref( locale, getDestinationDirectory(), sourceDirs );
 435  
             }
 436  1
             catch ( JxrException e )
 437  
             {
 438  1
                 throw new MavenReportException( "Error while generating the HTML source code of the projet.", e );
 439  
             }
 440  0
             catch ( IOException e )
 441  
             {
 442  0
                 throw new MavenReportException( "Error while generating the HTML source code of the projet.", e );
 443  7
             }
 444  
         }
 445  8
     }
 446  
 
 447  
     /**
 448  
      * Gets the list of the source directories to be included in the JXR report generation
 449  
      *
 450  
      * @return a List of the source directories whose contents will be included in the JXR report generation
 451  
      */
 452  
     protected List constructSourceDirs()
 453  
     {
 454  9
         List sourceDirs = new ArrayList( getSourceRoots() );
 455  9
         if ( aggregate )
 456  
         {
 457  1
             for ( Iterator i = reactorProjects.iterator(); i.hasNext(); )
 458  
             {
 459  2
                 MavenProject project = (MavenProject) i.next();
 460  
 
 461  2
                 if ( "java".equals( project.getArtifact().getArtifactHandler().getLanguage() ) )
 462  
                 {
 463  2
                     sourceDirs.addAll( getSourceRoots( project ) );
 464  
                 }
 465  2
             }
 466  
         }
 467  
 
 468  9
         sourceDirs = pruneSourceDirs( sourceDirs );
 469  9
         return sourceDirs;
 470  
     }
 471  
 
 472  
     /**
 473  
      * @see org.apache.maven.reporting.AbstractMavenReport#canGenerateReport()
 474  
      */
 475  
     public boolean canGenerateReport()
 476  
     {
 477  0
         return canGenerateReport( constructSourceDirs() );
 478  
     }
 479  
 
 480  
     /**
 481  
      * @see org.apache.maven.reporting.AbstractMavenReport#isExternalReport()
 482  
      */
 483  
     public boolean isExternalReport()
 484  
     {
 485  0
         return true;
 486  
     }
 487  
 
 488  
     /**
 489  
      * @return a String that contains the location of the javadocs
 490  
      */
 491  
     private String getJavadocLocation()
 492  
         throws IOException
 493  
     {
 494  8
         String location = null;
 495  8
         if ( linkJavadoc )
 496  
         {
 497  
             // We don't need to do the whole translation thing like normal, because JXR does it internally.
 498  
             // It probably shouldn't.
 499  5
             if ( getJavadocDir().exists() )
 500  
             {
 501  
                 // XRef was already generated by manual execution of a lifecycle binding
 502  2
                 location = getJavadocDir().getAbsolutePath();
 503  
             }
 504  
             else
 505  
             {
 506  
                 // Not yet generated - check if the report is on its way
 507  
 
 508  
                 // Special case: using the site:stage goal
 509  3
                 String stagingDirectory = System.getProperty( "stagingDirectory" );
 510  
 
 511  3
                 if ( StringUtils.isNotEmpty( stagingDirectory ) )
 512  
                 {
 513  0
                     String javadocDestDir = getJavadocDir().getName();
 514  0
                     boolean javadocAggregate = Boolean
 515  
                         .valueOf( JxrReportUtil.getMavenJavadocPluginBasicOption( project, "aggregate", "false" ) )
 516  
                         .booleanValue();
 517  
 
 518  0
                     String structureProject = JxrReportUtil.getStructure( project, false );
 519  
 
 520  0
                     if ( aggregate && javadocAggregate )
 521  
                     {
 522  0
                         File outputDirectory = new File( stagingDirectory, structureProject );
 523  0
                         location = outputDirectory + "/" + javadocDestDir;
 524  
                     }
 525  0
                     if ( !aggregate && javadocAggregate )
 526  
                     {
 527  0
                         location = stagingDirectory + "/" + javadocDestDir;
 528  
 
 529  0
                         String hierarchy = project.getName();
 530  
 
 531  0
                         MavenProject parent = project.getParent();
 532  0
                         while ( parent != null )
 533  
                         {
 534  0
                             hierarchy = parent.getName();
 535  0
                             parent = parent.getParent();
 536  
                         }
 537  0
                         File outputDirectory = new File( stagingDirectory, hierarchy );
 538  0
                         location = outputDirectory + "/" + javadocDestDir;
 539  
                     }
 540  0
                     if ( aggregate && !javadocAggregate )
 541  
                     {
 542  0
                         getLog().warn(
 543  
                                        "The JXR plugin is configured to build an aggregated report at the root, "
 544  
                                            + "not the Javadoc plugin." );
 545  
                     }
 546  0
                     if ( !aggregate && !javadocAggregate )
 547  
                     {
 548  0
                         location = stagingDirectory + "/" + structureProject + "/" + javadocDestDir;
 549  
                     }
 550  0
                 }
 551  
                 else
 552  
                 {
 553  3
                     location = getJavadocDir().getAbsolutePath();
 554  
                 }
 555  
             }
 556  
 
 557  5
             if ( location == null )
 558  
             {
 559  0
                 getLog().warn( "Unable to locate Javadoc to link to - DISABLED" );
 560  
             }
 561  
         }
 562  
 
 563  8
         return location;
 564  
     }
 565  
 
 566  
     /**
 567  
      * Abstract method that returns the target directory where the generated JXR reports will be put.
 568  
      *
 569  
      * @return  a String that contains the target directory name
 570  
      */
 571  
     protected abstract String getDestinationDirectory();
 572  
 
 573  
     /**
 574  
      * Abstract method that returns the specified source directories that will be included in the JXR report generation.
 575  
      *
 576  
      * @return a List of the source directories
 577  
      */
 578  
     protected abstract List getSourceRoots();
 579  
 
 580  
     /**
 581  
      * Abstract method that returns the compile source directories of the specified project that will be included in the
 582  
      * JXR report generation
 583  
      *
 584  
      * @param project the MavenProject where the JXR report plugin will be executed
 585  
      * @return a List of the source directories
 586  
      */
 587  
     protected abstract List getSourceRoots( MavenProject project );
 588  
 
 589  
     /**
 590  
      * Abstract method that returns the directory of the javadoc files.
 591  
      *
 592  
      * @return a File for the directory of the javadocs
 593  
      */
 594  
     protected abstract File getJavadocDir();
 595  
 }