Coverage Report - org.owasp.dependencycheck.dependency.Dependency
 
Classes in this File Line Coverage Branch Coverage Complexity
Dependency
64%
95/147
14%
18/126
2.762
 
 1  
 /*
 2  
  * This file is part of dependency-check-core.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  *
 16  
  * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
 17  
  */
 18  
 package org.owasp.dependencycheck.dependency;
 19  
 
 20  
 import java.io.File;
 21  
 import java.io.IOException;
 22  
 import java.security.NoSuchAlgorithmException;
 23  
 import java.util.ArrayList;
 24  
 import java.util.List;
 25  
 import java.util.Set;
 26  
 import java.util.SortedSet;
 27  
 import java.util.TreeSet;
 28  
 import java.util.logging.Level;
 29  
 import java.util.logging.Logger;
 30  
 import org.owasp.dependencycheck.utils.Checksum;
 31  
 import org.owasp.dependencycheck.utils.FileUtils;
 32  
 
 33  
 /**
 34  
  * A program dependency. This object is one of the core components within DependencyCheck. It is used to collect
 35  
  * information about the dependency in the form of evidence. The Evidence is then used to determine if there are any
 36  
  * known, published, vulnerabilities associated with the program dependency.
 37  
  *
 38  
  * @author Jeremy Long <jeremy.long@owasp.org>
 39  
  */
 40  58
 public class Dependency implements Comparable<Dependency> {
 41  
 
 42  
     /**
 43  
      * The actual file path of the dependency on disk.
 44  
      */
 45  
     private String actualFilePath;
 46  
     /**
 47  
      * The file path to display.
 48  
      */
 49  
     private String filePath;
 50  
     /**
 51  
      * The file name of the dependency.
 52  
      */
 53  
     private String fileName;
 54  
     /**
 55  
      * The file extension of the dependency.
 56  
      */
 57  
     private String fileExtension;
 58  
     /**
 59  
      * The md5 hash of the dependency.
 60  
      */
 61  
     private String md5sum;
 62  
     /**
 63  
      * The SHA1 hash of the dependency.
 64  
      */
 65  
     private String sha1sum;
 66  
     /**
 67  
      * A list of Identifiers.
 68  
      */
 69  
     private Set<Identifier> identifiers;
 70  
     /**
 71  
      * A collection of vendor evidence.
 72  
      */
 73  
     private final EvidenceCollection vendorEvidence;
 74  
     /**
 75  
      * A collection of product evidence.
 76  
      */
 77  
     private final EvidenceCollection productEvidence;
 78  
     /**
 79  
      * A collection of version evidence.
 80  
      */
 81  
     private final EvidenceCollection versionEvidence;
 82  
 
 83  
     /**
 84  
      * Constructs a new Dependency object.
 85  
      */
 86  132
     public Dependency() {
 87  132
         vendorEvidence = new EvidenceCollection();
 88  132
         productEvidence = new EvidenceCollection();
 89  132
         versionEvidence = new EvidenceCollection();
 90  132
         identifiers = new TreeSet<Identifier>();
 91  132
         vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
 92  132
     }
 93  
 
 94  
     /**
 95  
      * Constructs a new Dependency object.
 96  
      *
 97  
      * @param file the File to create the dependency object from.
 98  
      */
 99  
     public Dependency(File file) {
 100  90
         this();
 101  90
         this.actualFilePath = file.getPath();
 102  90
         this.filePath = this.actualFilePath;
 103  90
         this.fileName = file.getName();
 104  90
         this.fileExtension = FileUtils.getFileExtension(fileName);
 105  90
         determineHashes(file);
 106  90
     }
 107  
 
 108  
     /**
 109  
      * Returns the file name of the dependency.
 110  
      *
 111  
      * @return the file name of the dependency.
 112  
      */
 113  
     public String getFileName() {
 114  414
         return this.fileName;
 115  
     }
 116  
 
 117  
     /**
 118  
      * Sets the file name of the dependency.
 119  
      *
 120  
      * @param fileName the file name of the dependency.
 121  
      */
 122  
     public void setFileName(String fileName) {
 123  52
         this.fileName = fileName;
 124  52
     }
 125  
 
 126  
     /**
 127  
      * Sets the actual file path of the dependency on disk.
 128  
      *
 129  
      * @param actualFilePath the file path of the dependency.
 130  
      */
 131  
     public void setActualFilePath(String actualFilePath) {
 132  4
         this.actualFilePath = actualFilePath;
 133  4
         if (this.sha1sum == null) {
 134  4
             final File file = new File(this.actualFilePath);
 135  4
             determineHashes(file);
 136  
         }
 137  4
     }
 138  
 
 139  
     /**
 140  
      * Gets the file path of the dependency.
 141  
      *
 142  
      * @return the file path of the dependency.
 143  
      */
 144  
     public String getActualFilePath() {
 145  334
         return this.actualFilePath;
 146  
     }
 147  
 
 148  
     /**
 149  
      * Sets the file path of the dependency.
 150  
      *
 151  
      * @param filePath the file path of the dependency.
 152  
      */
 153  
     public void setFilePath(String filePath) {
 154  42
         this.filePath = filePath;
 155  42
     }
 156  
 
 157  
     /**
 158  
      * <p>
 159  
      * Gets the file path of the dependency.</p>
 160  
      * <p>
 161  
      * <b>NOTE:</b> This may not be the actual path of the file on disk. The actual path of the file on disk can be
 162  
      * obtained via the getActualFilePath().</p>
 163  
      *
 164  
      * @return the file path of the dependency.
 165  
      */
 166  
     public String getFilePath() {
 167  56
         return this.filePath;
 168  
     }
 169  
 
 170  
     /**
 171  
      * Sets the file name of the dependency.
 172  
      *
 173  
      * @param fileExtension the file name of the dependency.
 174  
      */
 175  
     public void setFileExtension(String fileExtension) {
 176  4
         this.fileExtension = fileExtension;
 177  4
     }
 178  
 
 179  
     /**
 180  
      * Gets the file extension of the dependency.
 181  
      *
 182  
      * @return the file extension of the dependency.
 183  
      */
 184  
     public String getFileExtension() {
 185  232
         return this.fileExtension;
 186  
     }
 187  
 
 188  
     /**
 189  
      * Returns the MD5 Checksum of the dependency file.
 190  
      *
 191  
      * @return the MD5 Checksum
 192  
      */
 193  
     public String getMd5sum() {
 194  10
         return this.md5sum;
 195  
     }
 196  
 
 197  
     /**
 198  
      * Sets the MD5 Checksum of the dependency.
 199  
      *
 200  
      * @param md5sum the MD5 Checksum
 201  
      */
 202  
     public void setMd5sum(String md5sum) {
 203  96
         this.md5sum = md5sum;
 204  96
     }
 205  
 
 206  
     /**
 207  
      * Returns the SHA1 Checksum of the dependency.
 208  
      *
 209  
      * @return the SHA1 Checksum
 210  
      */
 211  
     public String getSha1sum() {
 212  50
         return this.sha1sum;
 213  
     }
 214  
 
 215  
     /**
 216  
      * Sets the SHA1 Checksum of the dependency.
 217  
      *
 218  
      * @param sha1sum the SHA1 Checksum
 219  
      */
 220  
     public void setSha1sum(String sha1sum) {
 221  100
         this.sha1sum = sha1sum;
 222  100
     }
 223  
 
 224  
     /**
 225  
      * Returns a List of Identifiers.
 226  
      *
 227  
      * @return an ArrayList of Identifiers.
 228  
      */
 229  
     public Set<Identifier> getIdentifiers() {
 230  284
         return this.identifiers;
 231  
     }
 232  
 
 233  
     /**
 234  
      * Sets a List of Identifiers.
 235  
      *
 236  
      * @param identifiers A list of Identifiers.
 237  
      */
 238  
     public void setIdentifiers(Set<Identifier> identifiers) {
 239  2
         this.identifiers = identifiers;
 240  2
     }
 241  
 
 242  
     /**
 243  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 244  
      *
 245  
      * @param type the type of identifier (such as CPE)
 246  
      * @param value the value of the identifier
 247  
      * @param url the URL of the identifier
 248  
      */
 249  
     public void addIdentifier(String type, String value, String url) {
 250  12
         final Identifier i = new Identifier(type, value, url);
 251  12
         this.identifiers.add(i);
 252  12
     }
 253  
 
 254  
     /**
 255  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 256  
      *
 257  
      * @param type the type of identifier (such as CPE)
 258  
      * @param value the value of the identifier
 259  
      * @param url the URL of the identifier
 260  
      * @param confidence the confidence in the Identifier being accurate
 261  
      */
 262  
     public void addIdentifier(String type, String value, String url, Confidence confidence) {
 263  10
         final Identifier i = new Identifier(type, value, url);
 264  10
         i.setConfidence(confidence);
 265  10
         this.identifiers.add(i);
 266  10
     }
 267  
 
 268  
     /**
 269  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 270  
      *
 271  
      * @param identifier the identifier to add
 272  
      */
 273  
     public void addIdentifier(Identifier identifier) {
 274  216
         this.identifiers.add(identifier);
 275  216
     }
 276  
 
 277  
     /**
 278  
      * Returns the evidence used to identify this dependency.
 279  
      *
 280  
      * @return an EvidenceCollection.
 281  
      */
 282  
     public EvidenceCollection getEvidence() {
 283  2
         return EvidenceCollection.merge(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 284  
     }
 285  
 
 286  
     /**
 287  
      * Returns the evidence used to identify this dependency.
 288  
      *
 289  
      * @return an EvidenceCollection.
 290  
      */
 291  
     public EvidenceCollection getEvidenceUsed() {
 292  8
         return EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 293  
     }
 294  
 
 295  
     /**
 296  
      * Gets the Vendor Evidence.
 297  
      *
 298  
      * @return an EvidenceCollection.
 299  
      */
 300  
     public EvidenceCollection getVendorEvidence() {
 301  912
         return this.vendorEvidence;
 302  
     }
 303  
 
 304  
     /**
 305  
      * Gets the Product Evidence.
 306  
      *
 307  
      * @return an EvidenceCollection.
 308  
      */
 309  
     public EvidenceCollection getProductEvidence() {
 310  2184
         return this.productEvidence;
 311  
     }
 312  
 
 313  
     /**
 314  
      * Gets the Version Evidence.
 315  
      *
 316  
      * @return an EvidenceCollection.
 317  
      */
 318  
     public EvidenceCollection getVersionEvidence() {
 319  930
         return this.versionEvidence;
 320  
     }
 321  
     /**
 322  
      * A list of exceptions that occurred during analysis of this dependency.
 323  
      */
 324  132
     private List<Exception> analysisExceptions = new ArrayList<Exception>();
 325  
 
 326  
     /**
 327  
      * Get the value of analysisExceptions.
 328  
      *
 329  
      * @return the value of analysisExceptions
 330  
      */
 331  
     public List<Exception> getAnalysisExceptions() {
 332  0
         return analysisExceptions;
 333  
     }
 334  
 
 335  
     /**
 336  
      * Set the value of analysisExceptions.
 337  
      *
 338  
      * @param analysisExceptions new value of analysisExceptions
 339  
      */
 340  
     public void setAnalysisExceptions(List<Exception> analysisExceptions) {
 341  0
         this.analysisExceptions = analysisExceptions;
 342  0
     }
 343  
 
 344  
     /**
 345  
      * Adds an exception to the analysis exceptions collection.
 346  
      *
 347  
      * @param ex an exception.
 348  
      */
 349  
     public void addAnalysisException(Exception ex) {
 350  0
         this.analysisExceptions.add(ex);
 351  0
     }
 352  
     /**
 353  
      * The description of the JAR file.
 354  
      */
 355  
     private String description;
 356  
 
 357  
     /**
 358  
      * Get the value of description.
 359  
      *
 360  
      * @return the value of description
 361  
      */
 362  
     public String getDescription() {
 363  30
         return description;
 364  
     }
 365  
 
 366  
     /**
 367  
      * Set the value of description.
 368  
      *
 369  
      * @param description new value of description
 370  
      */
 371  
     public void setDescription(String description) {
 372  38
         this.description = description;
 373  38
     }
 374  
     /**
 375  
      * The license that this dependency uses.
 376  
      */
 377  
     private String license;
 378  
 
 379  
     /**
 380  
      * Get the value of license.
 381  
      *
 382  
      * @return the value of license
 383  
      */
 384  
     public String getLicense() {
 385  22
         return license;
 386  
     }
 387  
 
 388  
     /**
 389  
      * Set the value of license.
 390  
      *
 391  
      * @param license new value of license
 392  
      */
 393  
     public void setLicense(String license) {
 394  14
         this.license = license;
 395  14
     }
 396  
     /**
 397  
      * A list of vulnerabilities for this dependency.
 398  
      */
 399  
     private SortedSet<Vulnerability> vulnerabilities;
 400  
 
 401  
     /**
 402  
      * Get the list of vulnerabilities.
 403  
      *
 404  
      * @return the list of vulnerabilities
 405  
      */
 406  
     public SortedSet<Vulnerability> getVulnerabilities() {
 407  56
         return vulnerabilities;
 408  
     }
 409  
 
 410  
     /**
 411  
      * Set the value of vulnerabilities.
 412  
      *
 413  
      * @param vulnerabilities new value of vulnerabilities
 414  
      */
 415  
     public void setVulnerabilities(SortedSet<Vulnerability> vulnerabilities) {
 416  0
         this.vulnerabilities = vulnerabilities;
 417  0
     }
 418  
 
 419  
     /**
 420  
      * Determines the sha1 and md5 sum for the given file.
 421  
      *
 422  
      * @param file the file to create checksums for
 423  
      */
 424  
     private void determineHashes(File file) {
 425  94
         String md5 = null;
 426  94
         String sha1 = null;
 427  
         try {
 428  94
             md5 = Checksum.getMD5Checksum(file);
 429  90
             sha1 = Checksum.getSHA1Checksum(file);
 430  4
         } catch (IOException ex) {
 431  4
             final String msg = String.format("Unable to read '%s' to determine hashes.", file.getName());
 432  4
             Logger.getLogger(Dependency.class.getName()).log(Level.WARNING, msg);
 433  4
             Logger.getLogger(Dependency.class.getName()).log(Level.FINE, null, ex);
 434  0
         } catch (NoSuchAlgorithmException ex) {
 435  0
             final String msg = "Unable to use MD5 of SHA1 checksums.";
 436  0
             Logger.getLogger(Dependency.class.getName()).log(Level.WARNING, msg);
 437  0
             Logger.getLogger(Dependency.class.getName()).log(Level.FINE, null, ex);
 438  94
         }
 439  94
         this.setMd5sum(md5);
 440  94
         this.setSha1sum(sha1);
 441  94
     }
 442  
 
 443  
     /**
 444  
      * Adds a vulnerability to the dependency.
 445  
      *
 446  
      * @param vulnerability a vulnerability outlining a vulnerability.
 447  
      */
 448  
     public void addVulnerability(Vulnerability vulnerability) {
 449  6
         this.vulnerabilities.add(vulnerability);
 450  6
     }
 451  
     /**
 452  
      * A collection of related dependencies.
 453  
      */
 454  132
     private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
 455  
 
 456  
     /**
 457  
      * Get the value of relatedDependencies.
 458  
      *
 459  
      * @return the value of relatedDependencies
 460  
      */
 461  
     public Set<Dependency> getRelatedDependencies() {
 462  8
         return relatedDependencies;
 463  
     }
 464  
 
 465  
     /**
 466  
      * Set the value of relatedDependencies.
 467  
      *
 468  
      * @param relatedDependencies new value of relatedDependencies
 469  
      */
 470  
     public void setRelatedDependencies(Set<Dependency> relatedDependencies) {
 471  0
         this.relatedDependencies = relatedDependencies;
 472  0
     }
 473  
 
 474  
     /**
 475  
      * Adds a related dependency.
 476  
      *
 477  
      * @param dependency a reference to the related dependency
 478  
      */
 479  
     public void addRelatedDependency(Dependency dependency) {
 480  0
         relatedDependencies.add(dependency);
 481  0
     }
 482  
 
 483  
     /**
 484  
      * Implementation of the Comparable<Dependency> interface. The comparison is solely based on the file name.
 485  
      *
 486  
      * @param o a dependency to compare
 487  
      * @return an integer representing the natural ordering
 488  
      */
 489  
     public int compareTo(Dependency o) {
 490  58
         return this.getFileName().compareToIgnoreCase(o.getFileName());
 491  
     }
 492  
 
 493  
     /**
 494  
      * Implementation of the equals method.
 495  
      *
 496  
      * @param obj the object to compare
 497  
      * @return true if the objects are equal, otherwise false
 498  
      */
 499  
     @Override
 500  
     public boolean equals(Object obj) {
 501  0
         if (obj == null) {
 502  0
             return false;
 503  
         }
 504  0
         if (getClass() != obj.getClass()) {
 505  0
             return false;
 506  
         }
 507  0
         final Dependency other = (Dependency) obj;
 508  0
         if ((this.actualFilePath == null) ? (other.actualFilePath != null) : !this.actualFilePath.equals(other.actualFilePath)) {
 509  0
             return false;
 510  
         }
 511  0
         if ((this.filePath == null) ? (other.filePath != null) : !this.filePath.equals(other.filePath)) {
 512  0
             return false;
 513  
         }
 514  0
         if ((this.fileName == null) ? (other.fileName != null) : !this.fileName.equals(other.fileName)) {
 515  0
             return false;
 516  
         }
 517  0
         if ((this.fileExtension == null) ? (other.fileExtension != null) : !this.fileExtension.equals(other.fileExtension)) {
 518  0
             return false;
 519  
         }
 520  0
         if ((this.md5sum == null) ? (other.md5sum != null) : !this.md5sum.equals(other.md5sum)) {
 521  0
             return false;
 522  
         }
 523  0
         if ((this.sha1sum == null) ? (other.sha1sum != null) : !this.sha1sum.equals(other.sha1sum)) {
 524  0
             return false;
 525  
         }
 526  0
         if (this.identifiers != other.identifiers && (this.identifiers == null || !this.identifiers.equals(other.identifiers))) {
 527  0
             return false;
 528  
         }
 529  0
         if (this.vendorEvidence != other.vendorEvidence && (this.vendorEvidence == null || !this.vendorEvidence.equals(other.vendorEvidence))) {
 530  0
             return false;
 531  
         }
 532  0
         if (this.productEvidence != other.productEvidence && (this.productEvidence == null || !this.productEvidence.equals(other.productEvidence))) {
 533  0
             return false;
 534  
         }
 535  0
         if (this.versionEvidence != other.versionEvidence && (this.versionEvidence == null || !this.versionEvidence.equals(other.versionEvidence))) {
 536  0
             return false;
 537  
         }
 538  0
         if (this.analysisExceptions != other.analysisExceptions
 539  
                 && (this.analysisExceptions == null || !this.analysisExceptions.equals(other.analysisExceptions))) {
 540  0
             return false;
 541  
         }
 542  0
         if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
 543  0
             return false;
 544  
         }
 545  0
         if ((this.license == null) ? (other.license != null) : !this.license.equals(other.license)) {
 546  0
             return false;
 547  
         }
 548  0
         if (this.vulnerabilities != other.vulnerabilities && (this.vulnerabilities == null || !this.vulnerabilities.equals(other.vulnerabilities))) {
 549  0
             return false;
 550  
         }
 551  0
         if (this.relatedDependencies != other.relatedDependencies
 552  
                 && (this.relatedDependencies == null || !this.relatedDependencies.equals(other.relatedDependencies))) {
 553  0
             return false;
 554  
         }
 555  0
         return true;
 556  
     }
 557  
 
 558  
     /**
 559  
      * Generates the HashCode.
 560  
      *
 561  
      * @return the HashCode
 562  
      */
 563  
     @Override
 564  
     public int hashCode() {
 565  252
         int hash = 3;
 566  252
         hash = 47 * hash + (this.actualFilePath != null ? this.actualFilePath.hashCode() : 0);
 567  252
         hash = 47 * hash + (this.filePath != null ? this.filePath.hashCode() : 0);
 568  252
         hash = 47 * hash + (this.fileName != null ? this.fileName.hashCode() : 0);
 569  252
         hash = 47 * hash + (this.fileExtension != null ? this.fileExtension.hashCode() : 0);
 570  252
         hash = 47 * hash + (this.md5sum != null ? this.md5sum.hashCode() : 0);
 571  252
         hash = 47 * hash + (this.sha1sum != null ? this.sha1sum.hashCode() : 0);
 572  252
         hash = 47 * hash + (this.identifiers != null ? this.identifiers.hashCode() : 0);
 573  252
         hash = 47 * hash + (this.vendorEvidence != null ? this.vendorEvidence.hashCode() : 0);
 574  252
         hash = 47 * hash + (this.productEvidence != null ? this.productEvidence.hashCode() : 0);
 575  252
         hash = 47 * hash + (this.versionEvidence != null ? this.versionEvidence.hashCode() : 0);
 576  252
         hash = 47 * hash + (this.analysisExceptions != null ? this.analysisExceptions.hashCode() : 0);
 577  252
         hash = 47 * hash + (this.description != null ? this.description.hashCode() : 0);
 578  252
         hash = 47 * hash + (this.license != null ? this.license.hashCode() : 0);
 579  252
         hash = 47 * hash + (this.vulnerabilities != null ? this.vulnerabilities.hashCode() : 0);
 580  252
         hash = 47 * hash + (this.relatedDependencies != null ? this.relatedDependencies.hashCode() : 0);
 581  252
         return hash;
 582  
     }
 583  
 
 584  
     /**
 585  
      * Standard toString() implementation showing the filename, actualFilePath, and filePath.
 586  
      *
 587  
      * @return the string representation of the file
 588  
      */
 589  
     @Override
 590  
     public String toString() {
 591  0
         return "Dependency{ fileName='" + fileName + "', actualFilePath='" + actualFilePath + "', filePath='" + filePath + "'}";
 592  
     }
 593  
 }