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