Coverage Report - org.owasp.dependencycheck.dependency.Dependency
 
Classes in this File Line Coverage Branch Coverage Complexity
Dependency
61%
72/118
14%
17/120
2.42
 
 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  2
 public class Dependency implements Comparable<Dependency> {
 39  
 
 40  
     /**
 41  
      * The logger.
 42  
      */
 43  1
     private static final Logger LOGGER = Logger.getLogger(Dependency.class.getName());
 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  38
     public Dependency() {
 89  38
         vendorEvidence = new EvidenceCollection();
 90  38
         productEvidence = new EvidenceCollection();
 91  38
         versionEvidence = new EvidenceCollection();
 92  38
         identifiers = new TreeSet<Identifier>();
 93  38
         vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
 94  38
         suppressedIdentifiers = new TreeSet<Identifier>();
 95  38
         suppressedVulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
 96  38
     }
 97  
 
 98  
     /**
 99  
      * Constructs a new Dependency object.
 100  
      *
 101  
      * @param file the File to create the dependency object from.
 102  
      */
 103  
     public Dependency(File file) {
 104  17
         this();
 105  17
         this.actualFilePath = file.getPath();
 106  17
         this.filePath = this.actualFilePath;
 107  17
         this.fileName = file.getName();
 108  17
         this.fileExtension = FileUtils.getFileExtension(fileName);
 109  17
         determineHashes(file);
 110  17
     }
 111  
 
 112  
     /**
 113  
      * Returns the file name of the dependency.
 114  
      *
 115  
      * @return the file name of the dependency
 116  
      */
 117  
     public String getFileName() {
 118  
         return this.fileName;
 119  
     }
 120  
 
 121  
     /**
 122  
      * Returns the file name of the dependency with the backslash escaped for use in JavaScript. This is a complete hack
 123  
      * as I could not get the replace to work in the template itself.
 124  
      *
 125  
      * @return the file name of the dependency with the backslash escaped for use in JavaScript
 126  
      */
 127  
     public String getFileNameForJavaScript() {
 128  0
         return this.fileName.replace("\\", "\\\\");
 129  
     }
 130  
 
 131  
     /**
 132  
      * Sets the file name of the dependency.
 133  
      *
 134  
      * @param fileName the file name of the dependency
 135  
      */
 136  
     public void setFileName(String fileName) {
 137  
         this.fileName = fileName;
 138  
     }
 139  
 
 140  
     /**
 141  
      * Sets the actual file path of the dependency on disk.
 142  
      *
 143  
      * @param actualFilePath the file path of the dependency
 144  
      */
 145  
     public void setActualFilePath(String actualFilePath) {
 146  2
         this.actualFilePath = actualFilePath;
 147  2
         if (this.sha1sum == null) {
 148  2
             final File file = new File(this.actualFilePath);
 149  2
             determineHashes(file);
 150  
         }
 151  2
     }
 152  
 
 153  
     /**
 154  
      * Gets the file path of the dependency.
 155  
      *
 156  
      * @return the file path of the dependency
 157  
      */
 158  
     public String getActualFilePath() {
 159  
         return this.actualFilePath;
 160  
     }
 161  
 
 162  
     /**
 163  
      * Gets a reference to the File object.
 164  
      *
 165  
      * @return the File object
 166  
      */
 167  
     public File getActualFile() {
 168  2
         return new File(this.actualFilePath);
 169  
     }
 170  
 
 171  
     /**
 172  
      * Sets the file path of the dependency.
 173  
      *
 174  
      * @param filePath the file path of the dependency
 175  
      */
 176  
     public void setFilePath(String filePath) {
 177  
         this.filePath = filePath;
 178  
     }
 179  
 
 180  
     /**
 181  
      * The file name to display in reports.
 182  
      */
 183  38
     private String displayName = null;
 184  
 
 185  
     /**
 186  
      * Sets the file name to display in reports.
 187  
      *
 188  
      * @param displayName the name to display
 189  
      */
 190  
     public void setDisplayFileName(String displayName) {
 191  
         this.displayName = displayName;
 192  
     }
 193  
 
 194  
     /**
 195  
      * Returns the file name to display in reports; if no display file name has been set it will default to the actual
 196  
      * file name.
 197  
      *
 198  
      * @return the file name to display
 199  
      */
 200  
     public String getDisplayFileName() {
 201  0
         if (displayName == null) {
 202  0
             return this.fileName;
 203  
         }
 204  0
         return this.displayName;
 205  
     }
 206  
 
 207  
     /**
 208  
      * <p>
 209  
      * Gets the file path of the dependency.</p>
 210  
      * <p>
 211  
      * <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
 212  
      * obtained via the getActualFilePath().</p>
 213  
      *
 214  
      * @return the file path of the dependency
 215  
      */
 216  
     public String getFilePath() {
 217  
         return this.filePath;
 218  
     }
 219  
 
 220  
     /**
 221  
      * Sets the file name of the dependency.
 222  
      *
 223  
      * @param fileExtension the file name of the dependency
 224  
      */
 225  
     public void setFileExtension(String fileExtension) {
 226  
         this.fileExtension = fileExtension;
 227  
     }
 228  
 
 229  
     /**
 230  
      * Gets the file extension of the dependency.
 231  
      *
 232  
      * @return the file extension of the dependency
 233  
      */
 234  
     public String getFileExtension() {
 235  
         return this.fileExtension;
 236  
     }
 237  
 
 238  
     /**
 239  
      * Returns the MD5 Checksum of the dependency file.
 240  
      *
 241  
      * @return the MD5 Checksum
 242  
      */
 243  
     public String getMd5sum() {
 244  
         return this.md5sum;
 245  
     }
 246  
 
 247  
     /**
 248  
      * Sets the MD5 Checksum of the dependency.
 249  
      *
 250  
      * @param md5sum the MD5 Checksum
 251  
      */
 252  
     public void setMd5sum(String md5sum) {
 253  
         this.md5sum = md5sum;
 254  
     }
 255  
 
 256  
     /**
 257  
      * Returns the SHA1 Checksum of the dependency.
 258  
      *
 259  
      * @return the SHA1 Checksum
 260  
      */
 261  
     public String getSha1sum() {
 262  
         return this.sha1sum;
 263  
     }
 264  
 
 265  
     /**
 266  
      * Sets the SHA1 Checksum of the dependency.
 267  
      *
 268  
      * @param sha1sum the SHA1 Checksum
 269  
      */
 270  
     public void setSha1sum(String sha1sum) {
 271  
         this.sha1sum = sha1sum;
 272  
     }
 273  
 
 274  
     /**
 275  
      * Returns a List of Identifiers.
 276  
      *
 277  
      * @return an ArrayList of Identifiers
 278  
      */
 279  
     public Set<Identifier> getIdentifiers() {
 280  
         return this.identifiers;
 281  
     }
 282  
 
 283  
     /**
 284  
      * Sets a List of Identifiers.
 285  
      *
 286  
      * @param identifiers A list of Identifiers
 287  
      */
 288  
     public void setIdentifiers(Set<Identifier> identifiers) {
 289  
         this.identifiers = identifiers;
 290  
     }
 291  
 
 292  
     /**
 293  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 294  
      *
 295  
      * @param type the type of identifier (such as CPE)
 296  
      * @param value the value of the identifier
 297  
      * @param url the URL of the identifier
 298  
      */
 299  
     public void addIdentifier(String type, String value, String url) {
 300  11
         final Identifier i = new Identifier(type, value, url);
 301  11
         this.identifiers.add(i);
 302  11
     }
 303  
 
 304  
     /**
 305  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 306  
      *
 307  
      * @param type the type of identifier (such as CPE)
 308  
      * @param value the value of the identifier
 309  
      * @param url the URL of the identifier
 310  
      * @param confidence the confidence in the Identifier being accurate
 311  
      */
 312  
     public void addIdentifier(String type, String value, String url, Confidence confidence) {
 313  1
         final Identifier i = new Identifier(type, value, url);
 314  1
         i.setConfidence(confidence);
 315  1
         this.identifiers.add(i);
 316  1
     }
 317  
 
 318  
     /**
 319  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 320  
      *
 321  
      * @param identifier the identifier to add
 322  
      */
 323  
     public void addIdentifier(Identifier identifier) {
 324  4
         this.identifiers.add(identifier);
 325  4
     }
 326  
     /**
 327  
      * A set of identifiers that have been suppressed.
 328  
      */
 329  
     private Set<Identifier> suppressedIdentifiers;
 330  
 
 331  
     /**
 332  
      * Get the value of suppressedIdentifiers.
 333  
      *
 334  
      * @return the value of suppressedIdentifiers
 335  
      */
 336  
     public Set<Identifier> getSuppressedIdentifiers() {
 337  
         return suppressedIdentifiers;
 338  
     }
 339  
 
 340  
     /**
 341  
      * Set the value of suppressedIdentifiers.
 342  
      *
 343  
      * @param suppressedIdentifiers new value of suppressedIdentifiers
 344  
      */
 345  
     public void setSuppressedIdentifiers(Set<Identifier> suppressedIdentifiers) {
 346  
         this.suppressedIdentifiers = suppressedIdentifiers;
 347  
     }
 348  
 
 349  
     /**
 350  
      * Adds an identifier to the list of suppressed identifiers.
 351  
      *
 352  
      * @param identifier an identifier that was suppressed.
 353  
      */
 354  
     public void addSuppressedIdentifier(Identifier identifier) {
 355  7
         this.suppressedIdentifiers.add(identifier);
 356  7
     }
 357  
 
 358  
     /**
 359  
      * A set of vulnerabilities that have been suppressed.
 360  
      */
 361  
     private SortedSet<Vulnerability> suppressedVulnerabilities;
 362  
 
 363  
     /**
 364  
      * Get the value of suppressedVulnerabilities.
 365  
      *
 366  
      * @return the value of suppressedVulnerabilities
 367  
      */
 368  
     public SortedSet<Vulnerability> getSuppressedVulnerabilities() {
 369  
         return suppressedVulnerabilities;
 370  
     }
 371  
 
 372  
     /**
 373  
      * Set the value of suppressedVulnerabilities.
 374  
      *
 375  
      * @param suppressedVulnerabilities new value of suppressedVulnerabilities
 376  
      */
 377  
     public void setSuppressedVulnerabilities(SortedSet<Vulnerability> suppressedVulnerabilities) {
 378  
         this.suppressedVulnerabilities = suppressedVulnerabilities;
 379  
     }
 380  
 
 381  
     /**
 382  
      * Adds a vulnerability to the set of suppressed vulnerabilities.
 383  
      *
 384  
      * @param vulnerability the vulnerability that was suppressed
 385  
      */
 386  
     public void addSuppressedVulnerability(Vulnerability vulnerability) {
 387  3
         this.suppressedVulnerabilities.add(vulnerability);
 388  3
     }
 389  
 
 390  
     /**
 391  
      * Returns the evidence used to identify this dependency.
 392  
      *
 393  
      * @return an EvidenceCollection.
 394  
      */
 395  
     public EvidenceCollection getEvidence() {
 396  3
         return EvidenceCollection.merge(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 397  
     }
 398  
 
 399  
     /**
 400  
      * Returns the evidence used to identify this dependency.
 401  
      *
 402  
      * @return an EvidenceCollection.
 403  
      */
 404  
     public Set<Evidence> getEvidenceForDisplay() {
 405  0
         return EvidenceCollection.mergeForDisplay(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 406  
     }
 407  
 
 408  
     /**
 409  
      * Returns the evidence used to identify this dependency.
 410  
      *
 411  
      * @return an EvidenceCollection.
 412  
      */
 413  
     public EvidenceCollection getEvidenceUsed() {
 414  1
         return EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 415  
     }
 416  
 
 417  
     /**
 418  
      * Gets the Vendor Evidence.
 419  
      *
 420  
      * @return an EvidenceCollection.
 421  
      */
 422  
     public EvidenceCollection getVendorEvidence() {
 423  
         return this.vendorEvidence;
 424  
     }
 425  
 
 426  
     /**
 427  
      * Gets the Product Evidence.
 428  
      *
 429  
      * @return an EvidenceCollection.
 430  
      */
 431  
     public EvidenceCollection getProductEvidence() {
 432  
         return this.productEvidence;
 433  
     }
 434  
 
 435  
     /**
 436  
      * Gets the Version Evidence.
 437  
      *
 438  
      * @return an EvidenceCollection.
 439  
      */
 440  
     public EvidenceCollection getVersionEvidence() {
 441  
         return this.versionEvidence;
 442  
     }
 443  
     /**
 444  
      * The description of the JAR file.
 445  
      */
 446  
     private String description;
 447  
 
 448  
     /**
 449  
      * Get the value of description.
 450  
      *
 451  
      * @return the value of description
 452  
      */
 453  
     public String getDescription() {
 454  
         return description;
 455  
     }
 456  
 
 457  
     /**
 458  
      * Set the value of description.
 459  
      *
 460  
      * @param description new value of description
 461  
      */
 462  
     public void setDescription(String description) {
 463  
         this.description = description;
 464  
     }
 465  
     /**
 466  
      * The license that this dependency uses.
 467  
      */
 468  
     private String license;
 469  
 
 470  
     /**
 471  
      * Get the value of license.
 472  
      *
 473  
      * @return the value of license
 474  
      */
 475  
     public String getLicense() {
 476  
         return license;
 477  
     }
 478  
 
 479  
     /**
 480  
      * Set the value of license.
 481  
      *
 482  
      * @param license new value of license
 483  
      */
 484  
     public void setLicense(String license) {
 485  
         this.license = license;
 486  
     }
 487  
     /**
 488  
      * A list of vulnerabilities for this dependency.
 489  
      */
 490  
     private SortedSet<Vulnerability> vulnerabilities;
 491  
 
 492  
     /**
 493  
      * Get the list of vulnerabilities.
 494  
      *
 495  
      * @return the list of vulnerabilities
 496  
      */
 497  
     public SortedSet<Vulnerability> getVulnerabilities() {
 498  
         return vulnerabilities;
 499  
     }
 500  
 
 501  
     /**
 502  
      * Set the value of vulnerabilities.
 503  
      *
 504  
      * @param vulnerabilities new value of vulnerabilities
 505  
      */
 506  
     public void setVulnerabilities(SortedSet<Vulnerability> vulnerabilities) {
 507  
         this.vulnerabilities = vulnerabilities;
 508  
     }
 509  
 
 510  
     /**
 511  
      * Determines the sha1 and md5 sum for the given file.
 512  
      *
 513  
      * @param file the file to create checksums for
 514  
      */
 515  
     private void determineHashes(File file) {
 516  19
         String md5 = null;
 517  19
         String sha1 = null;
 518  
         try {
 519  19
             md5 = Checksum.getMD5Checksum(file);
 520  16
             sha1 = Checksum.getSHA1Checksum(file);
 521  3
         } catch (IOException ex) {
 522  3
             final String msg = String.format("Unable to read '%s' to determine hashes.", file.getName());
 523  3
             LOGGER.log(Level.WARNING, msg);
 524  3
             LOGGER.log(Level.FINE, null, ex);
 525  0
         } catch (NoSuchAlgorithmException ex) {
 526  0
             final String msg = "Unable to use MD5 of SHA1 checksums.";
 527  0
             LOGGER.log(Level.WARNING, msg);
 528  0
             LOGGER.log(Level.FINE, null, ex);
 529  19
         }
 530  19
         this.setMd5sum(md5);
 531  19
         this.setSha1sum(sha1);
 532  19
     }
 533  
 
 534  
     /**
 535  
      * Adds a vulnerability to the dependency.
 536  
      *
 537  
      * @param vulnerability a vulnerability outlining a vulnerability.
 538  
      */
 539  
     public void addVulnerability(Vulnerability vulnerability) {
 540  3
         this.vulnerabilities.add(vulnerability);
 541  3
     }
 542  
     /**
 543  
      * A collection of related dependencies.
 544  
      */
 545  38
     private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
 546  
 
 547  
     /**
 548  
      * Get the value of relatedDependencies.
 549  
      *
 550  
      * @return the value of relatedDependencies
 551  
      */
 552  
     public Set<Dependency> getRelatedDependencies() {
 553  
         return relatedDependencies;
 554  
     }
 555  
 
 556  
     /**
 557  
      * Set the value of relatedDependencies.
 558  
      *
 559  
      * @param relatedDependencies new value of relatedDependencies
 560  
      */
 561  
     public void setRelatedDependencies(Set<Dependency> relatedDependencies) {
 562  
         this.relatedDependencies = relatedDependencies;
 563  
     }
 564  
 
 565  
     /**
 566  
      * Adds a related dependency.
 567  
      *
 568  
      * @param dependency a reference to the related dependency
 569  
      */
 570  
     public void addRelatedDependency(Dependency dependency) {
 571  0
         relatedDependencies.add(dependency);
 572  0
     }
 573  
 
 574  
     /**
 575  
      * Implementation of the Comparable<Dependency> interface. The comparison is solely based on the file name.
 576  
      *
 577  
      * @param o a dependency to compare
 578  
      * @return an integer representing the natural ordering
 579  
      */
 580  
     public int compareTo(Dependency o) {
 581  2
         return this.getFileName().compareToIgnoreCase(o.getFileName());
 582  
     }
 583  
 
 584  
     /**
 585  
      * Implementation of the equals method.
 586  
      *
 587  
      * @param obj the object to compare
 588  
      * @return true if the objects are equal, otherwise false
 589  
      */
 590  
     @Override
 591  
     public boolean equals(Object obj) {
 592  0
         if (obj == null) {
 593  0
             return false;
 594  
         }
 595  0
         if (getClass() != obj.getClass()) {
 596  0
             return false;
 597  
         }
 598  0
         final Dependency other = (Dependency) obj;
 599  0
         if ((this.actualFilePath == null) ? (other.actualFilePath != null) : !this.actualFilePath.equals(other.actualFilePath)) {
 600  0
             return false;
 601  
         }
 602  0
         if ((this.filePath == null) ? (other.filePath != null) : !this.filePath.equals(other.filePath)) {
 603  0
             return false;
 604  
         }
 605  0
         if ((this.fileName == null) ? (other.fileName != null) : !this.fileName.equals(other.fileName)) {
 606  0
             return false;
 607  
         }
 608  0
         if ((this.fileExtension == null) ? (other.fileExtension != null) : !this.fileExtension.equals(other.fileExtension)) {
 609  0
             return false;
 610  
         }
 611  0
         if ((this.md5sum == null) ? (other.md5sum != null) : !this.md5sum.equals(other.md5sum)) {
 612  0
             return false;
 613  
         }
 614  0
         if ((this.sha1sum == null) ? (other.sha1sum != null) : !this.sha1sum.equals(other.sha1sum)) {
 615  0
             return false;
 616  
         }
 617  0
         if (this.identifiers != other.identifiers && (this.identifiers == null || !this.identifiers.equals(other.identifiers))) {
 618  0
             return false;
 619  
         }
 620  0
         if (this.vendorEvidence != other.vendorEvidence && (this.vendorEvidence == null || !this.vendorEvidence.equals(other.vendorEvidence))) {
 621  0
             return false;
 622  
         }
 623  0
         if (this.productEvidence != other.productEvidence && (this.productEvidence == null || !this.productEvidence.equals(other.productEvidence))) {
 624  0
             return false;
 625  
         }
 626  0
         if (this.versionEvidence != other.versionEvidence && (this.versionEvidence == null || !this.versionEvidence.equals(other.versionEvidence))) {
 627  0
             return false;
 628  
         }
 629  0
         if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
 630  0
             return false;
 631  
         }
 632  0
         if ((this.license == null) ? (other.license != null) : !this.license.equals(other.license)) {
 633  0
             return false;
 634  
         }
 635  0
         if (this.vulnerabilities != other.vulnerabilities && (this.vulnerabilities == null || !this.vulnerabilities.equals(other.vulnerabilities))) {
 636  0
             return false;
 637  
         }
 638  0
         if (this.relatedDependencies != other.relatedDependencies
 639  
                 && (this.relatedDependencies == null || !this.relatedDependencies.equals(other.relatedDependencies))) {
 640  0
             return false;
 641  
         }
 642  0
         return true;
 643  
     }
 644  
 
 645  
     /**
 646  
      * Generates the HashCode.
 647  
      *
 648  
      * @return the HashCode
 649  
      */
 650  
     @Override
 651  
     public int hashCode() {
 652  26
         int hash = 3;
 653  26
         hash = 47 * hash + (this.actualFilePath != null ? this.actualFilePath.hashCode() : 0);
 654  26
         hash = 47 * hash + (this.filePath != null ? this.filePath.hashCode() : 0);
 655  26
         hash = 47 * hash + (this.fileName != null ? this.fileName.hashCode() : 0);
 656  26
         hash = 47 * hash + (this.fileExtension != null ? this.fileExtension.hashCode() : 0);
 657  26
         hash = 47 * hash + (this.md5sum != null ? this.md5sum.hashCode() : 0);
 658  26
         hash = 47 * hash + (this.sha1sum != null ? this.sha1sum.hashCode() : 0);
 659  26
         hash = 47 * hash + (this.identifiers != null ? this.identifiers.hashCode() : 0);
 660  26
         hash = 47 * hash + (this.vendorEvidence != null ? this.vendorEvidence.hashCode() : 0);
 661  26
         hash = 47 * hash + (this.productEvidence != null ? this.productEvidence.hashCode() : 0);
 662  26
         hash = 47 * hash + (this.versionEvidence != null ? this.versionEvidence.hashCode() : 0);
 663  26
         hash = 47 * hash + (this.description != null ? this.description.hashCode() : 0);
 664  26
         hash = 47 * hash + (this.license != null ? this.license.hashCode() : 0);
 665  26
         hash = 47 * hash + (this.vulnerabilities != null ? this.vulnerabilities.hashCode() : 0);
 666  26
         hash = 47 * hash + (this.relatedDependencies != null ? this.relatedDependencies.hashCode() : 0);
 667  26
         return hash;
 668  
     }
 669  
 
 670  
     /**
 671  
      * Standard toString() implementation showing the filename, actualFilePath, and filePath.
 672  
      *
 673  
      * @return the string representation of the file
 674  
      */
 675  
     @Override
 676  
     public String toString() {
 677  0
         return "Dependency{ fileName='" + fileName + "', actualFilePath='" + actualFilePath + "', filePath='" + filePath + "'}";
 678  
     }
 679  
 }