Coverage Report - org.owasp.dependencycheck.dependency.Dependency
 
Classes in this File Line Coverage Branch Coverage Complexity
Dependency
66%
103/154
26%
18/68
1.661
 
 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.io.Serializable;
 23  
 import java.security.NoSuchAlgorithmException;
 24  
 import java.util.ArrayList;
 25  
 import java.util.HashSet;
 26  
 import java.util.List;
 27  
 import java.util.Set;
 28  
 import java.util.SortedSet;
 29  
 import java.util.TreeSet;
 30  
 
 31  
 import org.apache.commons.lang.ObjectUtils;
 32  
 import org.owasp.dependencycheck.data.nexus.MavenArtifact;
 33  
 import org.owasp.dependencycheck.utils.Checksum;
 34  
 import org.slf4j.Logger;
 35  
 import org.slf4j.LoggerFactory;
 36  
 
 37  
 /**
 38  
  * A program dependency. This object is one of the core components within DependencyCheck. It is used to collect information about
 39  
  * the dependency in the form of evidence. The Evidence is then used to determine if there are any known, published,
 40  
  * vulnerabilities associated with the program dependency.
 41  
  *
 42  
  * @author Jeremy Long
 43  
  */
 44  16
 public class Dependency implements Serializable, Comparable<Dependency> {
 45  
 
 46  
     /**
 47  
      * The logger.
 48  
      */
 49  8
     private static final Logger LOGGER = LoggerFactory.getLogger(Dependency.class);
 50  
     /**
 51  
      * Used as starting point for generating the value in {@link #hashCode()}.
 52  
      */
 53  
     private static final int MAGIC_HASH_INIT_VALUE = 3;
 54  
     /**
 55  
      * Used as a multiplier for generating the value in {@link #hashCode()}.
 56  
      */
 57  
     private static final int MAGIC_HASH_MULTIPLIER = 47;
 58  
     /**
 59  
      * The actual file path of the dependency on disk.
 60  
      */
 61  
     private String actualFilePath;
 62  
     /**
 63  
      * The file path to display.
 64  
      */
 65  
     private String filePath;
 66  
     /**
 67  
      * The file name of the dependency.
 68  
      */
 69  
     private String fileName;
 70  
     /**
 71  
      * The md5 hash of the dependency.
 72  
      */
 73  
     private String md5sum;
 74  
     /**
 75  
      * The SHA1 hash of the dependency.
 76  
      */
 77  
     private String sha1sum;
 78  
     /**
 79  
      * A list of Identifiers.
 80  
      */
 81  
     private Set<Identifier> identifiers;
 82  
     /**
 83  
      * A collection of vendor evidence.
 84  
      */
 85  
     private final EvidenceCollection vendorEvidence;
 86  
     /**
 87  
      * A collection of product evidence.
 88  
      */
 89  
     private final EvidenceCollection productEvidence;
 90  
     /**
 91  
      * A collection of version evidence.
 92  
      */
 93  
     private final EvidenceCollection versionEvidence;
 94  
 
 95  
     /**
 96  
      * Constructs a new Dependency object.
 97  
      */
 98  432
     public Dependency() {
 99  432
         vendorEvidence = new EvidenceCollection();
 100  432
         productEvidence = new EvidenceCollection();
 101  432
         versionEvidence = new EvidenceCollection();
 102  432
         identifiers = new TreeSet<Identifier>();
 103  432
         vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
 104  432
         suppressedIdentifiers = new TreeSet<Identifier>();
 105  432
         suppressedVulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
 106  432
     }
 107  
 
 108  
     /**
 109  
      * Constructs a new Dependency object.
 110  
      *
 111  
      * @param file the File to create the dependency object from.
 112  
      */
 113  
     public Dependency(File file) {
 114  264
         this();
 115  264
         this.actualFilePath = file.getAbsolutePath();
 116  264
         this.filePath = this.actualFilePath;
 117  264
         this.fileName = file.getName();
 118  264
         determineHashes(file);
 119  264
     }
 120  
 
 121  
     /**
 122  
      * Returns the file name of the dependency.
 123  
      *
 124  
      * @return the file name of the dependency
 125  
      */
 126  
     public String getFileName() {
 127  288
         return this.fileName;
 128  
     }
 129  
 
 130  
     /**
 131  
      * Returns the file name of the dependency with the backslash escaped for use in JavaScript. This is a complete hack as I
 132  
      * could not get the replace to work in the template itself.
 133  
      *
 134  
      * @return the file name of the dependency with the backslash escaped for use in JavaScript
 135  
      */
 136  
     public String getFileNameForJavaScript() {
 137  0
         return this.fileName.replace("\\", "\\\\");
 138  
     }
 139  
 
 140  
     /**
 141  
      * Sets the file name of the dependency.
 142  
      *
 143  
      * @param fileName the file name of the dependency
 144  
      */
 145  
     public void setFileName(String fileName) {
 146  56
         this.fileName = fileName;
 147  56
     }
 148  
 
 149  
     /**
 150  
      * Sets the actual file path of the dependency on disk.
 151  
      *
 152  
      * @param actualFilePath the file path of the dependency
 153  
      */
 154  
     public void setActualFilePath(String actualFilePath) {
 155  16
         this.actualFilePath = actualFilePath;
 156  16
         if (this.sha1sum == null) {
 157  0
             final File file = new File(this.actualFilePath);
 158  0
             determineHashes(file);
 159  
         }
 160  16
     }
 161  
 
 162  
     /**
 163  
      * Gets the file path of the dependency.
 164  
      *
 165  
      * @return the file path of the dependency
 166  
      */
 167  
     public String getActualFilePath() {
 168  392
         return this.actualFilePath;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Gets a reference to the File object.
 173  
      *
 174  
      * @return the File object
 175  
      */
 176  
     public File getActualFile() {
 177  416
         return new File(this.actualFilePath);
 178  
     }
 179  
 
 180  
     /**
 181  
      * Sets the file path of the dependency.
 182  
      *
 183  
      * @param filePath the file path of the dependency
 184  
      */
 185  
     public void setFilePath(String filePath) {
 186  56
         this.filePath = filePath;
 187  56
     }
 188  
 
 189  
     /**
 190  
      * The file name to display in reports.
 191  
      */
 192  432
     private String displayName = null;
 193  
 
 194  
     /**
 195  
      * Sets the file name to display in reports.
 196  
      *
 197  
      * @param displayName the name to display
 198  
      */
 199  
     public void setDisplayFileName(String displayName) {
 200  128
         this.displayName = displayName;
 201  128
     }
 202  
 
 203  
     /**
 204  
      * Returns the file name to display in reports; if no display file name has been set it will default to the actual file name.
 205  
      *
 206  
      * @return the file name to display
 207  
      */
 208  
     public String getDisplayFileName() {
 209  80
         if (displayName == null) {
 210  0
             return this.fileName;
 211  
         }
 212  80
         return this.displayName;
 213  
     }
 214  
 
 215  
     /**
 216  
      * <p>
 217  
      * Gets the file path of the dependency.</p>
 218  
      * <p>
 219  
      * <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 obtained via
 220  
      * the getActualFilePath().</p>
 221  
      *
 222  
      * @return the file path of the dependency
 223  
      */
 224  
     public String getFilePath() {
 225  224
         return this.filePath;
 226  
     }
 227  
 
 228  
     /**
 229  
      * Returns the MD5 Checksum of the dependency file.
 230  
      *
 231  
      * @return the MD5 Checksum
 232  
      */
 233  
     public String getMd5sum() {
 234  16
         return this.md5sum;
 235  
     }
 236  
 
 237  
     /**
 238  
      * Sets the MD5 Checksum of the dependency.
 239  
      *
 240  
      * @param md5sum the MD5 Checksum
 241  
      */
 242  
     public void setMd5sum(String md5sum) {
 243  272
         this.md5sum = md5sum;
 244  272
     }
 245  
 
 246  
     /**
 247  
      * Returns the SHA1 Checksum of the dependency.
 248  
      *
 249  
      * @return the SHA1 Checksum
 250  
      */
 251  
     public String getSha1sum() {
 252  72
         return this.sha1sum;
 253  
     }
 254  
 
 255  
     /**
 256  
      * Sets the SHA1 Checksum of the dependency.
 257  
      *
 258  
      * @param sha1sum the SHA1 Checksum
 259  
      */
 260  
     public void setSha1sum(String sha1sum) {
 261  336
         this.sha1sum = sha1sum;
 262  336
     }
 263  
 
 264  
     /**
 265  
      * Returns a List of Identifiers.
 266  
      *
 267  
      * @return an ArrayList of Identifiers
 268  
      */
 269  
     public Set<Identifier> getIdentifiers() {
 270  880
         return this.identifiers;
 271  
     }
 272  
 
 273  
     /**
 274  
      * Sets a List of Identifiers.
 275  
      *
 276  
      * @param identifiers A list of Identifiers
 277  
      */
 278  
     public void setIdentifiers(Set<Identifier> identifiers) {
 279  8
         this.identifiers = identifiers;
 280  8
     }
 281  
 
 282  
     /**
 283  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 284  
      *
 285  
      * @param type the type of identifier (such as CPE)
 286  
      * @param value the value of the identifier
 287  
      * @param url the URL of the identifier
 288  
      */
 289  
     public void addIdentifier(String type, String value, String url) {
 290  88
         final Identifier i = new Identifier(type, value, url);
 291  88
         this.identifiers.add(i);
 292  88
     }
 293  
 
 294  
     /**
 295  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 296  
      *
 297  
      * @param type the type of identifier (such as CPE)
 298  
      * @param value the value of the identifier
 299  
      * @param url the URL of the identifier
 300  
      * @param confidence the confidence in the Identifier being accurate
 301  
      */
 302  
     public void addIdentifier(String type, String value, String url, Confidence confidence) {
 303  16
         final Identifier i = new Identifier(type, value, url);
 304  16
         i.setConfidence(confidence);
 305  16
         this.identifiers.add(i);
 306  16
     }
 307  
 
 308  
     /**
 309  
      * Adds the maven artifact as evidence.
 310  
      *
 311  
      * @param source The source of the evidence
 312  
      * @param mavenArtifact The maven artifact
 313  
      * @param confidence The confidence level of this evidence
 314  
      */
 315  
     public void addAsEvidence(String source, MavenArtifact mavenArtifact, Confidence confidence) {
 316  16
         if (mavenArtifact.getGroupId() != null && !mavenArtifact.getGroupId().isEmpty()) {
 317  8
             this.getVendorEvidence().addEvidence(source, "groupid", mavenArtifact.getGroupId(), confidence);
 318  
         }
 319  16
         if (mavenArtifact.getArtifactId() != null && !mavenArtifact.getArtifactId().isEmpty()) {
 320  8
             this.getProductEvidence().addEvidence(source, "artifactid", mavenArtifact.getArtifactId(), confidence);
 321  
         }
 322  16
         if (mavenArtifact.getVersion() != null && !mavenArtifact.getVersion().isEmpty()) {
 323  8
             this.getVersionEvidence().addEvidence(source, "version", mavenArtifact.getVersion(), confidence);
 324  
         }
 325  16
         if (mavenArtifact.getArtifactUrl() != null && !mavenArtifact.getArtifactUrl().isEmpty()) {
 326  8
             boolean found = false;
 327  8
             for (Identifier i : this.getIdentifiers()) {
 328  0
                 if ("maven".equals(i.getType()) && i.getValue().equals(mavenArtifact.toString())) {
 329  0
                     found = true;
 330  0
                     i.setConfidence(Confidence.HIGHEST);
 331  0
                     final String url = "http://search.maven.org/#search|ga|1|1%3A%22" + this.getSha1sum() + "%22";
 332  0
                     i.setUrl(url);
 333  
                     //i.setUrl(mavenArtifact.getArtifactUrl());
 334  0
                     LOGGER.debug("Already found identifier {}. Confidence set to highest", i.getValue());
 335  0
                     break;
 336  
                 }
 337  0
             }
 338  8
             if (!found) {
 339  8
                 LOGGER.debug("Adding new maven identifier {}", mavenArtifact.toString());
 340  8
                 this.addIdentifier("maven", mavenArtifact.toString(), mavenArtifact.getArtifactUrl(), Confidence.HIGHEST);
 341  
             }
 342  
         }
 343  16
     }
 344  
 
 345  
     /**
 346  
      * Adds an entry to the list of detected Identifiers for the dependency file.
 347  
      *
 348  
      * @param identifier the identifier to add
 349  
      */
 350  
     public void addIdentifier(Identifier identifier) {
 351  24
         this.identifiers.add(identifier);
 352  24
     }
 353  
 
 354  
     /**
 355  
      * A set of identifiers that have been suppressed.
 356  
      */
 357  
     private Set<Identifier> suppressedIdentifiers;
 358  
 
 359  
     /**
 360  
      * Get the value of suppressedIdentifiers.
 361  
      *
 362  
      * @return the value of suppressedIdentifiers
 363  
      */
 364  
     public Set<Identifier> getSuppressedIdentifiers() {
 365  40
         return suppressedIdentifiers;
 366  
     }
 367  
 
 368  
     /**
 369  
      * Set the value of suppressedIdentifiers.
 370  
      *
 371  
      * @param suppressedIdentifiers new value of suppressedIdentifiers
 372  
      */
 373  
     public void setSuppressedIdentifiers(Set<Identifier> suppressedIdentifiers) {
 374  0
         this.suppressedIdentifiers = suppressedIdentifiers;
 375  0
     }
 376  
 
 377  
     /**
 378  
      * Adds an identifier to the list of suppressed identifiers.
 379  
      *
 380  
      * @param identifier an identifier that was suppressed.
 381  
      */
 382  
     public void addSuppressedIdentifier(Identifier identifier) {
 383  32
         this.suppressedIdentifiers.add(identifier);
 384  32
     }
 385  
 
 386  
     /**
 387  
      * A set of vulnerabilities that have been suppressed.
 388  
      */
 389  
     private SortedSet<Vulnerability> suppressedVulnerabilities;
 390  
 
 391  
     /**
 392  
      * Get the value of suppressedVulnerabilities.
 393  
      *
 394  
      * @return the value of suppressedVulnerabilities
 395  
      */
 396  
     public SortedSet<Vulnerability> getSuppressedVulnerabilities() {
 397  24
         return suppressedVulnerabilities;
 398  
     }
 399  
 
 400  
     /**
 401  
      * Set the value of suppressedVulnerabilities.
 402  
      *
 403  
      * @param suppressedVulnerabilities new value of suppressedVulnerabilities
 404  
      */
 405  
     public void setSuppressedVulnerabilities(SortedSet<Vulnerability> suppressedVulnerabilities) {
 406  0
         this.suppressedVulnerabilities = suppressedVulnerabilities;
 407  0
     }
 408  
 
 409  
     /**
 410  
      * Adds a vulnerability to the set of suppressed vulnerabilities.
 411  
      *
 412  
      * @param vulnerability the vulnerability that was suppressed
 413  
      */
 414  
     public void addSuppressedVulnerability(Vulnerability vulnerability) {
 415  24
         this.suppressedVulnerabilities.add(vulnerability);
 416  24
     }
 417  
 
 418  
     /**
 419  
      * Returns the evidence used to identify this dependency.
 420  
      *
 421  
      * @return an EvidenceCollection.
 422  
      */
 423  
     public EvidenceCollection getEvidence() {
 424  88
         return EvidenceCollection.merge(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 425  
     }
 426  
 
 427  
     /**
 428  
      * Returns the evidence used to identify this dependency.
 429  
      *
 430  
      * @return an EvidenceCollection.
 431  
      */
 432  
     public Set<Evidence> getEvidenceForDisplay() {
 433  0
         return EvidenceCollection.mergeForDisplay(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 434  
     }
 435  
 
 436  
     /**
 437  
      * Returns the evidence used to identify this dependency.
 438  
      *
 439  
      * @return an EvidenceCollection.
 440  
      */
 441  
     public EvidenceCollection getEvidenceUsed() {
 442  8
         return EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
 443  
     }
 444  
 
 445  
     /**
 446  
      * Gets the Vendor Evidence.
 447  
      *
 448  
      * @return an EvidenceCollection.
 449  
      */
 450  
     public EvidenceCollection getVendorEvidence() {
 451  800
         return this.vendorEvidence;
 452  
     }
 453  
 
 454  
     /**
 455  
      * Gets the Product Evidence.
 456  
      *
 457  
      * @return an EvidenceCollection.
 458  
      */
 459  
     public EvidenceCollection getProductEvidence() {
 460  1128
         return this.productEvidence;
 461  
     }
 462  
 
 463  
     /**
 464  
      * Gets the Version Evidence.
 465  
      *
 466  
      * @return an EvidenceCollection.
 467  
      */
 468  
     public EvidenceCollection getVersionEvidence() {
 469  536
         return this.versionEvidence;
 470  
     }
 471  
 
 472  
     /**
 473  
      * The description of the JAR file.
 474  
      */
 475  
     private String description;
 476  
 
 477  
     /**
 478  
      * Get the value of description.
 479  
      *
 480  
      * @return the value of description
 481  
      */
 482  
     public String getDescription() {
 483  72
         return description;
 484  
     }
 485  
 
 486  
     /**
 487  
      * Set the value of description.
 488  
      *
 489  
      * @param description new value of description
 490  
      */
 491  
     public void setDescription(String description) {
 492  144
         this.description = description;
 493  144
     }
 494  
 
 495  
     /**
 496  
      * The license that this dependency uses.
 497  
      */
 498  
     private String license;
 499  
 
 500  
     /**
 501  
      * Get the value of license.
 502  
      *
 503  
      * @return the value of license
 504  
      */
 505  
     public String getLicense() {
 506  16
         return license;
 507  
     }
 508  
 
 509  
     /**
 510  
      * Set the value of license.
 511  
      *
 512  
      * @param license new value of license
 513  
      */
 514  
     public void setLicense(String license) {
 515  16
         this.license = license;
 516  16
     }
 517  
 
 518  
     /**
 519  
      * A list of vulnerabilities for this dependency.
 520  
      */
 521  
     private SortedSet<Vulnerability> vulnerabilities;
 522  
 
 523  
     /**
 524  
      * Get the list of vulnerabilities.
 525  
      *
 526  
      * @return the list of vulnerabilities
 527  
      */
 528  
     public SortedSet<Vulnerability> getVulnerabilities() {
 529  112
         return vulnerabilities;
 530  
     }
 531  
 
 532  
     /**
 533  
      * Set the value of vulnerabilities.
 534  
      *
 535  
      * @param vulnerabilities new value of vulnerabilities
 536  
      */
 537  
     public void setVulnerabilities(SortedSet<Vulnerability> vulnerabilities) {
 538  0
         this.vulnerabilities = vulnerabilities;
 539  0
     }
 540  
 
 541  
     /**
 542  
      * Determines the sha1 and md5 sum for the given file.
 543  
      *
 544  
      * @param file the file to create checksums for
 545  
      */
 546  
     private void determineHashes(File file) {
 547  264
         String md5 = null;
 548  264
         String sha1 = null;
 549  
         try {
 550  264
             md5 = Checksum.getMD5Checksum(file);
 551  256
             sha1 = Checksum.getSHA1Checksum(file);
 552  8
         } catch (IOException ex) {
 553  8
             LOGGER.warn("Unable to read '{}' to determine hashes.", file.getName());
 554  8
             LOGGER.debug("", ex);
 555  0
         } catch (NoSuchAlgorithmException ex) {
 556  0
             LOGGER.warn("Unable to use MD5 of SHA1 checksums.");
 557  0
             LOGGER.debug("", ex);
 558  264
         }
 559  264
         this.setMd5sum(md5);
 560  264
         this.setSha1sum(sha1);
 561  264
     }
 562  
 
 563  
     /**
 564  
      * Adds a vulnerability to the dependency.
 565  
      *
 566  
      * @param vulnerability a vulnerability outlining a vulnerability.
 567  
      */
 568  
     public void addVulnerability(Vulnerability vulnerability) {
 569  24
         this.vulnerabilities.add(vulnerability);
 570  24
     }
 571  
 
 572  
     /**
 573  
      * A collection of related dependencies.
 574  
      */
 575  432
     private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
 576  
 
 577  
     /**
 578  
      * Get the value of {@link #relatedDependencies}. This field is used to collect other dependencies which really represent the
 579  
      * same dependency, and may be presented as one item in reports.
 580  
      *
 581  
      * @return the value of relatedDependencies
 582  
      */
 583  
     public Set<Dependency> getRelatedDependencies() {
 584  0
         return relatedDependencies;
 585  
     }
 586  
 
 587  
     /**
 588  
      * A list of projects that reference this dependency.
 589  
      */
 590  432
     private Set<String> projectReferences = new HashSet<String>();
 591  
 
 592  
     /**
 593  
      * Get the value of projectReferences.
 594  
      *
 595  
      * @return the value of projectReferences
 596  
      */
 597  
     public Set<String> getProjectReferences() {
 598  0
         return projectReferences;
 599  
     }
 600  
 
 601  
     /**
 602  
      * Set the value of projectReferences.
 603  
      *
 604  
      * @param projectReferences new value of projectReferences
 605  
      */
 606  
     public void setProjectReferences(Set<String> projectReferences) {
 607  0
         this.projectReferences = projectReferences;
 608  0
     }
 609  
 
 610  
     /**
 611  
      * Adds a project reference.
 612  
      *
 613  
      * @param projectReference a project reference
 614  
      */
 615  
     public void addProjectReference(String projectReference) {
 616  0
         this.projectReferences.add(projectReference);
 617  0
     }
 618  
 
 619  
     /**
 620  
      * Add a collection of project reference.
 621  
      *
 622  
      * @param projectReferences a set of project references
 623  
      */
 624  
     public void addAllProjectReferences(Set<String> projectReferences) {
 625  0
         this.projectReferences.addAll(projectReferences);
 626  0
     }
 627  
 
 628  
     /**
 629  
      * Set the value of relatedDependencies.
 630  
      *
 631  
      * @param relatedDependencies new value of relatedDependencies
 632  
      */
 633  
     public void setRelatedDependencies(Set<Dependency> relatedDependencies) {
 634  0
         this.relatedDependencies = relatedDependencies;
 635  0
     }
 636  
 
 637  
     /**
 638  
      * Adds a related dependency. The internal collection is normally a {@link java.util.TreeSet}, which relies on
 639  
      * {@link #compareTo(Dependency)}. A consequence of this is that if you attempt to add a dependency with the same file path
 640  
      * (modulo character case) as one that is already in the collection, it won't get added.
 641  
      *
 642  
      * @param dependency a reference to the related dependency
 643  
      */
 644  
     public void addRelatedDependency(Dependency dependency) {
 645  0
         if (this == dependency) {
 646  0
             LOGGER.warn("Attempted to add a circular reference - please post the log file to issue #172 here "
 647  
                     + "https://github.com/jeremylong/DependencyCheck/issues/172");
 648  0
             LOGGER.debug("this: {}", this);
 649  0
             LOGGER.debug("dependency: {}", dependency);
 650  0
         } else if (!relatedDependencies.add(dependency)) {
 651  0
             LOGGER.debug("Failed to add dependency, likely due to referencing the same file as another dependency in the set.");
 652  0
             LOGGER.debug("this: {}", this);
 653  0
             LOGGER.debug("dependency: {}", dependency);
 654  
         }
 655  0
     }
 656  
 
 657  
     /**
 658  
      * A list of available versions.
 659  
      */
 660  432
     private List<String> availableVersions = new ArrayList<String>();
 661  
 
 662  
     /**
 663  
      * Get the value of availableVersions.
 664  
      *
 665  
      * @return the value of availableVersions
 666  
      */
 667  
     public List<String> getAvailableVersions() {
 668  0
         return availableVersions;
 669  
     }
 670  
 
 671  
     /**
 672  
      * Set the value of availableVersions.
 673  
      *
 674  
      * @param availableVersions new value of availableVersions
 675  
      */
 676  
     public void setAvailableVersions(List<String> availableVersions) {
 677  0
         this.availableVersions = availableVersions;
 678  0
     }
 679  
 
 680  
     /**
 681  
      * Adds a version to the available version list.
 682  
      *
 683  
      * @param version the version to add to the list
 684  
      */
 685  
     public void addAvailableVersion(String version) {
 686  0
         this.availableVersions.add(version);
 687  0
     }
 688  
 
 689  
     /**
 690  
      * Implementation of the Comparable<Dependency> interface. The comparison is solely based on the file path.
 691  
      *
 692  
      * @param o a dependency to compare
 693  
      * @return an integer representing the natural ordering
 694  
      */
 695  
     public int compareTo(Dependency o) {
 696  16
         return this.getFilePath().compareToIgnoreCase(o.getFilePath());
 697  
     }
 698  
 
 699  
     /**
 700  
      * Implementation of the equals method.
 701  
      *
 702  
      * @param obj the object to compare
 703  
      * @return true if the objects are equal, otherwise false
 704  
      */
 705  
     @Override
 706  
     public boolean equals(Object obj) {
 707  0
         if (obj == null || getClass() != obj.getClass()) {
 708  0
             return false;
 709  
         }
 710  0
         final Dependency other = (Dependency) obj;
 711  0
         return ObjectUtils.equals(this.actualFilePath, other.actualFilePath)
 712  
                 && ObjectUtils.equals(this.filePath, other.filePath)
 713  
                 && ObjectUtils.equals(this.fileName, other.fileName)
 714  
                 && ObjectUtils.equals(this.md5sum, other.md5sum)
 715  
                 && ObjectUtils.equals(this.sha1sum, other.sha1sum)
 716  
                 && ObjectUtils.equals(this.identifiers, other.identifiers)
 717  
                 && ObjectUtils.equals(this.vendorEvidence, other.vendorEvidence)
 718  
                 && ObjectUtils.equals(this.productEvidence, other.productEvidence)
 719  
                 && ObjectUtils.equals(this.versionEvidence, other.versionEvidence)
 720  
                 && ObjectUtils.equals(this.description, other.description)
 721  
                 && ObjectUtils.equals(this.license, other.license)
 722  
                 && ObjectUtils.equals(this.vulnerabilities, other.vulnerabilities)
 723  
                 && ObjectUtils.equals(this.relatedDependencies, other.relatedDependencies)
 724  
                 && ObjectUtils.equals(this.projectReferences, other.projectReferences)
 725  
                 && ObjectUtils.equals(this.availableVersions, other.availableVersions);
 726  
     }
 727  
 
 728  
     /**
 729  
      * Generates the HashCode.
 730  
      *
 731  
      * @return the HashCode
 732  
      */
 733  
     @Override
 734  
     public int hashCode() {
 735  304
         int hash = MAGIC_HASH_INIT_VALUE;
 736  4864
         for (Object field : new Object[]{this.actualFilePath, this.filePath, this.fileName, this.md5sum,
 737  
             this.sha1sum, this.identifiers, this.vendorEvidence, this.productEvidence, this.versionEvidence,
 738  
             this.description, this.license, this.vulnerabilities, this.relatedDependencies, this.projectReferences,
 739  
             this.availableVersions}) {
 740  4560
             hash = MAGIC_HASH_MULTIPLIER * hash + ObjectUtils.hashCode(field);
 741  
         }
 742  304
         return hash;
 743  
     }
 744  
 
 745  
     /**
 746  
      * Standard toString() implementation showing the filename, actualFilePath, and filePath.
 747  
      *
 748  
      * @return the string representation of the file
 749  
      */
 750  
     @Override
 751  
     public String toString() {
 752  0
         return "Dependency{ fileName='" + fileName + "', actualFilePath='" + actualFilePath + "', filePath='" + filePath + "'}";
 753  
     }
 754  
 }