Coverage Report - org.owasp.dependencycheck.dependency.Dependency
 
Classes in this File Line Coverage Branch Coverage Complexity
Dependency
61%
91/148
14%
18/126
2.721
 
 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  32
 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  69
     public Dependency() {
 87  69
         vendorEvidence = new EvidenceCollection();
 88  69
         productEvidence = new EvidenceCollection();
 89  69
         versionEvidence = new EvidenceCollection();
 90  69
         identifiers = new TreeSet<Identifier>();
 91  69
         vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
 92  69
     }
 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  48
         this();
 101  48
         this.actualFilePath = file.getPath();
 102  48
         this.filePath = this.actualFilePath;
 103  48
         this.fileName = file.getName();
 104  48
         this.fileExtension = FileUtils.getFileExtension(fileName);
 105  48
         determineHashes(file);
 106  48
     }
 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  208
         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  26
         this.fileName = fileName;
 124  26
     }
 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  2
         this.actualFilePath = actualFilePath;
 133  2
         if (this.sha1sum == null) {
 134  2
             final File file = new File(this.actualFilePath);
 135  2
             determineHashes(file);
 136  
         }
 137  2
     }
 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  167
         return this.actualFilePath;
 146  
     }
 147  
 
 148  
     /**
 149  
      * Gets a reference to the File object.
 150  
      *
 151  
      * @return the File object.
 152  
      */
 153  
     public File getActualFile() {
 154  0
         return new File(this.actualFilePath);
 155  
     }
 156  
 
 157  
     /**
 158  
      * Sets the file path of the dependency.
 159  
      *
 160  
      * @param filePath the file path of the dependency.
 161  
      */
 162  
     public void setFilePath(String filePath) {
 163  21
         this.filePath = filePath;
 164  21
     }
 165  
 
 166  
     /**
 167  
      * <p>
 168  
      * Gets the file path of the dependency.</p>
 169  
      * <p>
 170  
      * <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
 171  
      * obtained via the getActualFilePath().</p>
 172  
      *
 173  
      * @return the file path of the dependency.
 174  
      */
 175  
     public String getFilePath() {
 176  28
         return this.filePath;
 177  
     }
 178  
 
 179  
     /**
 180  
      * Sets the file name of the dependency.
 181  
      *
 182  
      * @param fileExtension the file name of the dependency.
 183  
      */
 184  
     public void setFileExtension(String fileExtension) {
 185  2
         this.fileExtension = fileExtension;
 186  2
     }
 187  
 
 188  
     /**
 189  
      * Gets the file extension of the dependency.
 190  
      *
 191  
      * @return the file extension of the dependency.
 192  
      */
 193  
     public String getFileExtension() {
 194  125
         return this.fileExtension;
 195  
     }
 196  
 
 197  
     /**
 198  
      * Returns the MD5 Checksum of the dependency file.
 199  
      *
 200  
      * @return the MD5 Checksum
 201  
      */
 202  
     public String getMd5sum() {
 203  5
         return this.md5sum;
 204  
     }
 205  
 
 206  
     /**
 207  
      * Sets the MD5 Checksum of the dependency.
 208  
      *
 209  
      * @param md5sum the MD5 Checksum
 210  
      */
 211  
     public void setMd5sum(String md5sum) {
 212  51
         this.md5sum = md5sum;
 213  51
     }
 214  
 
 215  
     /**
 216  
      * Returns the SHA1 Checksum of the dependency.
 217  
      *
 218  
      * @return the SHA1 Checksum
 219  
      */
 220  
     public String getSha1sum() {
 221  20
         return this.sha1sum;
 222  
     }
 223  
 
 224  
     /**
 225  
      * Sets the SHA1 Checksum of the dependency.
 226  
      *
 227  
      * @param sha1sum the SHA1 Checksum
 228  
      */
 229  
     public void setSha1sum(String sha1sum) {
 230  53
         this.sha1sum = sha1sum;
 231  53
     }
 232  
 
 233  
     /**
 234  
      * Returns a List of Identifiers.
 235  
      *
 236  
      * @return an ArrayList of Identifiers.
 237  
      */
 238  
     public Set<Identifier> getIdentifiers() {
 239  142
         return this.identifiers;
 240  
     }
 241  
 
 242  
     /**
 243  
      * Sets a List of Identifiers.
 244  
      *
 245  
      * @param identifiers A list of Identifiers.
 246  
      */
 247  
     public void setIdentifiers(Set<Identifier> identifiers) {
 248  1
         this.identifiers = identifiers;
 249  1
     }
 250  
 
 251  
     /**
 252  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 253  
      *
 254  
      * @param type the type of identifier (such as CPE)
 255  
      * @param value the value of the identifier
 256  
      * @param url the URL of the identifier
 257  
      */
 258  
     public void addIdentifier(String type, String value, String url) {
 259  6
         final Identifier i = new Identifier(type, value, url);
 260  6
         this.identifiers.add(i);
 261  6
     }
 262  
 
 263  
     /**
 264  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 265  
      *
 266  
      * @param type the type of identifier (such as CPE)
 267  
      * @param value the value of the identifier
 268  
      * @param url the URL of the identifier
 269  
      * @param confidence the confidence in the Identifier being accurate
 270  
      */
 271  
     public void addIdentifier(String type, String value, String url, Confidence confidence) {
 272  0
         final Identifier i = new Identifier(type, value, url);
 273  0
         i.setConfidence(confidence);
 274  0
         this.identifiers.add(i);
 275  0
     }
 276  
 
 277  
     /**
 278  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 279  
      *
 280  
      * @param identifier the identifier to add
 281  
      */
 282  
     public void addIdentifier(Identifier identifier) {
 283  88
         this.identifiers.add(identifier);
 284  88
     }
 285  
 
 286  
     /**
 287  
      * Returns the evidence used to identify this dependency.
 288  
      *
 289  
      * @return an EvidenceCollection.
 290  
      */
 291  
     public EvidenceCollection getEvidence() {
 292  1
         return EvidenceCollection.merge(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 293  
     }
 294  
 
 295  
     /**
 296  
      * Returns the evidence used to identify this dependency.
 297  
      *
 298  
      * @return an EvidenceCollection.
 299  
      */
 300  
     public EvidenceCollection getEvidenceUsed() {
 301  4
         return EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 302  
     }
 303  
 
 304  
     /**
 305  
      * Gets the Vendor Evidence.
 306  
      *
 307  
      * @return an EvidenceCollection.
 308  
      */
 309  
     public EvidenceCollection getVendorEvidence() {
 310  451
         return this.vendorEvidence;
 311  
     }
 312  
 
 313  
     /**
 314  
      * Gets the Product Evidence.
 315  
      *
 316  
      * @return an EvidenceCollection.
 317  
      */
 318  
     public EvidenceCollection getProductEvidence() {
 319  1087
         return this.productEvidence;
 320  
     }
 321  
 
 322  
     /**
 323  
      * Gets the Version Evidence.
 324  
      *
 325  
      * @return an EvidenceCollection.
 326  
      */
 327  
     public EvidenceCollection getVersionEvidence() {
 328  460
         return this.versionEvidence;
 329  
     }
 330  
     /**
 331  
      * A list of exceptions that occurred during analysis of this dependency.
 332  
      */
 333  69
     private List<Exception> analysisExceptions = new ArrayList<Exception>();
 334  
 
 335  
     /**
 336  
      * Get the value of analysisExceptions.
 337  
      *
 338  
      * @return the value of analysisExceptions
 339  
      */
 340  
     public List<Exception> getAnalysisExceptions() {
 341  0
         return analysisExceptions;
 342  
     }
 343  
 
 344  
     /**
 345  
      * Set the value of analysisExceptions.
 346  
      *
 347  
      * @param analysisExceptions new value of analysisExceptions
 348  
      */
 349  
     public void setAnalysisExceptions(List<Exception> analysisExceptions) {
 350  0
         this.analysisExceptions = analysisExceptions;
 351  0
     }
 352  
 
 353  
     /**
 354  
      * Adds an exception to the analysis exceptions collection.
 355  
      *
 356  
      * @param ex an exception.
 357  
      */
 358  
     public void addAnalysisException(Exception ex) {
 359  0
         this.analysisExceptions.add(ex);
 360  0
     }
 361  
     /**
 362  
      * The description of the JAR file.
 363  
      */
 364  
     private String description;
 365  
 
 366  
     /**
 367  
      * Get the value of description.
 368  
      *
 369  
      * @return the value of description
 370  
      */
 371  
     public String getDescription() {
 372  15
         return description;
 373  
     }
 374  
 
 375  
     /**
 376  
      * Set the value of description.
 377  
      *
 378  
      * @param description new value of description
 379  
      */
 380  
     public void setDescription(String description) {
 381  19
         this.description = description;
 382  19
     }
 383  
     /**
 384  
      * The license that this dependency uses.
 385  
      */
 386  
     private String license;
 387  
 
 388  
     /**
 389  
      * Get the value of license.
 390  
      *
 391  
      * @return the value of license
 392  
      */
 393  
     public String getLicense() {
 394  11
         return license;
 395  
     }
 396  
 
 397  
     /**
 398  
      * Set the value of license.
 399  
      *
 400  
      * @param license new value of license
 401  
      */
 402  
     public void setLicense(String license) {
 403  7
         this.license = license;
 404  7
     }
 405  
     /**
 406  
      * A list of vulnerabilities for this dependency.
 407  
      */
 408  
     private SortedSet<Vulnerability> vulnerabilities;
 409  
 
 410  
     /**
 411  
      * Get the list of vulnerabilities.
 412  
      *
 413  
      * @return the list of vulnerabilities
 414  
      */
 415  
     public SortedSet<Vulnerability> getVulnerabilities() {
 416  28
         return vulnerabilities;
 417  
     }
 418  
 
 419  
     /**
 420  
      * Set the value of vulnerabilities.
 421  
      *
 422  
      * @param vulnerabilities new value of vulnerabilities
 423  
      */
 424  
     public void setVulnerabilities(SortedSet<Vulnerability> vulnerabilities) {
 425  0
         this.vulnerabilities = vulnerabilities;
 426  0
     }
 427  
 
 428  
     /**
 429  
      * Determines the sha1 and md5 sum for the given file.
 430  
      *
 431  
      * @param file the file to create checksums for
 432  
      */
 433  
     private void determineHashes(File file) {
 434  50
         String md5 = null;
 435  50
         String sha1 = null;
 436  
         try {
 437  50
             md5 = Checksum.getMD5Checksum(file);
 438  48
             sha1 = Checksum.getSHA1Checksum(file);
 439  2
         } catch (IOException ex) {
 440  2
             final String msg = String.format("Unable to read '%s' to determine hashes.", file.getName());
 441  2
             Logger.getLogger(Dependency.class.getName()).log(Level.WARNING, msg);
 442  2
             Logger.getLogger(Dependency.class.getName()).log(Level.FINE, null, ex);
 443  0
         } catch (NoSuchAlgorithmException ex) {
 444  0
             final String msg = "Unable to use MD5 of SHA1 checksums.";
 445  0
             Logger.getLogger(Dependency.class.getName()).log(Level.WARNING, msg);
 446  0
             Logger.getLogger(Dependency.class.getName()).log(Level.FINE, null, ex);
 447  50
         }
 448  50
         this.setMd5sum(md5);
 449  50
         this.setSha1sum(sha1);
 450  50
     }
 451  
 
 452  
     /**
 453  
      * Adds a vulnerability to the dependency.
 454  
      *
 455  
      * @param vulnerability a vulnerability outlining a vulnerability.
 456  
      */
 457  
     public void addVulnerability(Vulnerability vulnerability) {
 458  3
         this.vulnerabilities.add(vulnerability);
 459  3
     }
 460  
     /**
 461  
      * A collection of related dependencies.
 462  
      */
 463  69
     private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
 464  
 
 465  
     /**
 466  
      * Get the value of relatedDependencies.
 467  
      *
 468  
      * @return the value of relatedDependencies
 469  
      */
 470  
     public Set<Dependency> getRelatedDependencies() {
 471  4
         return relatedDependencies;
 472  
     }
 473  
 
 474  
     /**
 475  
      * Set the value of relatedDependencies.
 476  
      *
 477  
      * @param relatedDependencies new value of relatedDependencies
 478  
      */
 479  
     public void setRelatedDependencies(Set<Dependency> relatedDependencies) {
 480  0
         this.relatedDependencies = relatedDependencies;
 481  0
     }
 482  
 
 483  
     /**
 484  
      * Adds a related dependency.
 485  
      *
 486  
      * @param dependency a reference to the related dependency
 487  
      */
 488  
     public void addRelatedDependency(Dependency dependency) {
 489  0
         relatedDependencies.add(dependency);
 490  0
     }
 491  
 
 492  
     /**
 493  
      * Implementation of the Comparable<Dependency> interface. The comparison is solely based on the file name.
 494  
      *
 495  
      * @param o a dependency to compare
 496  
      * @return an integer representing the natural ordering
 497  
      */
 498  
     public int compareTo(Dependency o) {
 499  32
         return this.getFileName().compareToIgnoreCase(o.getFileName());
 500  
     }
 501  
 
 502  
     /**
 503  
      * Implementation of the equals method.
 504  
      *
 505  
      * @param obj the object to compare
 506  
      * @return true if the objects are equal, otherwise false
 507  
      */
 508  
     @Override
 509  
     public boolean equals(Object obj) {
 510  0
         if (obj == null) {
 511  0
             return false;
 512  
         }
 513  0
         if (getClass() != obj.getClass()) {
 514  0
             return false;
 515  
         }
 516  0
         final Dependency other = (Dependency) obj;
 517  0
         if ((this.actualFilePath == null) ? (other.actualFilePath != null) : !this.actualFilePath.equals(other.actualFilePath)) {
 518  0
             return false;
 519  
         }
 520  0
         if ((this.filePath == null) ? (other.filePath != null) : !this.filePath.equals(other.filePath)) {
 521  0
             return false;
 522  
         }
 523  0
         if ((this.fileName == null) ? (other.fileName != null) : !this.fileName.equals(other.fileName)) {
 524  0
             return false;
 525  
         }
 526  0
         if ((this.fileExtension == null) ? (other.fileExtension != null) : !this.fileExtension.equals(other.fileExtension)) {
 527  0
             return false;
 528  
         }
 529  0
         if ((this.md5sum == null) ? (other.md5sum != null) : !this.md5sum.equals(other.md5sum)) {
 530  0
             return false;
 531  
         }
 532  0
         if ((this.sha1sum == null) ? (other.sha1sum != null) : !this.sha1sum.equals(other.sha1sum)) {
 533  0
             return false;
 534  
         }
 535  0
         if (this.identifiers != other.identifiers && (this.identifiers == null || !this.identifiers.equals(other.identifiers))) {
 536  0
             return false;
 537  
         }
 538  0
         if (this.vendorEvidence != other.vendorEvidence && (this.vendorEvidence == null || !this.vendorEvidence.equals(other.vendorEvidence))) {
 539  0
             return false;
 540  
         }
 541  0
         if (this.productEvidence != other.productEvidence && (this.productEvidence == null || !this.productEvidence.equals(other.productEvidence))) {
 542  0
             return false;
 543  
         }
 544  0
         if (this.versionEvidence != other.versionEvidence && (this.versionEvidence == null || !this.versionEvidence.equals(other.versionEvidence))) {
 545  0
             return false;
 546  
         }
 547  0
         if (this.analysisExceptions != other.analysisExceptions
 548  
                 && (this.analysisExceptions == null || !this.analysisExceptions.equals(other.analysisExceptions))) {
 549  0
             return false;
 550  
         }
 551  0
         if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
 552  0
             return false;
 553  
         }
 554  0
         if ((this.license == null) ? (other.license != null) : !this.license.equals(other.license)) {
 555  0
             return false;
 556  
         }
 557  0
         if (this.vulnerabilities != other.vulnerabilities && (this.vulnerabilities == null || !this.vulnerabilities.equals(other.vulnerabilities))) {
 558  0
             return false;
 559  
         }
 560  0
         if (this.relatedDependencies != other.relatedDependencies
 561  
                 && (this.relatedDependencies == null || !this.relatedDependencies.equals(other.relatedDependencies))) {
 562  0
             return false;
 563  
         }
 564  0
         return true;
 565  
     }
 566  
 
 567  
     /**
 568  
      * Generates the HashCode.
 569  
      *
 570  
      * @return the HashCode
 571  
      */
 572  
     @Override
 573  
     public int hashCode() {
 574  135
         int hash = 3;
 575  135
         hash = 47 * hash + (this.actualFilePath != null ? this.actualFilePath.hashCode() : 0);
 576  135
         hash = 47 * hash + (this.filePath != null ? this.filePath.hashCode() : 0);
 577  135
         hash = 47 * hash + (this.fileName != null ? this.fileName.hashCode() : 0);
 578  135
         hash = 47 * hash + (this.fileExtension != null ? this.fileExtension.hashCode() : 0);
 579  135
         hash = 47 * hash + (this.md5sum != null ? this.md5sum.hashCode() : 0);
 580  135
         hash = 47 * hash + (this.sha1sum != null ? this.sha1sum.hashCode() : 0);
 581  135
         hash = 47 * hash + (this.identifiers != null ? this.identifiers.hashCode() : 0);
 582  135
         hash = 47 * hash + (this.vendorEvidence != null ? this.vendorEvidence.hashCode() : 0);
 583  135
         hash = 47 * hash + (this.productEvidence != null ? this.productEvidence.hashCode() : 0);
 584  135
         hash = 47 * hash + (this.versionEvidence != null ? this.versionEvidence.hashCode() : 0);
 585  135
         hash = 47 * hash + (this.analysisExceptions != null ? this.analysisExceptions.hashCode() : 0);
 586  135
         hash = 47 * hash + (this.description != null ? this.description.hashCode() : 0);
 587  135
         hash = 47 * hash + (this.license != null ? this.license.hashCode() : 0);
 588  135
         hash = 47 * hash + (this.vulnerabilities != null ? this.vulnerabilities.hashCode() : 0);
 589  135
         hash = 47 * hash + (this.relatedDependencies != null ? this.relatedDependencies.hashCode() : 0);
 590  135
         return hash;
 591  
     }
 592  
 
 593  
     /**
 594  
      * Standard toString() implementation showing the filename, actualFilePath, and filePath.
 595  
      *
 596  
      * @return the string representation of the file
 597  
      */
 598  
     @Override
 599  
     public String toString() {
 600  0
         return "Dependency{ fileName='" + fileName + "', actualFilePath='" + actualFilePath + "', filePath='" + filePath + "'}";
 601  
     }
 602  
 }