Skip to content

Commit 31a4890

Browse files
authored
Merge pull request #1072 from DependencyTrack/component-occurrences
Ingest component occurrences
2 parents 9556f7e + 3a4b66b commit 31a4890

24 files changed

+801
-71
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
<lib.cpe-parser.version>2.1.0</lib.cpe-parser.version>
9393
<lib.cvss-calculator.version>1.4.3</lib.cvss-calculator.version>
9494
<lib.owasp-rr-calculator.version>1.0.1</lib.owasp-rr-calculator.version>
95-
<lib.cyclonedx-java.version>9.1.0</lib.cyclonedx-java.version>
95+
<lib.cyclonedx-java.version>10.1.0</lib.cyclonedx-java.version>
9696
<lib.datanucleus-postgresql.version>0.3.0</lib.datanucleus-postgresql.version>
9797
<lib.jaxb.runtime.version>4.0.5</lib.jaxb.runtime.version>
9898
<!--

src/main/java/org/dependencytrack/model/Component.java

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
import org.dependencytrack.persistence.converter.OrganizationalEntityJsonConverter;
3636
import org.dependencytrack.resources.v1.serializers.CustomPackageURLSerializer;
3737

38+
import jakarta.validation.constraints.NotBlank;
39+
import jakarta.validation.constraints.NotNull;
40+
import jakarta.validation.constraints.Pattern;
41+
import jakarta.validation.constraints.Size;
3842
import javax.jdo.annotations.Column;
3943
import javax.jdo.annotations.Convert;
4044
import javax.jdo.annotations.Element;
@@ -51,13 +55,10 @@
5155
import javax.jdo.annotations.PrimaryKey;
5256
import javax.jdo.annotations.Serialized;
5357
import javax.jdo.annotations.Unique;
54-
import jakarta.validation.constraints.NotBlank;
55-
import jakarta.validation.constraints.NotNull;
56-
import jakarta.validation.constraints.Pattern;
57-
import jakarta.validation.constraints.Size;
5858
import java.io.Serializable;
5959
import java.util.ArrayList;
6060
import java.util.Collection;
61+
import java.util.HashSet;
6162
import java.util.List;
6263
import java.util.Set;
6364
import java.util.UUID;
@@ -80,6 +81,7 @@
8081
@Persistent(name = "vulnerabilities"),
8182
}),
8283
@FetchGroup(name = "BOM_UPLOAD_PROCESSING", members = {
84+
@Persistent(name = "occurrences"),
8385
@Persistent(name = "properties")
8486
}),
8587
@FetchGroup(name = "IDENTITY", members = {
@@ -356,6 +358,10 @@ public enum FetchGroup {
356358
@Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering", value = "id ASC"))
357359
private Collection<Component> children;
358360

361+
@Persistent(mappedBy = "component", defaultFetchGroup = "false")
362+
@JsonIgnore
363+
private Set<ComponentOccurrence> occurrences;
364+
359365
@Persistent(mappedBy = "component", defaultFetchGroup = "false")
360366
@Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering", value = "groupName ASC, propertyName ASC, id ASC"))
361367
private List<ComponentProperty> properties;
@@ -406,6 +412,10 @@ public enum FetchGroup {
406412
private transient boolean expandDependencyGraph;
407413
private transient String author;
408414

415+
// TODO: Move this to another class, similar to ConciseProjectListItem.
416+
// This is only relevant when listing components.
417+
private transient Long occurrenceCount;
418+
409419
public Component(){}
410420

411421
public Component(final long id) {
@@ -751,6 +761,21 @@ public void setChildren(Collection<Component> children) {
751761
this.children = children;
752762
}
753763

764+
public Set<ComponentOccurrence> getOccurrences() {
765+
return occurrences;
766+
}
767+
768+
public void setOccurrences(final Set<ComponentOccurrence> occurrences) {
769+
this.occurrences = occurrences;
770+
}
771+
772+
public void addOccurrence(final ComponentOccurrence occurrence) {
773+
if (occurrences == null) {
774+
occurrences = new HashSet<>();
775+
}
776+
occurrences.add(occurrence);
777+
}
778+
754779
public List<ComponentProperty> getProperties() {
755780
return properties;
756781
}
@@ -759,6 +784,13 @@ public void setProperties(List<ComponentProperty> properties) {
759784
this.properties = properties;
760785
}
761786

787+
public void addProperty(final ComponentProperty property) {
788+
if (properties == null) {
789+
properties = new ArrayList<>();
790+
}
791+
properties.add(property);
792+
}
793+
762794
public List<Vulnerability> getVulnerabilities() {
763795
return vulnerabilities;
764796
}
@@ -891,6 +923,14 @@ public void setAuthor(String author){
891923
this.author=author;
892924
}
893925

926+
public Long getOccurrenceCount() {
927+
return occurrenceCount;
928+
}
929+
930+
public void setOccurrenceCount(final Long occurrenceCount) {
931+
this.occurrenceCount = occurrenceCount;
932+
}
933+
894934
@Override
895935
public String toString() {
896936
if (getPurl() != null) {
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* This file is part of Dependency-Track.
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+
* SPDX-License-Identifier: Apache-2.0
17+
* Copyright (c) OWASP Foundation. All Rights Reserved.
18+
*/
19+
package org.dependencytrack.model;
20+
21+
import com.fasterxml.jackson.annotation.JsonFormat;
22+
import com.fasterxml.jackson.annotation.JsonIgnore;
23+
import com.fasterxml.jackson.annotation.JsonInclude;
24+
import org.datanucleus.api.jdo.annotations.CreateTimestamp;
25+
26+
import javax.jdo.annotations.Column;
27+
import javax.jdo.annotations.ForeignKey;
28+
import javax.jdo.annotations.ForeignKeyAction;
29+
import javax.jdo.annotations.Index;
30+
import javax.jdo.annotations.NotPersistent;
31+
import javax.jdo.annotations.PersistenceCapable;
32+
import javax.jdo.annotations.Persistent;
33+
import javax.jdo.annotations.PrimaryKey;
34+
import java.time.Instant;
35+
import java.util.UUID;
36+
37+
/**
38+
* @since 5.6.0
39+
*/
40+
@PersistenceCapable(table = "COMPONENT_OCCURRENCE")
41+
@JsonInclude(JsonInclude.Include.NON_NULL)
42+
public class ComponentOccurrence {
43+
44+
public record Identity(
45+
String location,
46+
Integer line,
47+
Integer offset,
48+
String symbol) {
49+
50+
public static Identity of(final ComponentOccurrence occurrence) {
51+
return new Identity(
52+
occurrence.getLocation(),
53+
occurrence.getLine(),
54+
occurrence.getOffset(),
55+
occurrence.getSymbol());
56+
}
57+
58+
}
59+
60+
@PrimaryKey(name = "COMPONENT_OCCURRENCE_PK")
61+
@Persistent(customValueStrategy = "uuid-v7")
62+
@Column(name = "ID", sqlType = "UUID")
63+
private UUID id;
64+
65+
@Persistent
66+
@ForeignKey(
67+
name = "COMPONENT_OCCURRENCE_COMPONENT_FK",
68+
deferred = "true",
69+
deleteAction = ForeignKeyAction.CASCADE,
70+
updateAction = ForeignKeyAction.NONE)
71+
@Index(name = "COMPONENT_OCCURRENCE_COMPONENT_ID_IDX")
72+
@Column(name = "COMPONENT_ID", allowsNull = "false")
73+
@JsonIgnore
74+
private Component component;
75+
76+
@Persistent
77+
@Column(name = "LOCATION")
78+
private String location;
79+
80+
@Persistent
81+
@Column(name = "LINE")
82+
private Integer line;
83+
84+
@Persistent
85+
@Column(name = "OFFSET")
86+
private Integer offset;
87+
88+
@Persistent
89+
@Column(name = "SYMBOL")
90+
private String symbol;
91+
92+
@Persistent
93+
@CreateTimestamp
94+
@Column(name = "CREATED_AT")
95+
@JsonFormat(
96+
shape = JsonFormat.Shape.NUMBER_INT,
97+
without = JsonFormat.Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
98+
private Instant createdAt;
99+
100+
@NotPersistent
101+
@JsonIgnore
102+
private transient Integer totalCount;
103+
104+
public UUID getId() {
105+
return id;
106+
}
107+
108+
public void setId(final UUID id) {
109+
this.id = id;
110+
}
111+
112+
public Component getComponent() {
113+
return component;
114+
}
115+
116+
public void setComponent(final Component component) {
117+
this.component = component;
118+
}
119+
120+
public String getLocation() {
121+
return location;
122+
}
123+
124+
public void setLocation(final String location) {
125+
this.location = location;
126+
}
127+
128+
public Integer getLine() {
129+
return line;
130+
}
131+
132+
public void setLine(final Integer line) {
133+
this.line = line;
134+
}
135+
136+
public Integer getOffset() {
137+
return offset;
138+
}
139+
140+
public void setOffset(final Integer offset) {
141+
this.offset = offset;
142+
}
143+
144+
public String getSymbol() {
145+
return symbol;
146+
}
147+
148+
public void setSymbol(final String symbol) {
149+
this.symbol = symbol;
150+
}
151+
152+
public Instant getCreatedAt() {
153+
return createdAt;
154+
}
155+
156+
public void setCreatedAt(final Instant createdAt) {
157+
this.createdAt = createdAt;
158+
}
159+
160+
public Integer getTotalCount() {
161+
return totalCount;
162+
}
163+
164+
public void setTotalCount(final Integer totalCount) {
165+
this.totalCount = totalCount;
166+
}
167+
168+
}

src/main/java/org/dependencytrack/model/sqlmapping/ComponentProjection.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ public class ComponentProjection {
159159

160160
public Boolean isCustomLicense;
161161

162+
public long occurrenceCount;
162163
public Long totalCount;
163164

164165
public static Component mapToComponent(ComponentProjection result) {
@@ -197,6 +198,7 @@ public static Component mapToComponent(ComponentProjection result) {
197198
if (result.externalReferences != null) {
198199
componentPersistent.setExternalReferences(SerializationUtils.deserialize(result.externalReferences));
199200
}
201+
componentPersistent.setOccurrenceCount(result.occurrenceCount);
200202
componentPersistent.setPurl(result.purl);
201203
componentPersistent.setPurlCoordinates(result.purlCoordinates);
202204
componentPersistent.setVersion(result.version);

0 commit comments

Comments
 (0)