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