Coverage Report - org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis
 
Classes in this File Line Coverage Branch Coverage Complexity
ProjectDependencyAnalysis
57%
38/66
50%
20/40
2.909
 
 1  
 package org.apache.maven.shared.dependency.analyzer;
 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.util.Arrays;
 23  
 import java.util.Collections;
 24  
 import java.util.HashSet;
 25  
 import java.util.Iterator;
 26  
 import java.util.LinkedHashSet;
 27  
 import java.util.Set;
 28  
 
 29  
 import org.apache.maven.artifact.Artifact;
 30  
 
 31  
 /**
 32  
  * Project dependencies analysis result.
 33  
  * 
 34  
  * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
 35  
  * @version $Id: ProjectDependencyAnalysis.java 1400637 2012-10-21 13:09:09Z hboutemy $
 36  
  */
 37  
 public class ProjectDependencyAnalysis
 38  
 {
 39  
     // fields -----------------------------------------------------------------
 40  
 
 41  
     private final Set<Artifact> usedDeclaredArtifacts;
 42  
 
 43  
     private final Set<Artifact> usedUndeclaredArtifacts;
 44  
 
 45  
     private final Set<Artifact> unusedDeclaredArtifacts;
 46  
 
 47  
     // constructors -----------------------------------------------------------
 48  
 
 49  
     public ProjectDependencyAnalysis()
 50  
     {
 51  4
         this( null, null, null );
 52  4
     }
 53  
 
 54  
     public ProjectDependencyAnalysis( Set<Artifact> usedDeclaredArtifacts, Set<Artifact> usedUndeclaredArtifacts,
 55  
                                       Set<Artifact> unusedDeclaredArtifacts )
 56  26
     {
 57  26
         this.usedDeclaredArtifacts = safeCopy( usedDeclaredArtifacts );
 58  26
         this.usedUndeclaredArtifacts = safeCopy( usedUndeclaredArtifacts );
 59  26
         this.unusedDeclaredArtifacts = safeCopy( unusedDeclaredArtifacts );
 60  26
     }
 61  
 
 62  
     // public methods ---------------------------------------------------------
 63  
 
 64  
     /**
 65  
      * Used and declared artifacts.
 66  
      */
 67  
     public Set<Artifact> getUsedDeclaredArtifacts()
 68  
     {
 69  22
         return usedDeclaredArtifacts;
 70  
     }
 71  
 
 72  
     /**
 73  
      * Used but not declared artifacts.
 74  
      */
 75  
     public Set<Artifact> getUsedUndeclaredArtifacts()
 76  
     {
 77  22
         return usedUndeclaredArtifacts;
 78  
     }
 79  
 
 80  
     /**
 81  
      * Unused but declared artifacts.
 82  
      */
 83  
     public Set<Artifact> getUnusedDeclaredArtifacts()
 84  
     {
 85  22
         return unusedDeclaredArtifacts;
 86  
     }
 87  
 
 88  
     /**
 89  
      * Filter not-compile scoped artifacts from unused declared.
 90  
      * 
 91  
      * @return updated project dependency analysis
 92  
      * @since 1.3
 93  
      */
 94  
     public ProjectDependencyAnalysis ignoreNonCompile()
 95  
     {
 96  0
         Set<Artifact> filteredUnusedDeclared = new HashSet<Artifact>( unusedDeclaredArtifacts );
 97  0
         for ( Iterator<Artifact> iter = filteredUnusedDeclared.iterator(); iter.hasNext(); )
 98  
         {
 99  0
             Artifact artifact = iter.next();
 100  0
             if ( !artifact.getScope().equals( Artifact.SCOPE_COMPILE ) )
 101  
             {
 102  0
                 iter.remove();
 103  
             }
 104  0
         }
 105  
 
 106  0
         return new ProjectDependencyAnalysis( usedDeclaredArtifacts, usedUndeclaredArtifacts, filteredUnusedDeclared );
 107  
     }
 108  
 
 109  
     /**
 110  
      * Force use status of some declared dependencies, to manually fix consequences of bytecode-level analysis which
 111  
      * happens to not detect some effective use (constants, annotation with source-retention, javadoc).
 112  
      * 
 113  
      * @param forceUsedDependencies dependencies to move from "unused-declared" to "used-declared", with
 114  
      *            <code>groupId:artifactId</code> format
 115  
      * @return updated project dependency analysis
 116  
      * @throws ProjectDependencyAnalyzerException if dependencies forced were either not declared or already detected as
 117  
      *             used
 118  
      * @since 1.3
 119  
      */
 120  
     public ProjectDependencyAnalysis forceDeclaredDependenciesUsage( String[] forceUsedDependencies )
 121  
         throws ProjectDependencyAnalyzerException
 122  
     {
 123  6
         Set<String> forced = new HashSet<String>( Arrays.asList( forceUsedDependencies ) );
 124  
 
 125  6
         Set<Artifact> forcedUnusedDeclared = new HashSet<Artifact>( unusedDeclaredArtifacts );
 126  6
         Set<Artifact> forcedUsedDeclared = new HashSet<Artifact>( usedDeclaredArtifacts );
 127  
 
 128  6
         for ( Iterator<Artifact> iter = forcedUnusedDeclared.iterator(); iter.hasNext(); )
 129  
         {
 130  2
             Artifact artifact = iter.next();
 131  
 
 132  2
             if ( forced.remove( artifact.getGroupId() + ':' + artifact.getArtifactId() ) )
 133  
             {
 134  
                 // ok, change artifact status from unused-declared to used-declared
 135  2
                 iter.remove();
 136  2
                 forcedUsedDeclared.add( artifact );
 137  
             }
 138  2
         }
 139  
 
 140  6
         if ( !forced.isEmpty() )
 141  
         {
 142  
             // trying to force dependencies as used-declared which were not declared or already detected as used
 143  4
             Set<String> used = new HashSet<String>();
 144  4
             for ( Artifact artifact : usedDeclaredArtifacts )
 145  
             {
 146  8
                 String id = artifact.getGroupId() + ':' + artifact.getArtifactId();
 147  8
                 if ( forced.remove( id ) )
 148  
                 {
 149  2
                     used.add( id );
 150  
                 }
 151  8
             }
 152  
 
 153  4
             StringBuilder builder = new StringBuilder();
 154  4
             if ( !forced.isEmpty() )
 155  
             {
 156  2
                 builder.append( "not declared: " + forced );
 157  
             }
 158  4
             if ( !used.isEmpty() )
 159  
             {
 160  2
                 if ( builder.length() > 0 )
 161  
                 {
 162  0
                     builder.append( " and " );
 163  
                 }
 164  2
                 builder.append( "declared but already detected as used: " + used );
 165  
             }
 166  4
             throw new ProjectDependencyAnalyzerException( "Trying to force use of dependencies which are " + builder );
 167  
         }
 168  
 
 169  2
         return new ProjectDependencyAnalysis( forcedUsedDeclared, usedUndeclaredArtifacts, forcedUnusedDeclared );
 170  
     }
 171  
 
 172  
     // Object methods ---------------------------------------------------------
 173  
 
 174  
     /*
 175  
      * @see java.lang.Object#hashCode()
 176  
      */
 177  
     public int hashCode()
 178  
     {
 179  0
         int hashCode = getUsedDeclaredArtifacts().hashCode();
 180  0
         hashCode = ( hashCode * 37 ) + getUsedUndeclaredArtifacts().hashCode();
 181  0
         hashCode = ( hashCode * 37 ) + getUnusedDeclaredArtifacts().hashCode();
 182  
 
 183  0
         return hashCode;
 184  
     }
 185  
 
 186  
     /*
 187  
      * @see java.lang.Object#equals(java.lang.Object)
 188  
      */
 189  
     public boolean equals( Object object )
 190  
     {
 191  10
         if ( object instanceof ProjectDependencyAnalysis )
 192  
         {
 193  10
             ProjectDependencyAnalysis analysis = (ProjectDependencyAnalysis) object;
 194  
 
 195  10
             return getUsedDeclaredArtifacts().equals( analysis.getUsedDeclaredArtifacts() )
 196  
                 && getUsedUndeclaredArtifacts().equals( analysis.getUsedUndeclaredArtifacts() )
 197  
                 && getUnusedDeclaredArtifacts().equals( analysis.getUnusedDeclaredArtifacts() );
 198  
         }
 199  
 
 200  0
         return false;
 201  
     }
 202  
 
 203  
     /*
 204  
      * @see java.lang.Object#toString()
 205  
      */
 206  
     public String toString()
 207  
     {
 208  0
         StringBuffer buffer = new StringBuffer();
 209  
 
 210  0
         if ( !getUsedDeclaredArtifacts().isEmpty() )
 211  
         {
 212  0
             buffer.append( "usedDeclaredArtifacts=" ).append( getUsedDeclaredArtifacts() );
 213  
         }
 214  
 
 215  0
         if ( !getUsedUndeclaredArtifacts().isEmpty() )
 216  
         {
 217  0
             if ( buffer.length() > 0)
 218  
             {
 219  0
                 buffer.append( "," );
 220  
             }
 221  
 
 222  0
             buffer.append( "usedUndeclaredArtifacts=" ).append( getUsedUndeclaredArtifacts() );
 223  
         }
 224  
 
 225  0
         if ( !getUnusedDeclaredArtifacts().isEmpty() )
 226  
         {
 227  0
             if ( buffer.length() > 0)
 228  
             {
 229  0
                 buffer.append( "," );
 230  
             }
 231  
 
 232  0
             buffer.append( "unusedDeclaredArtifacts=" ).append( getUnusedDeclaredArtifacts() );
 233  
         }
 234  
 
 235  0
         buffer.insert( 0, "[" );
 236  0
         buffer.insert( 0, getClass().getName() );
 237  
 
 238  0
         buffer.append( "]" );
 239  
 
 240  0
         return buffer.toString();
 241  
     }
 242  
 
 243  
     // private methods --------------------------------------------------------
 244  
 
 245  
     private Set<Artifact> safeCopy( Set<Artifact> set )
 246  
     {
 247  78
         return ( set == null ) ? Collections.<Artifact> emptySet()
 248  
                         : Collections.unmodifiableSet( new LinkedHashSet<Artifact>( set ) );
 249  
     }
 250  
 }