Coverage Report - org.apache.maven.report.projectinfo.dependencies.renderer.DependenciesRenderer
 
Classes in this File Line Coverage Branch Coverage Complexity
DependenciesRenderer
45%
247/548
30%
49/164
4,024
DependenciesRenderer$1
100%
6/6
50%
1/2
4,024
DependenciesRenderer$2
12%
1/8
0%
0/8
4,024
DependenciesRenderer$FileDecimalFormat
25%
4/16
0%
0/4
4,024
DependenciesRenderer$TotalCell
0%
0/57
0%
0/32
4,024
 
 1  
 package org.apache.maven.report.projectinfo.dependencies.renderer;
 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.security.NoSuchAlgorithmException;
 26  
 import java.security.SecureRandom;
 27  
 import java.text.DecimalFormat;
 28  
 import java.text.DecimalFormatSymbols;
 29  
 import java.text.FieldPosition;
 30  
 import java.util.ArrayList;
 31  
 import java.util.Collections;
 32  
 import java.util.Comparator;
 33  
 import java.util.HashMap;
 34  
 import java.util.HashSet;
 35  
 import java.util.Iterator;
 36  
 import java.util.List;
 37  
 import java.util.Locale;
 38  
 import java.util.Map;
 39  
 import java.util.Set;
 40  
 import java.util.SortedSet;
 41  
 import java.util.TreeSet;
 42  
 
 43  
 import org.apache.maven.artifact.Artifact;
 44  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 45  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 46  
 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
 47  
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 48  
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 49  
 import org.apache.maven.doxia.parser.Parser;
 50  
 import org.apache.maven.doxia.sink.Sink;
 51  
 import org.apache.maven.model.License;
 52  
 import org.apache.maven.plugin.logging.Log;
 53  
 import org.apache.maven.project.MavenProject;
 54  
 import org.apache.maven.project.MavenProjectBuilder;
 55  
 import org.apache.maven.project.ProjectBuildingException;
 56  
 import org.apache.maven.report.projectinfo.ProjectInfoReportUtils;
 57  
 import org.apache.maven.report.projectinfo.dependencies.Dependencies;
 58  
 import org.apache.maven.report.projectinfo.dependencies.DependenciesReportConfiguration;
 59  
 import org.apache.maven.report.projectinfo.dependencies.RepositoryUtils;
 60  
 import org.apache.maven.reporting.AbstractMavenReportRenderer;
 61  
 import org.apache.maven.settings.Settings;
 62  
 import org.apache.maven.shared.dependency.tree.DependencyNode;
 63  
 import org.apache.maven.shared.jar.JarData;
 64  
 import org.codehaus.plexus.i18n.I18N;
 65  
 import org.codehaus.plexus.util.StringUtils;
 66  
 
 67  
 /**
 68  
  * Renderer the dependencies report.
 69  
  *
 70  
  * @version $Id: DependenciesRenderer.java 679796 2008-07-25 13:14:34Z vsiveton $
 71  
  * @since 2.1
 72  
  */
 73  
 public class DependenciesRenderer
 74  
     extends AbstractMavenReportRenderer
 75  
 {
 76  
     /** URL for the 'icon_info_sml.gif' image */
 77  
     private static final String IMG_INFO_URL = "./images/icon_info_sml.gif";
 78  
 
 79  
     /** URL for the 'close.gif' image */
 80  
     private static final String IMG_CLOSE_URL = "./images/close.gif";
 81  
 
 82  
     /** Random used to generate a UID */
 83  
     private static final SecureRandom RANDOM;
 84  
 
 85  
     /** Used to format decimal values in the "Dependency File Details" table */
 86  1
     protected static final DecimalFormat DEFAULT_DECIMAL_FORMAT = new DecimalFormat( "#,##0" );
 87  
 
 88  1
     private static final Set JAR_SUBTYPE = new HashSet();
 89  
 
 90  
     /**
 91  
      * An HTML script tag with the Javascript used by the dependencies report.
 92  
      */
 93  
     private static final String JAVASCRIPT;
 94  
 
 95  
     private final DependencyNode dependencyTreeNode;
 96  
 
 97  
     private final Dependencies dependencies;
 98  
 
 99  
     private final DependenciesReportConfiguration configuration;
 100  
 
 101  
     private final Locale locale;
 102  
 
 103  
     private final I18N i18n;
 104  
 
 105  
     private final Log log;
 106  
 
 107  
     private final Settings settings;
 108  
 
 109  
     private final RepositoryUtils repoUtils;
 110  
 
 111  
     /** Used to format file length values */
 112  
     private final DecimalFormat fileLengthDecimalFormat;
 113  
 
 114  
     /**
 115  
      * Will be filled with license name / set of projects.
 116  
      */
 117  1
     private Map licenseMap = new HashMap()
 118  
     {
 119  
         /** {@inheritDoc} */
 120  1
         public Object put( Object key, Object value )
 121  
         {
 122  
             // handle multiple values as a set to avoid duplicates
 123  2
             SortedSet valueList = (SortedSet) get( key );
 124  2
             if ( valueList == null )
 125  
             {
 126  2
                 valueList = new TreeSet();
 127  
             }
 128  2
             valueList.add( value );
 129  2
             return super.put( key, valueList );
 130  
         }
 131  
     };
 132  
 
 133  
     private final ArtifactFactory artifactFactory;
 134  
 
 135  
     private final MavenProjectBuilder mavenProjectBuilder;
 136  
 
 137  
     private final List remoteRepositories;
 138  
 
 139  
     private final ArtifactRepository localRepository;
 140  
 
 141  
     static
 142  
     {
 143  1
         JAR_SUBTYPE.add( "jar" );
 144  1
         JAR_SUBTYPE.add( "war" );
 145  1
         JAR_SUBTYPE.add( "ear" );
 146  1
         JAR_SUBTYPE.add( "sar" );
 147  1
         JAR_SUBTYPE.add( "rar" );
 148  1
         JAR_SUBTYPE.add( "par" );
 149  1
         JAR_SUBTYPE.add( "ejb" );
 150  
 
 151  
         try
 152  
         {
 153  1
             RANDOM = SecureRandom.getInstance( "SHA1PRNG" );
 154  
         }
 155  0
         catch ( NoSuchAlgorithmException e )
 156  
         {
 157  0
             throw new RuntimeException( e );
 158  1
         }
 159  
 
 160  1
         StringBuffer sb = new StringBuffer();
 161  1
         sb.append( "<script language=\"javascript\" type=\"text/javascript\">" ).append( "\n" );
 162  1
         sb.append( "      function toggleDependencyDetail( divId, imgId )" ).append( "\n" );
 163  1
         sb.append( "      {" ).append( "\n" );
 164  1
         sb.append( "        var div = document.getElementById( divId );" ).append( "\n" );
 165  1
         sb.append( "        var img = document.getElementById( imgId );" ).append( "\n" );
 166  1
         sb.append( "        if( div.style.display == '' )" ).append( "\n" );
 167  1
         sb.append( "        {" ).append( "\n" );
 168  1
         sb.append( "          div.style.display = 'none';" ).append( "\n" );
 169  1
         sb.append( "          img.src='" + IMG_INFO_URL + "';" ).append( "\n" );
 170  1
         sb.append( "        }" ).append( "\n" );
 171  1
         sb.append( "        else" ).append( "\n" );
 172  1
         sb.append( "        {" ).append( "\n" );
 173  1
         sb.append( "          div.style.display = '';" ).append( "\n" );
 174  1
         sb.append( "          img.src='" + IMG_CLOSE_URL + "';" ).append( "\n" );
 175  1
         sb.append( "        }" ).append( "\n" );
 176  1
         sb.append( "      }" ).append( "\n" );
 177  1
         sb.append( "</script>" ).append( "\n" );
 178  1
         JAVASCRIPT = sb.toString();
 179  1
     }
 180  
 
 181  
     /**
 182  
      * Default constructor.
 183  
      *
 184  
      * @param sink
 185  
      * @param locale
 186  
      * @param i18n
 187  
      * @param log
 188  
      * @param settings
 189  
      * @param dependencies
 190  
      * @param dependencyTreeNode
 191  
      * @param config
 192  
      * @param repoUtils
 193  
      * @param artifactFactory
 194  
      * @param mavenProjectBuilder
 195  
      * @param remoteRepositories
 196  
      * @param localRepository
 197  
      */
 198  
     public DependenciesRenderer( Sink sink, Locale locale, I18N i18n, Log log, Settings settings,
 199  
                                  Dependencies dependencies, DependencyNode dependencyTreeNode,
 200  
                                  DependenciesReportConfiguration config, RepositoryUtils repoUtils,
 201  
                                  ArtifactFactory artifactFactory, MavenProjectBuilder mavenProjectBuilder,
 202  
                                  List remoteRepositories, ArtifactRepository localRepository )
 203  
     {
 204  1
         super( sink );
 205  
 
 206  1
         this.locale = locale;
 207  1
         this.i18n = i18n;
 208  1
         this.log = log;
 209  1
         this.settings = settings;
 210  1
         this.dependencies = dependencies;
 211  1
         this.dependencyTreeNode = dependencyTreeNode;
 212  1
         this.repoUtils = repoUtils;
 213  1
         this.configuration = config;
 214  1
         this.artifactFactory = artifactFactory;
 215  1
         this.mavenProjectBuilder = mavenProjectBuilder;
 216  1
         this.remoteRepositories = remoteRepositories;
 217  1
         this.localRepository = localRepository;
 218  
 
 219  
         // Using the right set of symbols depending of the locale
 220  1
         DEFAULT_DECIMAL_FORMAT.setDecimalFormatSymbols( new DecimalFormatSymbols( locale ) );
 221  
 
 222  1
         this.fileLengthDecimalFormat = new FileDecimalFormat( i18n, locale );
 223  1
         this.fileLengthDecimalFormat.setDecimalFormatSymbols( new DecimalFormatSymbols( locale ) );
 224  1
     }
 225  
 
 226  
     // ----------------------------------------------------------------------
 227  
     // Public methods
 228  
     // ----------------------------------------------------------------------
 229  
 
 230  
     /** {@inheritDoc} */
 231  
     public String getTitle()
 232  
     {
 233  2
         return getReportString( "report.dependencies.title" );
 234  
     }
 235  
 
 236  
     /** {@inheritDoc} */
 237  
     public void renderBody()
 238  
     {
 239  
         // Dependencies report
 240  
 
 241  1
         if ( !dependencies.hasDependencies() )
 242  
         {
 243  0
             startSection( getTitle() );
 244  
 
 245  
             // TODO: should the report just be excluded?
 246  0
             paragraph( getReportString( "report.dependencies.nolist" ) );
 247  
 
 248  0
             endSection();
 249  
 
 250  0
             return;
 251  
         }
 252  
 
 253  
         // === Section: Project Dependencies.
 254  1
         renderSectionProjectDependencies();
 255  
 
 256  
         // === Section: Project Transitive Dependencies.
 257  1
         renderSectionProjectTransitiveDependencies();
 258  
 
 259  
         // === Section: Project Dependency Graph.
 260  1
         renderSectionProjectDependencyGraph();
 261  
 
 262  
         // === Section: Licenses
 263  1
         renderSectionDependencyLicenseListing();
 264  
 
 265  1
         if ( configuration.getDependencyDetailsEnabled() )
 266  
         {
 267  
             // === Section: Dependency File Details.
 268  0
             renderSectionDependencyFileDetails();
 269  
         }
 270  
 
 271  1
         if ( configuration.getDependencyLocationsEnabled() )
 272  
         {
 273  
             // === Section: Dependency Repository Locations.
 274  0
             renderSectionDependencyRepositoryLocations();
 275  
         }
 276  1
     }
 277  
 
 278  
     // ----------------------------------------------------------------------
 279  
     // Private methods
 280  
     // ----------------------------------------------------------------------
 281  
 
 282  
     /**
 283  
      * @param withClassifier <code>true</code> to include the classifier column, <code>false</code> otherwise.
 284  
      * @param withOptional <code>true</code> to include the optional column, <code>false</code> otherwise.
 285  
      * @return the dependency table header with/without classifier/optional column
 286  
      * @see #renderArtifactRow(Artifact, boolean, boolean)
 287  
      */
 288  
     private String[] getDependencyTableHeader( boolean withClassifier, boolean withOptional )
 289  
     {
 290  1
         String groupId = getReportString( "report.dependencies.column.groupId" );
 291  1
         String artifactId = getReportString( "report.dependencies.column.artifactId" );
 292  1
         String version = getReportString( "report.dependencies.column.version" );
 293  1
         String classifier = getReportString( "report.dependencies.column.classifier" );
 294  1
         String type = getReportString( "report.dependencies.column.type" );
 295  1
         String optional = getReportString( "report.dependencies.column.optional" );
 296  
 
 297  1
         if ( withClassifier )
 298  
         {
 299  0
             if ( withOptional )
 300  
             {
 301  0
                 return new String[] { groupId, artifactId, version, classifier, type, optional };
 302  
             }
 303  
 
 304  0
             return new String[] { groupId, artifactId, version, classifier, type };
 305  
         }
 306  
 
 307  1
         if ( withOptional )
 308  
         {
 309  0
             return new String[] { groupId, artifactId, version, type, optional };
 310  
         }
 311  
 
 312  1
         return new String[] { groupId, artifactId, version, type };
 313  
     }
 314  
 
 315  
     private void renderSectionProjectDependencies()
 316  
     {
 317  1
         startSection( getTitle() );
 318  
 
 319  
         // collect dependencies by scope
 320  1
         Map dependenciesByScope = dependencies.getDependenciesByScope( false );
 321  
 
 322  1
         renderDependenciesForAllScopes( dependenciesByScope );
 323  
 
 324  1
         endSection();
 325  1
     }
 326  
 
 327  
     /**
 328  
      * @param dependenciesByScope map with supported scopes as key and a list of <code>Artifact</code> as values.
 329  
      * @see Artifact#SCOPE_COMPILE
 330  
      * @see Artifact#SCOPE_PROVIDED
 331  
      * @see Artifact#SCOPE_RUNTIME
 332  
      * @see Artifact#SCOPE_SYSTEM
 333  
      * @see Artifact#SCOPE_TEST
 334  
      */
 335  
     private void renderDependenciesForAllScopes( Map dependenciesByScope )
 336  
     {
 337  1
         renderDependenciesForScope( Artifact.SCOPE_COMPILE, (List) dependenciesByScope.get( Artifact.SCOPE_COMPILE ) );
 338  1
         renderDependenciesForScope( Artifact.SCOPE_RUNTIME, (List) dependenciesByScope.get( Artifact.SCOPE_RUNTIME ) );
 339  1
         renderDependenciesForScope( Artifact.SCOPE_TEST, (List) dependenciesByScope.get( Artifact.SCOPE_TEST ) );
 340  1
         renderDependenciesForScope( Artifact.SCOPE_PROVIDED,
 341  
                                     (List) dependenciesByScope.get( Artifact.SCOPE_PROVIDED ) );
 342  1
         renderDependenciesForScope( Artifact.SCOPE_SYSTEM, (List) dependenciesByScope.get( Artifact.SCOPE_SYSTEM ) );
 343  1
     }
 344  
 
 345  
     private void renderSectionProjectTransitiveDependencies()
 346  
     {
 347  1
         Map dependenciesByScope = dependencies.getDependenciesByScope( true );
 348  
 
 349  1
         startSection( getReportString( "report.transitivedependencies.title" ) );
 350  
 
 351  1
         if ( dependenciesByScope.values().isEmpty() )
 352  
         {
 353  1
             paragraph( getReportString( "report.transitivedependencies.nolist" ) );
 354  
         }
 355  
         else
 356  
         {
 357  0
             paragraph( getReportString( "report.transitivedependencies.intro" ) );
 358  
 
 359  0
             renderDependenciesForAllScopes( dependenciesByScope );
 360  
         }
 361  
 
 362  1
         endSection();
 363  1
     }
 364  
 
 365  
     private void renderSectionProjectDependencyGraph()
 366  
     {
 367  1
         startSection( getReportString( "report.dependencies.graph.title" ) );
 368  
 
 369  
         // === SubSection: Dependency Tree
 370  1
         renderSectionDependencyTree();
 371  
 
 372  1
         endSection();
 373  1
     }
 374  
 
 375  
     private void renderSectionDependencyTree()
 376  
     {
 377  1
         sink.rawText( JAVASCRIPT );
 378  
 
 379  
         // for Dependencies Graph Tree
 380  1
         startSection( getReportString( "report.dependencies.graph.tree.title" ) );
 381  
 
 382  1
         sink.list();
 383  1
         printDependencyListing( dependencyTreeNode );
 384  1
         sink.list_();
 385  
 
 386  1
         endSection();
 387  1
     }
 388  
 
 389  
     private void renderSectionDependencyFileDetails()
 390  
     {
 391  0
         startSection( getReportString( "report.dependencies.file.details.title" ) );
 392  
 
 393  0
         List alldeps = dependencies.getAllDependencies();
 394  0
         Collections.sort( alldeps, getArtifactComparator() );
 395  
 
 396  
         // i18n
 397  0
         String filename = getReportString( "report.dependencies.file.details.column.file" );
 398  0
         String size = getReportString( "report.dependencies.file.details.column.size" );
 399  0
         String entries = getReportString( "report.dependencies.file.details.column.entries" );
 400  0
         String classes = getReportString( "report.dependencies.file.details.column.classes" );
 401  0
         String packages = getReportString( "report.dependencies.file.details.column.packages" );
 402  0
         String jdkrev = getReportString( "report.dependencies.file.details.column.jdkrev" );
 403  0
         String debug = getReportString( "report.dependencies.file.details.column.debug" );
 404  0
         String sealed = getReportString( "report.dependencies.file.details.column.sealed" );
 405  
 
 406  0
         int[] justification =
 407  
             new int[] { Parser.JUSTIFY_LEFT, Parser.JUSTIFY_RIGHT, Parser.JUSTIFY_RIGHT, Parser.JUSTIFY_RIGHT,
 408  
                 Parser.JUSTIFY_RIGHT, Parser.JUSTIFY_CENTER, Parser.JUSTIFY_CENTER, Parser.JUSTIFY_CENTER };
 409  
 
 410  0
         startTable();
 411  
 
 412  0
         sink.tableRows( justification, true );
 413  
 
 414  0
         TotalCell totaldeps = new TotalCell( DEFAULT_DECIMAL_FORMAT );
 415  0
         TotalCell totaldepsize = new TotalCell( fileLengthDecimalFormat );
 416  0
         TotalCell totalentries = new TotalCell( DEFAULT_DECIMAL_FORMAT );
 417  0
         TotalCell totalclasses = new TotalCell( DEFAULT_DECIMAL_FORMAT );
 418  0
         TotalCell totalpackages = new TotalCell( DEFAULT_DECIMAL_FORMAT );
 419  0
         double highestjdk = 0.0;
 420  0
         TotalCell totaldebug = new TotalCell( DEFAULT_DECIMAL_FORMAT );
 421  0
         TotalCell totalsealed = new TotalCell( DEFAULT_DECIMAL_FORMAT );
 422  
 
 423  0
         boolean hasSealed = hasSealed( alldeps );
 424  
 
 425  
         // Table header
 426  
         String[] tableHeader;
 427  0
         if ( hasSealed )
 428  
         {
 429  0
             tableHeader = new String[] { filename, size, entries, classes, packages, jdkrev, debug, sealed };
 430  
         }
 431  
         else
 432  
         {
 433  0
             tableHeader = new String[] { filename, size, entries, classes, packages, jdkrev, debug };
 434  
         }
 435  0
         tableHeader( tableHeader );
 436  
 
 437  
         // Table rows
 438  0
         for ( Iterator it = alldeps.iterator(); it.hasNext(); )
 439  
         {
 440  0
             Artifact artifact = (Artifact) it.next();
 441  
 
 442  0
             if ( artifact.getFile() == null )
 443  
             {
 444  0
                 log.error( "Artifact: " + artifact.getId() + " has no file." );
 445  0
                 continue;
 446  
             }
 447  
 
 448  0
             File artifactFile = artifact.getFile();
 449  
 
 450  0
             totaldeps.incrementTotal( artifact.getScope() );
 451  0
             totaldepsize.addTotal( artifactFile.length(), artifact.getScope() );
 452  
 
 453  0
             if ( JAR_SUBTYPE.contains( artifact.getType().toLowerCase() ) )
 454  
             {
 455  
                 try
 456  
                 {
 457  0
                     JarData jarDetails = dependencies.getJarDependencyDetails( artifact );
 458  
 
 459  0
                     String debugstr = "release";
 460  0
                     if ( jarDetails.isDebugPresent() )
 461  
                     {
 462  0
                         debugstr = "debug";
 463  0
                         totaldebug.incrementTotal( artifact.getScope() );
 464  
                     }
 465  
 
 466  0
                     totalentries.addTotal( jarDetails.getNumEntries(), artifact.getScope() );
 467  0
                     totalclasses.addTotal( jarDetails.getNumClasses(), artifact.getScope() );
 468  0
                     totalpackages.addTotal( jarDetails.getNumPackages(), artifact.getScope() );
 469  
 
 470  
                     try
 471  
                     {
 472  0
                         if ( jarDetails.getJdkRevision() != null )
 473  
                         {
 474  0
                             highestjdk = Math.max( highestjdk, Double.parseDouble( jarDetails.getJdkRevision() ) );
 475  
                         }
 476  
                     }
 477  0
                     catch ( NumberFormatException e )
 478  
                     {
 479  
                         // ignore
 480  0
                     }
 481  
 
 482  0
                     String sealedstr = "";
 483  0
                     if ( jarDetails.isSealed() )
 484  
                     {
 485  0
                         sealedstr = "sealed";
 486  0
                         totalsealed.incrementTotal( artifact.getScope() );
 487  
                     }
 488  
 
 489  0
                     tableRow( hasSealed, new String[] { artifactFile.getName(),
 490  
                         fileLengthDecimalFormat.format( artifactFile.length() ),
 491  
                         DEFAULT_DECIMAL_FORMAT.format( jarDetails.getNumEntries() ),
 492  
                         DEFAULT_DECIMAL_FORMAT.format( jarDetails.getNumClasses() ),
 493  
                         DEFAULT_DECIMAL_FORMAT.format( jarDetails.getNumPackages() ), jarDetails.getJdkRevision(),
 494  
                         debugstr, sealedstr } );
 495  
                 }
 496  0
                 catch ( IOException e )
 497  
                 {
 498  0
                     createExceptionInfoTableRow( artifact, artifactFile, e, hasSealed );
 499  0
                 }
 500  
             }
 501  
             else
 502  
             {
 503  0
                 tableRow( hasSealed, new String[] { artifactFile.getName(),
 504  
                     fileLengthDecimalFormat.format( artifactFile.length() ), "", "", "", "", "", "" } );
 505  
             }
 506  0
         }
 507  
 
 508  
         // Total raws
 509  0
         tableHeader[0] = getReportString( "report.dependencies.file.details.total" );
 510  0
         tableHeader( tableHeader );
 511  
 
 512  0
         justification[0] = Parser.JUSTIFY_RIGHT;
 513  0
         justification[6] = Parser.JUSTIFY_RIGHT;
 514  
 
 515  0
         for ( int i = -1; i < TotalCell.SCOPES_COUNT; i++ )
 516  
         {
 517  0
             if ( totaldeps.getTotal( i ) > 0 )
 518  
             {
 519  0
                 tableRow( hasSealed, new String[] { totaldeps.getTotalString( i ), totaldepsize.getTotalString( i ),
 520  
                     totalentries.getTotalString( i ), totalclasses.getTotalString( i ),
 521  
                     totalpackages.getTotalString( i ), ( i < 0 ) ? String.valueOf( highestjdk ) : "",
 522  
                     totaldebug.getTotalString( i ), totalsealed.getTotalString( i ) } );
 523  
             }
 524  
         }
 525  
 
 526  0
         sink.tableRows_();
 527  
 
 528  0
         endTable();
 529  0
         endSection();
 530  0
     }
 531  
 
 532  
     private void tableRow( boolean fullRow, String[] content )
 533  
     {
 534  1
         sink.tableRow();
 535  
 
 536  1
         int count = fullRow ? content.length : ( content.length - 1 );
 537  
 
 538  5
         for ( int i = 0; i < count; i++ )
 539  
         {
 540  4
             tableCell( content[i] );
 541  
         }
 542  
 
 543  1
         sink.tableRow_();
 544  1
     }
 545  
 
 546  
     private void createExceptionInfoTableRow( Artifact artifact, File artifactFile, Exception e, boolean hasSealed )
 547  
     {
 548  0
         tableRow( hasSealed, new String[] { artifact.getId(), artifactFile.getAbsolutePath(), e.getMessage(), "", "",
 549  
             "", "", "" } );
 550  0
     }
 551  
 
 552  
     private void populateRepositoryMap( Map repos, List rowRepos )
 553  
     {
 554  0
         Iterator it = rowRepos.iterator();
 555  0
         while ( it.hasNext() )
 556  
         {
 557  0
             ArtifactRepository repo = (ArtifactRepository) it.next();
 558  
 
 559  0
             repos.put( repo.getId(), repo );
 560  0
         }
 561  0
     }
 562  
 
 563  
     private void blacklistRepositoryMap( Map repos, List repoUrlBlackListed )
 564  
     {
 565  0
         for ( Iterator it = repos.keySet().iterator(); it.hasNext(); )
 566  
         {
 567  0
             String key = (String) it.next();
 568  0
             ArtifactRepository repo = (ArtifactRepository) repos.get( key );
 569  
 
 570  
             // ping repo
 571  0
             if ( !repo.isBlacklisted() )
 572  
             {
 573  0
                 if ( !repoUrlBlackListed.contains( repo.getUrl() ) )
 574  
                 {
 575  
                     try
 576  
                     {
 577  0
                         URL repoUrl = new URL( repo.getUrl() );
 578  0
                         if ( ProjectInfoReportUtils.getInputStream( repoUrl, settings ) == null )
 579  
                         {
 580  0
                             log.warn( "The repository url '" + repoUrl + "' has no stream - Repository '"
 581  
                                 + repo.getId() + "' will be blacklisted." );
 582  0
                             repo.setBlacklisted( true );
 583  0
                             repoUrlBlackListed.add( repo.getUrl() );
 584  
                         }
 585  
                     }
 586  0
                     catch ( IOException e )
 587  
                     {
 588  0
                         log.warn( "The repository url '" + repo.getUrl() + "' is invalid - Repository '" + repo.getId()
 589  
                             + "' will be blacklisted." );
 590  0
                         repo.setBlacklisted( true );
 591  0
                         repoUrlBlackListed.add( repo.getUrl() );
 592  0
                     }
 593  
                 }
 594  
                 else
 595  
                 {
 596  0
                     repo.setBlacklisted( true );
 597  
                 }
 598  
             }
 599  
             else
 600  
             {
 601  0
                 repoUrlBlackListed.add( repo.getUrl() );
 602  
             }
 603  0
         }
 604  0
     }
 605  
 
 606  
     private void renderSectionDependencyRepositoryLocations()
 607  
     {
 608  0
         startSection( getReportString( "report.dependencies.repo.locations.title" ) );
 609  
 
 610  
         // Collect Alphabetical Dependencies
 611  0
         List alldeps = dependencies.getAllDependencies();
 612  0
         Collections.sort( alldeps, getArtifactComparator() );
 613  
 
 614  
         // Collect Repositories
 615  0
         Map repoMap = new HashMap();
 616  
 
 617  0
         populateRepositoryMap( repoMap, repoUtils.getRemoteArtifactRepositories() );
 618  0
         for ( Iterator it = alldeps.iterator(); it.hasNext(); )
 619  
         {
 620  0
             Artifact artifact = (Artifact) it.next();
 621  
             try
 622  
             {
 623  0
                 MavenProject artifactProject = repoUtils.getMavenProjectFromRepository( artifact );
 624  0
                 populateRepositoryMap( repoMap, artifactProject.getRemoteArtifactRepositories() );
 625  
             }
 626  0
             catch ( ProjectBuildingException e )
 627  
             {
 628  0
                 log.warn( "Unable to create Maven project from repository.", e );
 629  0
             }
 630  0
         }
 631  
 
 632  0
         List repoUrlBlackListed = new ArrayList();
 633  0
         blacklistRepositoryMap( repoMap, repoUrlBlackListed );
 634  
 
 635  
         // Render Repository List
 636  
 
 637  0
         printRepositories( repoMap, repoUrlBlackListed );
 638  
 
 639  
         // Render Artifacts locations
 640  
 
 641  0
         printArtifactsLocations( repoMap, alldeps );
 642  
 
 643  0
         endSection();
 644  0
     }
 645  
 
 646  
     private void renderSectionDependencyLicenseListing()
 647  
     {
 648  1
         startSection( getReportString( "report.dependencies.graph.tables.licenses" ) );
 649  1
         printGroupedLicenses();
 650  1
         endSection();
 651  1
     }
 652  
 
 653  
     private void renderDependenciesForScope( String scope, List artifacts )
 654  
     {
 655  5
         if ( artifacts != null )
 656  
         {
 657  1
             boolean withClassifier = hasClassifier( artifacts );
 658  1
             boolean withOptional = hasOptional( artifacts );
 659  1
             String[] tableHeader = getDependencyTableHeader( withClassifier, withOptional );
 660  
 
 661  
             // can't use straight artifact comparison because we want optional last
 662  1
             Collections.sort( artifacts, getArtifactComparator() );
 663  
 
 664  1
             startSection( scope );
 665  
 
 666  1
             paragraph( getReportString( "report.dependencies.intro." + scope ) );
 667  
 
 668  1
             startTable();
 669  1
             tableHeader( tableHeader );
 670  1
             for ( Iterator iterator = artifacts.iterator(); iterator.hasNext(); )
 671  
             {
 672  1
                 Artifact artifact = (Artifact) iterator.next();
 673  
 
 674  1
                 renderArtifactRow( artifact, withClassifier, withOptional );
 675  1
             }
 676  1
             endTable();
 677  
 
 678  1
             endSection();
 679  
         }
 680  5
     }
 681  
 
 682  
     private Comparator getArtifactComparator()
 683  
     {
 684  1
         return new Comparator()
 685  
         {
 686  1
             public int compare( Object o1, Object o2 )
 687  
             {
 688  0
                 Artifact a1 = (Artifact) o1;
 689  0
                 Artifact a2 = (Artifact) o2;
 690  
 
 691  
                 // put optional last
 692  0
                 if ( a1.isOptional() && !a2.isOptional() )
 693  
                 {
 694  0
                     return +1;
 695  
                 }
 696  0
                 else if ( !a1.isOptional() && a2.isOptional() )
 697  
                 {
 698  0
                     return -1;
 699  
                 }
 700  
                 else
 701  
                 {
 702  0
                     return a1.compareTo( a2 );
 703  
                 }
 704  
             }
 705  
         };
 706  
     }
 707  
 
 708  
     /**
 709  
      * @param artifact not null
 710  
      * @param withClassifier <code>true</code> to include the classifier column, <code>false</code> otherwise.
 711  
      * @param withOptional <code>true</code> to include the optional column, <code>false</code> otherwise.
 712  
      * @see #getDependencyTableHeader(boolean, boolean)
 713  
      */
 714  
     private void renderArtifactRow( Artifact artifact, boolean withClassifier, boolean withOptional )
 715  
     {
 716  1
         String isOptional =
 717  
             artifact.isOptional() ? getReportString( "report.dependencies.column.isOptional" )
 718  
                             : getReportString( "report.dependencies.column.isNotOptional" );
 719  
 
 720  1
         String url =
 721  
             ProjectInfoReportUtils.getArtifactUrl( artifactFactory, artifact, mavenProjectBuilder, remoteRepositories,
 722  
                                                    localRepository );
 723  1
         String artifactIdCell = ProjectInfoReportUtils.getArtifactIdCell( artifact.getArtifactId(), url );
 724  
 
 725  
         String content[];
 726  1
         if ( withClassifier )
 727  
         {
 728  0
             content =
 729  
                 new String[] { artifact.getGroupId(), artifactIdCell, artifact.getVersion(), artifact.getClassifier(),
 730  
                     artifact.getType(), isOptional };
 731  
         }
 732  
         else
 733  
         {
 734  1
             content =
 735  
                 new String[] { artifact.getGroupId(), artifactIdCell, artifact.getVersion(), artifact.getType(),
 736  
                     isOptional };
 737  
         }
 738  
 
 739  1
         tableRow( withOptional, content );
 740  1
     }
 741  
 
 742  
     private void printDependencyListing( DependencyNode node )
 743  
     {
 744  2
         Artifact artifact = node.getArtifact();
 745  2
         String id = artifact.getId();
 746  2
         String dependencyDetailId = getUUID();
 747  2
         String imgId = getUUID();
 748  
 
 749  2
         sink.listItem();
 750  
 
 751  2
         sink.paragraph();
 752  2
         sink.text( id + ( StringUtils.isNotEmpty( artifact.getScope() ) ? " (" + artifact.getScope() + ") " : " " ) );
 753  2
         sink.rawText( "<img id=\"" + imgId + "\" src=\"" + IMG_INFO_URL
 754  
             + "\" alt=\"Information\" onclick=\"toggleDependencyDetail( '" + dependencyDetailId + "', '" + imgId
 755  
             + "' );\" style=\"cursor: pointer;vertical-align:text-bottom;\"></img>" );
 756  2
         sink.paragraph_();
 757  
 
 758  2
         printDescriptionsAndURLs( node, dependencyDetailId );
 759  
 
 760  2
         if ( !node.getChildren().isEmpty() )
 761  
         {
 762  1
             boolean toBeIncluded = false;
 763  1
             List subList = new ArrayList();
 764  1
             for ( Iterator deps = node.getChildren().iterator(); deps.hasNext(); )
 765  
             {
 766  1
                 DependencyNode dep = (DependencyNode) deps.next();
 767  
 
 768  1
                 if ( !dependencies.getAllDependencies().contains( dep.getArtifact() ) )
 769  
                 {
 770  0
                     continue;
 771  
                 }
 772  
 
 773  1
                 subList.add( dep );
 774  1
                 toBeIncluded = true;
 775  1
             }
 776  
 
 777  1
             if ( toBeIncluded )
 778  
             {
 779  1
                 sink.list();
 780  1
                 for ( Iterator deps = subList.iterator(); deps.hasNext(); )
 781  
                 {
 782  1
                     DependencyNode dep = (DependencyNode) deps.next();
 783  
 
 784  1
                     printDependencyListing( dep );
 785  1
                 }
 786  1
                 sink.list_();
 787  
             }
 788  
         }
 789  
 
 790  2
         sink.listItem_();
 791  2
     }
 792  
 
 793  
     private void printDescriptionsAndURLs( DependencyNode node, String uid )
 794  
     {
 795  2
         Artifact artifact = node.getArtifact();
 796  2
         String id = artifact.getId();
 797  2
         String unknownLicenseMessage = getReportString( "report.dependencies.graph.tables.unknown" );
 798  
 
 799  2
         sink.rawText( "<div id=\"" + uid + "\" style=\"display:none\">" );
 800  
 
 801  2
         sink.table();
 802  
 
 803  2
         if ( !Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
 804  
         {
 805  
             try
 806  
             {
 807  2
                 MavenProject artifactProject = repoUtils.getMavenProjectFromRepository( artifact );
 808  2
                 String artifactDescription = artifactProject.getDescription();
 809  2
                 String artifactUrl = artifactProject.getUrl();
 810  2
                 String artifactName = artifactProject.getName();
 811  2
                 List licenses = artifactProject.getLicenses();
 812  
 
 813  2
                 sink.tableRow();
 814  2
                 sink.tableHeaderCell();
 815  2
                 sink.text( artifactName );
 816  2
                 sink.tableHeaderCell_();
 817  2
                 sink.tableRow_();
 818  
 
 819  2
                 sink.tableRow();
 820  2
                 sink.tableCell();
 821  
 
 822  2
                 sink.paragraph();
 823  2
                 sink.bold();
 824  2
                 sink.text( getReportString( "report.dependencies.column.description" ) + ": " );
 825  2
                 sink.bold_();
 826  2
                 if ( StringUtils.isNotEmpty( artifactDescription ) )
 827  
                 {
 828  1
                     sink.text( artifactDescription );
 829  
                 }
 830  
                 else
 831  
                 {
 832  1
                     sink.text( getReportString( "report.index.nodescription" ) );
 833  
                 }
 834  2
                 sink.paragraph_();
 835  
 
 836  2
                 if ( StringUtils.isNotEmpty( artifactUrl ) )
 837  
                 {
 838  1
                     sink.paragraph();
 839  1
                     sink.bold();
 840  1
                     sink.text( getReportString( "report.dependencies.column.url" ) + ": " );
 841  1
                     sink.bold_();
 842  1
                     if ( ProjectInfoReportUtils.isArtifactUrlValid( artifactUrl ) )
 843  
                     {
 844  1
                         sink.link( artifactUrl );
 845  1
                         sink.text( artifactUrl );
 846  1
                         sink.link_();
 847  
                     }
 848  
                     else
 849  
                     {
 850  0
                         sink.text( artifactUrl );
 851  
                     }
 852  1
                     sink.paragraph_();
 853  
                 }
 854  
 
 855  2
                 sink.paragraph();
 856  2
                 sink.bold();
 857  2
                 sink.text( getReportString( "report.license.title" ) + ": " );
 858  2
                 sink.bold_();
 859  2
                 if ( !licenses.isEmpty() )
 860  
                 {
 861  1
                     for ( Iterator iter = licenses.iterator(); iter.hasNext(); )
 862  
                     {
 863  1
                         License element = (License) iter.next();
 864  1
                         String licenseName = element.getName();
 865  1
                         String licenseUrl = element.getUrl();
 866  
 
 867  1
                         if ( licenseUrl != null )
 868  
                         {
 869  1
                             sink.link( licenseUrl );
 870  
                         }
 871  1
                         sink.text( licenseName );
 872  
 
 873  1
                         if ( licenseUrl != null )
 874  
                         {
 875  1
                             sink.link_();
 876  
                         }
 877  
 
 878  1
                         licenseMap.put( licenseName, artifactName );
 879  1
                     }
 880  
                 }
 881  
                 else
 882  
                 {
 883  1
                     sink.text( getReportString( "report.license.nolicense" ) );
 884  
 
 885  1
                     licenseMap.put( unknownLicenseMessage, artifactName );
 886  
                 }
 887  2
                 sink.paragraph_();
 888  
             }
 889  0
             catch ( ProjectBuildingException e )
 890  
             {
 891  0
                 log.error( "ProjectBuildingException error : ", e );
 892  2
             }
 893  
         }
 894  
         else
 895  
         {
 896  0
             sink.tableRow();
 897  0
             sink.tableHeaderCell();
 898  0
             sink.text( id );
 899  0
             sink.tableHeaderCell_();
 900  0
             sink.tableRow_();
 901  
 
 902  0
             sink.tableRow();
 903  0
             sink.tableCell();
 904  
 
 905  0
             sink.paragraph();
 906  0
             sink.bold();
 907  0
             sink.text( getReportString( "report.dependencies.column.description" ) + ": " );
 908  0
             sink.bold_();
 909  0
             sink.text( getReportString( "report.index.nodescription" ) );
 910  0
             sink.paragraph_();
 911  
 
 912  0
             if ( artifact.getFile() != null )
 913  
             {
 914  0
                 sink.paragraph();
 915  0
                 sink.bold();
 916  0
                 sink.text( getReportString( "report.dependencies.column.url" ) + ": " );
 917  0
                 sink.bold_();
 918  0
                 sink.text( artifact.getFile().getAbsolutePath() );
 919  0
                 sink.paragraph_();
 920  
             }
 921  
         }
 922  
 
 923  2
         sink.tableCell_();
 924  2
         sink.tableRow_();
 925  
 
 926  2
         sink.table_();
 927  
 
 928  2
         sink.rawText( "</div>" );
 929  2
     }
 930  
 
 931  
     private void printGroupedLicenses()
 932  
     {
 933  1
         for ( Iterator iter = licenseMap.keySet().iterator(); iter.hasNext(); )
 934  
         {
 935  2
             String licenseName = (String) iter.next();
 936  2
             sink.paragraph();
 937  2
             sink.bold();
 938  2
             if ( StringUtils.isEmpty( licenseName ) )
 939  
             {
 940  0
                 sink.text( i18n.getString( "project-info-report", locale, "report.dependencies.unamed" ) );
 941  
             }
 942  
             else
 943  
             {
 944  2
                 sink.text( licenseName );
 945  
             }
 946  2
             sink.text( ": " );
 947  2
             sink.bold_();
 948  
 
 949  2
             SortedSet projects = (SortedSet) licenseMap.get( licenseName );
 950  
 
 951  2
             for ( Iterator iterator = projects.iterator(); iterator.hasNext(); )
 952  
             {
 953  2
                 String projectName = (String) iterator.next();
 954  2
                 sink.text( projectName );
 955  2
                 if ( iterator.hasNext() )
 956  
                 {
 957  0
                     sink.text( ", " );
 958  
                 }
 959  2
             }
 960  
 
 961  2
             sink.paragraph_();
 962  2
         }
 963  1
     }
 964  
 
 965  
     private void printRepositories( Map repoMap, List repoUrlBlackListed )
 966  
     {
 967  
         // i18n
 968  0
         String repoid = getReportString( "report.dependencies.repo.locations.column.repoid" );
 969  0
         String url = getReportString( "report.dependencies.repo.locations.column.url" );
 970  0
         String release = getReportString( "report.dependencies.repo.locations.column.release" );
 971  0
         String snapshot = getReportString( "report.dependencies.repo.locations.column.snapshot" );
 972  0
         String blacklisted = getReportString( "report.dependencies.repo.locations.column.blacklisted" );
 973  0
         String releaseEnabled = getReportString( "report.dependencies.repo.locations.cell.release.enabled" );
 974  0
         String releaseDisabled = getReportString( "report.dependencies.repo.locations.cell.release.disabled" );
 975  0
         String snapshotEnabled = getReportString( "report.dependencies.repo.locations.cell.snapshot.enabled" );
 976  0
         String snapshotDisabled = getReportString( "report.dependencies.repo.locations.cell.snapshot.disabled" );
 977  0
         String blacklistedEnabled = getReportString( "report.dependencies.repo.locations.cell.blacklisted.enabled" );
 978  0
         String blacklistedDisabled = getReportString( "report.dependencies.repo.locations.cell.blacklisted.disabled" );
 979  
 
 980  0
         startTable();
 981  
 
 982  
         // Table header
 983  
 
 984  
         String[] tableHeader;
 985  
         int[] justificationRepo;
 986  0
         if ( repoUrlBlackListed.isEmpty() )
 987  
         {
 988  0
             tableHeader = new String[] { repoid, url, release, snapshot };
 989  0
             justificationRepo =
 990  
                 new int[] { Parser.JUSTIFY_LEFT, Parser.JUSTIFY_LEFT, Parser.JUSTIFY_CENTER, Parser.JUSTIFY_CENTER };
 991  
         }
 992  
         else
 993  
         {
 994  0
             tableHeader = new String[] { repoid, url, release, snapshot, blacklisted };
 995  0
             justificationRepo =
 996  
                 new int[] { Parser.JUSTIFY_LEFT, Parser.JUSTIFY_LEFT, Parser.JUSTIFY_CENTER, Parser.JUSTIFY_CENTER,
 997  
                     Parser.JUSTIFY_CENTER };
 998  
         }
 999  
 
 1000  0
         sink.tableRows( justificationRepo, true );
 1001  
 
 1002  0
         tableHeader( tableHeader );
 1003  
 
 1004  
         // Table rows
 1005  
 
 1006  0
         for ( Iterator it = repoMap.keySet().iterator(); it.hasNext(); )
 1007  
         {
 1008  0
             String key = (String) it.next();
 1009  0
             ArtifactRepository repo = (ArtifactRepository) repoMap.get( key );
 1010  
 
 1011  0
             sink.tableRow();
 1012  0
             tableCell( repo.getId() );
 1013  
 
 1014  0
             sink.tableCell();
 1015  0
             if ( repo.isBlacklisted() )
 1016  
             {
 1017  0
                 sink.text( repo.getUrl() );
 1018  
             }
 1019  
             else
 1020  
             {
 1021  0
                 sink.link( repo.getUrl() );
 1022  0
                 sink.text( repo.getUrl() );
 1023  0
                 sink.link_();
 1024  
             }
 1025  0
             sink.tableCell_();
 1026  
 
 1027  0
             ArtifactRepositoryPolicy releasePolicy = repo.getReleases();
 1028  0
             tableCell( releasePolicy.isEnabled() ? releaseEnabled : releaseDisabled );
 1029  
 
 1030  0
             ArtifactRepositoryPolicy snapshotPolicy = repo.getSnapshots();
 1031  0
             tableCell( snapshotPolicy.isEnabled() ? snapshotEnabled : snapshotDisabled );
 1032  
 
 1033  0
             if ( !repoUrlBlackListed.isEmpty() )
 1034  
             {
 1035  0
                 tableCell( repo.isBlacklisted() ? blacklistedEnabled : blacklistedDisabled );
 1036  
             }
 1037  0
             sink.tableRow_();
 1038  0
         }
 1039  
 
 1040  0
         sink.tableRows_();
 1041  
 
 1042  0
         endTable();
 1043  0
     }
 1044  
 
 1045  
     private void printArtifactsLocations( Map repoMap, List alldeps )
 1046  
     {
 1047  
         // i18n
 1048  0
         String artifact = getReportString( "report.dependencies.repo.locations.column.artifact" );
 1049  
 
 1050  0
         sink.paragraph();
 1051  0
         sink.text( getReportString( "report.dependencies.repo.locations.artifact.breakdown" ) );
 1052  0
         sink.paragraph_();
 1053  
 
 1054  0
         List repoIdList = new ArrayList();
 1055  
         // removed blacklisted repo
 1056  0
         for ( Iterator it = repoMap.keySet().iterator(); it.hasNext(); )
 1057  
         {
 1058  0
             String repokey = (String) it.next();
 1059  0
             ArtifactRepository repo = (ArtifactRepository) repoMap.get( repokey );
 1060  0
             if ( !repo.isBlacklisted() )
 1061  
             {
 1062  0
                 repoIdList.add( repokey );
 1063  
             }
 1064  0
         }
 1065  
 
 1066  0
         String[] tableHeader = new String[repoIdList.size() + 1];
 1067  0
         int[] justificationRepo = new int[repoIdList.size() + 1];
 1068  
 
 1069  0
         tableHeader[0] = artifact;
 1070  0
         justificationRepo[0] = Parser.JUSTIFY_LEFT;
 1071  
 
 1072  0
         int idnum = 1;
 1073  0
         for ( Iterator it = repoIdList.iterator(); it.hasNext(); )
 1074  
         {
 1075  0
             String id = (String) it.next();
 1076  0
             tableHeader[idnum] = id;
 1077  0
             justificationRepo[idnum] = Parser.JUSTIFY_CENTER;
 1078  0
             idnum++;
 1079  0
         }
 1080  
 
 1081  0
         Map totalByRepo = new HashMap();
 1082  0
         TotalCell totaldeps = new TotalCell( DEFAULT_DECIMAL_FORMAT );
 1083  
 
 1084  0
         startTable();
 1085  
 
 1086  0
         sink.tableRows( justificationRepo, true );
 1087  
 
 1088  0
         tableHeader( tableHeader );
 1089  
 
 1090  0
         for ( Iterator it = alldeps.iterator(); it.hasNext(); )
 1091  
         {
 1092  0
             Artifact dependency = (Artifact) it.next();
 1093  
 
 1094  0
             totaldeps.incrementTotal( dependency.getScope() );
 1095  
 
 1096  0
             sink.tableRow();
 1097  
 
 1098  0
             if ( !Artifact.SCOPE_SYSTEM.equals( dependency.getScope() ) )
 1099  
             {
 1100  
 
 1101  0
                 tableCell( dependency.getId() );
 1102  
 
 1103  0
                 for ( Iterator itrepo = repoIdList.iterator(); itrepo.hasNext(); )
 1104  
                 {
 1105  0
                     String repokey = (String) itrepo.next();
 1106  0
                     ArtifactRepository repo = (ArtifactRepository) repoMap.get( repokey );
 1107  
 
 1108  0
                     String depUrl = repoUtils.getDependencyUrlFromRepository( dependency, repo );
 1109  
 
 1110  0
                     Integer old = (Integer) totalByRepo.get( repokey );
 1111  0
                     if ( old == null )
 1112  
                     {
 1113  0
                         totalByRepo.put( repokey, new Integer( 0 ) );
 1114  0
                         old = new Integer( 0 );
 1115  
                     }
 1116  
 
 1117  0
                     boolean dependencyExists = false;
 1118  
                     // check snapshots in snapshots repository only and releases in release repositories...
 1119  0
                     if ( ( dependency.isSnapshot() && repo.getSnapshots().isEnabled() )
 1120  
                         || ( !dependency.isSnapshot() && repo.getReleases().isEnabled() ) )
 1121  
                     {
 1122  0
                         dependencyExists = repoUtils.dependencyExistsInRepo( repo, dependency );
 1123  
                     }
 1124  
 
 1125  0
                     if ( dependencyExists )
 1126  
                     {
 1127  0
                         sink.tableCell();
 1128  0
                         if ( StringUtils.isNotEmpty( depUrl ) )
 1129  
                         {
 1130  0
                             sink.link( depUrl );
 1131  
                         }
 1132  
                         else
 1133  
                         {
 1134  0
                             sink.text( depUrl );
 1135  
                         }
 1136  
 
 1137  0
                         sink.figure();
 1138  0
                         sink.figureCaption();
 1139  0
                         sink.text( "Found at " + repo.getUrl() );
 1140  0
                         sink.figureCaption_();
 1141  0
                         sink.figureGraphics( "images/icon_success_sml.gif" );
 1142  0
                         sink.figure_();
 1143  
 
 1144  0
                         sink.link_();
 1145  0
                         sink.tableCell_();
 1146  
 
 1147  0
                         totalByRepo.put( repokey, new Integer( old.intValue() + 1 ) );
 1148  
                     }
 1149  
                     else
 1150  
                     {
 1151  0
                         tableCell( "-" );
 1152  
                     }
 1153  0
                 }
 1154  
             }
 1155  
             else
 1156  
             {
 1157  0
                 tableCell( dependency.getId() );
 1158  
 
 1159  0
                 for ( Iterator itrepo = repoIdList.iterator(); itrepo.hasNext(); )
 1160  
                 {
 1161  0
                     itrepo.next();
 1162  
 
 1163  0
                     tableCell( "-" );
 1164  
                 }
 1165  
             }
 1166  
 
 1167  0
             sink.tableRow_();
 1168  0
         }
 1169  
 
 1170  
         // Total row
 1171  
 
 1172  
         // reused key
 1173  0
         tableHeader[0] = getReportString( "report.dependencies.file.details.total" );
 1174  0
         tableHeader( tableHeader );
 1175  0
         String[] totalRow = new String[repoIdList.size() + 1];
 1176  0
         totalRow[0] = totaldeps.toString();
 1177  0
         idnum = 1;
 1178  0
         for ( Iterator itrepo = repoIdList.iterator(); itrepo.hasNext(); )
 1179  
         {
 1180  0
             String repokey = (String) itrepo.next();
 1181  
 
 1182  0
             totalRow[idnum++] = totalByRepo.get( repokey ).toString();
 1183  0
         }
 1184  
 
 1185  0
         tableRow( totalRow );
 1186  
 
 1187  0
         sink.tableRows_();
 1188  
 
 1189  0
         endTable();
 1190  0
     }
 1191  
 
 1192  
     private String getReportString( String key )
 1193  
     {
 1194  24
         return i18n.getString( "project-info-report", locale, key );
 1195  
     }
 1196  
 
 1197  
     /**
 1198  
      * @param artifacts not null
 1199  
      * @return <code>true</code> if one artifact in the list has a classifier, <code>false</code> otherwise.
 1200  
      */
 1201  
     private boolean hasClassifier( List artifacts )
 1202  
     {
 1203  1
         for ( Iterator iterator = artifacts.iterator(); iterator.hasNext(); )
 1204  
         {
 1205  1
             Artifact artifact = (Artifact) iterator.next();
 1206  
 
 1207  1
             if ( StringUtils.isNotEmpty( artifact.getClassifier() ) )
 1208  
             {
 1209  0
                 return true;
 1210  
             }
 1211  1
         }
 1212  
 
 1213  1
         return false;
 1214  
     }
 1215  
 
 1216  
     /**
 1217  
      * @param artifacts not null
 1218  
      * @return <code>true</code> if one artifact in the list is optional, <code>false</code> otherwise.
 1219  
      */
 1220  
     private boolean hasOptional( List artifacts )
 1221  
     {
 1222  1
         for ( Iterator iterator = artifacts.iterator(); iterator.hasNext(); )
 1223  
         {
 1224  1
             Artifact artifact = (Artifact) iterator.next();
 1225  
 
 1226  1
             if ( artifact.isOptional() )
 1227  
             {
 1228  0
                 return true;
 1229  
             }
 1230  1
         }
 1231  
 
 1232  1
         return false;
 1233  
     }
 1234  
 
 1235  
     /**
 1236  
      * @param artifacts not null
 1237  
      * @return <code>true</code> if one artifact in the list is sealed, <code>false</code> otherwise.
 1238  
      */
 1239  
     private boolean hasSealed( List artifacts )
 1240  
     {
 1241  0
         for ( Iterator it = artifacts.iterator(); it.hasNext(); )
 1242  
         {
 1243  0
             Artifact artifact = (Artifact) it.next();
 1244  
 
 1245  
             // TODO site:run Why do we need to resolve this...
 1246  0
             if ( artifact.getFile() == null && !Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
 1247  
             {
 1248  
                 try
 1249  
                 {
 1250  0
                     repoUtils.resolve( artifact );
 1251  
                 }
 1252  0
                 catch ( ArtifactResolutionException e )
 1253  
                 {
 1254  0
                     log.error( "Artifact: " + artifact.getId() + " has no file.", e );
 1255  0
                     continue;
 1256  
                 }
 1257  0
                 catch ( ArtifactNotFoundException e )
 1258  
                 {
 1259  0
                     if ( ( dependencies.getProject().getGroupId().equals( artifact.getGroupId() ) )
 1260  
                         && ( dependencies.getProject().getArtifactId().equals( artifact.getArtifactId() ) )
 1261  
                         && ( dependencies.getProject().getVersion().equals( artifact.getVersion() ) ) )
 1262  
                     {
 1263  0
                         log.warn( "The artifact of this project has never been deployed." );
 1264  
                     }
 1265  
                     else
 1266  
                     {
 1267  0
                         log.error( "Artifact: " + artifact.getId() + " has no file.", e );
 1268  
                     }
 1269  
 
 1270  0
                     continue;
 1271  0
                 }
 1272  
             }
 1273  
 
 1274  0
             if ( JAR_SUBTYPE.contains( artifact.getType().toLowerCase() ) )
 1275  
             {
 1276  
                 try
 1277  
                 {
 1278  0
                     JarData jarDetails = dependencies.getJarDependencyDetails( artifact );
 1279  0
                     if ( jarDetails.isSealed() )
 1280  
                     {
 1281  0
                         return true;
 1282  
                     }
 1283  
                 }
 1284  0
                 catch ( IOException e )
 1285  
                 {
 1286  0
                     log.error( "IOException: " + e.getMessage(), e );
 1287  0
                 }
 1288  
             }
 1289  0
         }
 1290  0
         return false;
 1291  
     }
 1292  
 
 1293  
     /**
 1294  
      * @return a valid HTML ID respecting
 1295  
      * <a href="http://www.w3.org/TR/xhtml1/#C_8">XHTML 1.0 section C.8. Fragment Identifiers</a>
 1296  
      */
 1297  
     private static String getUUID()
 1298  
     {
 1299  4
         return "_" + Math.abs( RANDOM.nextInt() );
 1300  
     }
 1301  
 
 1302  
     /**
 1303  
      * Formats file length with the associated <a href="http://en.wikipedia.org/wiki/SI_prefix#Computing">SI</a>
 1304  
      * unit (GB, MB, kB) and using the pattern <code>########.00</code> by default.
 1305  
      *
 1306  
      * @see <a href="http://en.wikipedia.org/wiki/SI_prefix#Computing>
 1307  
      * http://en.wikipedia.org/wiki/SI_prefix#Computing</a>
 1308  
      * @see <a href="http://en.wikipedia.org/wiki/Binary_prefix">
 1309  
      * http://en.wikipedia.org/wiki/Binary_prefix</a>
 1310  
      * @see <a href="http://en.wikipedia.org/wiki/Octet_(computing)">
 1311  
      * http://en.wikipedia.org/wiki/Octet_(computing)</a>
 1312  
      */
 1313  
     static class FileDecimalFormat
 1314  
         extends DecimalFormat
 1315  
     {
 1316  
         private static final long serialVersionUID = 4062503546523610081L;
 1317  
 
 1318  
         private final I18N i18n;
 1319  
 
 1320  
         private final Locale locale;
 1321  
 
 1322  
         /**
 1323  
          * Default constructor
 1324  
          *
 1325  
          * @param i18n
 1326  
          * @param locale
 1327  
          */
 1328  
         public FileDecimalFormat( I18N i18n, Locale locale )
 1329  
         {
 1330  1
             super( "#,###.00" );
 1331  
 
 1332  1
             this.i18n = i18n;
 1333  1
             this.locale = locale;
 1334  1
         }
 1335  
 
 1336  
         /** {@inheritDoc} */
 1337  
         public StringBuffer format( long fs, StringBuffer result, FieldPosition fieldPosition )
 1338  
         {
 1339  0
             if ( fs > 1024 * 1024 * 1024 )
 1340  
             {
 1341  0
                 result = super.format( (float) fs / ( 1024 * 1024 * 1024 ), result, fieldPosition );
 1342  0
                 result.append( " " ).append( getString( i18n, "report.dependencies.file.details.column.size.gb" ) );
 1343  0
                 return result;
 1344  
             }
 1345  
 
 1346  0
             if ( fs > 1024 * 1024 )
 1347  
             {
 1348  0
                 result = super.format( (float) fs / ( 1024 * 1024 ), result, fieldPosition );
 1349  0
                 result.append( " " ).append( getString( i18n, "report.dependencies.file.details.column.size.mb" ) );
 1350  0
                 return result;
 1351  
             }
 1352  
 
 1353  0
             result = super.format( (float) fs / ( 1024 ), result, fieldPosition );
 1354  0
             result.append( " " ).append( getString( i18n, "report.dependencies.file.details.column.size.kb" ) );
 1355  0
             return result;
 1356  
         }
 1357  
 
 1358  
         private String getString( I18N i18n, String key )
 1359  
         {
 1360  0
             return i18n.getString( "project-info-report", locale, key );
 1361  
         }
 1362  
     }
 1363  
 
 1364  
     /**
 1365  
      * Combine total and total by scope in a cell.
 1366  
      */
 1367  
     static class TotalCell
 1368  
     {
 1369  
         static final int SCOPES_COUNT = 5;
 1370  
 
 1371  
         final DecimalFormat decimalFormat;
 1372  
 
 1373  0
         long total = 0;
 1374  
 
 1375  0
         long totalCompileScope = 0;
 1376  
 
 1377  0
         long totalTestScope = 0;
 1378  
 
 1379  0
         long totalRuntimeScope = 0;
 1380  
 
 1381  0
         long totalProvidedScope = 0;
 1382  
 
 1383  0
         long totalSystemScope = 0;
 1384  
 
 1385  
         TotalCell( DecimalFormat decimalFormat )
 1386  0
         {
 1387  0
             this.decimalFormat = decimalFormat;
 1388  0
         }
 1389  
 
 1390  
         void incrementTotal( String scope )
 1391  
         {
 1392  0
             addTotal( 1, scope );
 1393  0
         }
 1394  
 
 1395  
         static String getScope( int index )
 1396  
         {
 1397  0
             switch ( index )
 1398  
             {
 1399  
                 case 0:
 1400  0
                     return Artifact.SCOPE_COMPILE;
 1401  
                 case 1:
 1402  0
                     return Artifact.SCOPE_TEST;
 1403  
                 case 2:
 1404  0
                     return Artifact.SCOPE_RUNTIME;
 1405  
                 case 3:
 1406  0
                     return Artifact.SCOPE_PROVIDED;
 1407  
                 case 4:
 1408  0
                     return Artifact.SCOPE_SYSTEM;
 1409  
                 default:
 1410  0
                     return null;
 1411  
             }
 1412  
         }
 1413  
 
 1414  
         long getTotal( int index )
 1415  
         {
 1416  0
             switch ( index )
 1417  
             {
 1418  
                 case 0:
 1419  0
                     return totalCompileScope;
 1420  
                 case 1:
 1421  0
                     return totalTestScope;
 1422  
                 case 2:
 1423  0
                     return totalRuntimeScope;
 1424  
                 case 3:
 1425  0
                     return totalProvidedScope;
 1426  
                 case 4:
 1427  0
                     return totalSystemScope;
 1428  
                 default:
 1429  0
                     return total;
 1430  
             }
 1431  
         }
 1432  
 
 1433  
         String getTotalString( int index )
 1434  
         {
 1435  0
             long total = getTotal( index );
 1436  
 
 1437  0
             if ( total <= 0 )
 1438  
             {
 1439  0
                 return "";
 1440  
             }
 1441  
 
 1442  0
             StringBuffer sb = new StringBuffer();
 1443  0
             if ( index >= 0 )
 1444  
             {
 1445  0
                 sb.append( getScope( index ) ).append( ": " );
 1446  
             }
 1447  0
             sb.append( decimalFormat.format( getTotal( index ) ) );
 1448  0
             return sb.toString();
 1449  
         }
 1450  
 
 1451  
         void addTotal( long add, String scope )
 1452  
         {
 1453  0
             total += add;
 1454  
 
 1455  0
             if ( Artifact.SCOPE_COMPILE.equals( scope ) )
 1456  
             {
 1457  0
                 totalCompileScope += add;
 1458  
             }
 1459  0
             else if ( Artifact.SCOPE_TEST.equals( scope ) )
 1460  
             {
 1461  0
                 totalTestScope += add;
 1462  
             }
 1463  0
             else if ( Artifact.SCOPE_RUNTIME.equals( scope ) )
 1464  
             {
 1465  0
                 totalRuntimeScope += add;
 1466  
             }
 1467  0
             else if ( Artifact.SCOPE_PROVIDED.equals( scope ) )
 1468  
             {
 1469  0
                 totalProvidedScope += add;
 1470  
             }
 1471  0
             else if ( Artifact.SCOPE_SYSTEM.equals( scope ) )
 1472  
             {
 1473  0
                 totalSystemScope += add;
 1474  
             }
 1475  0
         }
 1476  
 
 1477  
         /** {@inheritDoc} */
 1478  
         public String toString()
 1479  
         {
 1480  0
             StringBuffer sb = new StringBuffer();
 1481  0
             sb.append( decimalFormat.format( total ) );
 1482  0
             sb.append( " (" );
 1483  
 
 1484  0
             boolean needSeparator = false;
 1485  0
             for ( int i = 0; i < SCOPES_COUNT; i++ )
 1486  
             {
 1487  0
                 if ( getTotal( i ) > 0 )
 1488  
                 {
 1489  0
                     if ( needSeparator )
 1490  
                     {
 1491  0
                         sb.append( ", " );
 1492  
                     }
 1493  0
                     sb.append( getTotalString( i ) );
 1494  0
                     needSeparator = true;
 1495  
                 }
 1496  
             }
 1497  
 
 1498  0
             sb.append( ")" );
 1499  
 
 1500  0
             return sb.toString();
 1501  
         }
 1502  
     }
 1503  
 }