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