All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.metaeffekt.mirror.contents.advisory.AdvisoryEntry Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.metaeffekt.mirror.contents.advisory;

import com.metaeffekt.artifact.analysis.utils.CustomCollectors;
import com.metaeffekt.artifact.analysis.utils.FileUtils;
import com.metaeffekt.artifact.analysis.utils.StringUtils;
import com.metaeffekt.artifact.analysis.utils.TimeUtils;
import com.metaeffekt.mirror.contents.base.DescriptionParagraph;
import com.metaeffekt.mirror.contents.base.MatchableDetailsAmbDataClass;
import com.metaeffekt.mirror.contents.base.Reference;
import com.metaeffekt.mirror.contents.store.AdvisoryTypeIdentifier;
import com.metaeffekt.mirror.contents.store.AdvisoryTypeStore;
import com.metaeffekt.mirror.contents.store.ContentIdentifierStore;
import com.metaeffekt.mirror.contents.store.VulnerabilityTypeIdentifier;
import com.metaeffekt.mirror.contents.vulnerability.Vulnerability;
import lombok.Getter;
import lombok.Setter;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.json.JSONArray;
import org.json.JSONObject;
import org.metaeffekt.core.inventory.processor.model.AdvisoryMetaData;
import org.metaeffekt.core.security.cvss.processor.CvssVectorSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public abstract class AdvisoryEntry extends MatchableDetailsAmbDataClass {

    private final static Logger LOG = LoggerFactory.getLogger(AdvisoryEntry.class);

    protected final static Set CONVERSION_KEYS_AMB = new HashSet(MatchableDetailsAmbDataClass.CONVERSION_KEYS_AMB) {{
        addAll(Arrays.asList(
                AdvisoryMetaData.Attribute.NAME.getKey(),
                AdvisoryMetaData.Attribute.SOURCE.getKey(),
                AdvisoryMetaData.Attribute.SOURCE_IMPLEMENTATION.getKey(),
                AdvisoryMetaData.Attribute.URL.getKey(),
                AdvisoryMetaData.Attribute.TYPE.getKey(),
                AdvisoryMetaData.Attribute.SUMMARY.getKey(),
                AdvisoryMetaData.Attribute.DESCRIPTION.getKey(),
                AdvisoryMetaData.Attribute.THREAT.getKey(),
                AdvisoryMetaData.Attribute.RECOMMENDATIONS.getKey(),
                AdvisoryMetaData.Attribute.WORKAROUNDS.getKey(),
                AdvisoryMetaData.Attribute.ACKNOWLEDGEMENTS.getKey(),
                AdvisoryMetaData.Attribute.REFERENCES.getKey(),
                AdvisoryMetaData.Attribute.KEYWORDS.getKey(),
                AdvisoryMetaData.Attribute.CREATE_DATE.getKey(),
                AdvisoryMetaData.Attribute.CREATE_DATE_FORMATTED.getKey(),
                AdvisoryMetaData.Attribute.UPDATE_DATE.getKey(),
                AdvisoryMetaData.Attribute.UPDATE_DATE_FORMATTED.getKey(),
                AdvisoryMetaData.Attribute.MATCHING_SOURCE.getKey(),
                AdvisoryMetaData.Attribute.DATA_SOURCE.getKey(),
                AdvisoryMetaData.Attribute.CVSS_VECTORS.getKey()
        ));
    }};

    protected final static Set CONVERSION_KEYS_MAP = new HashSet(MatchableDetailsAmbDataClass.CONVERSION_KEYS_MAP) {{
        addAll(Arrays.asList(
                "id", "url", "summary", "description", "threat", "recommendations", "workarounds",
                "references", "acknowledgements", "keywords", "createDate", "updateDate",
                "cvss"
        ));
    }};


    /**
     * Stores what provider this advisory originates from.
* Must be defined on all advisory instances. */ protected AdvisoryTypeIdentifier sourceIdentifier; @Getter protected String summary; @Getter protected final List description = new ArrayList<>(); @Getter @Setter protected String threat; @Getter @Setter protected String recommendations; @Getter @Setter protected String workarounds; @Getter protected final Set acknowledgements = new LinkedHashSet<>(); @Getter protected final Set references = new LinkedHashSet<>(); @Getter protected final Set keywords = new LinkedHashSet<>(); @Getter protected Date createDate; @Getter protected Date updateDate; @Getter private final CvssVectorSet cvssVectors = new CvssVectorSet(); public final static Comparator UPDATE_CREATE_TIME_COMPARATOR = Comparator .comparing(AdvisoryEntry::getUpdateDate) .thenComparing(AdvisoryEntry::getCreateDate); public AdvisoryEntry(AdvisoryTypeIdentifier source) { if (source == null) { throw new IllegalArgumentException("Advisory source must not be null"); } else { this.sourceIdentifier = source; } } public AdvisoryEntry(AdvisoryTypeIdentifier source, String id) { this(source); this.id = id; } public void setSourceIdentifier(AdvisoryTypeIdentifier source) { if (source == null) { throw new IllegalArgumentException("Advisory source must not be null"); } if (LOG.isDebugEnabled() && source != this.sourceIdentifier) { LOG.warn("Explicitly assigned source differs from originally assigned [{}] --> [{}]", this.sourceIdentifier.toExtendedString(), source.toExtendedString()); } this.sourceIdentifier = source; } @Override public AdvisoryTypeIdentifier getSourceIdentifier() { return sourceIdentifier; } public AdvisoryEntry setSummary(String summary) { this.summary = summary; return this; } public void setDescription(DescriptionParagraph paragraph) { this.description.clear(); if (paragraph.isEmpty()) return; this.description.add(paragraph); } public void addDescription(String title, String content) { if (StringUtils.hasText(content)) { this.addDescription(new DescriptionParagraph(title, content)); } } public void addDescription(DescriptionParagraph paragraph) { if (paragraph.isEmpty()) return; this.description.add(paragraph); } public void addDescription(List paragraphs) { paragraphs.stream() .filter(p -> !p.isEmpty()) .forEach(this::addDescription); } public void clearDescription() { this.description.clear(); } public void addReference(Reference reference) { if (StringUtils.hasText(reference.getUrl())) { this.references.add(reference); } } public void addReferences(Collection references) { references.forEach(this::addReference); } public void removeReference(String reference) { this.references.removeIf(r -> r.getUrl().equals(reference)); this.references.removeIf(r -> r.getTitle().equals(reference)); } public void removeReference(Reference reference) { this.references.remove(reference); } public void addAcknowledgement(String author) { if (StringUtils.hasText(author)) { this.acknowledgements.add(author); } } public void addAcknowledgements(Collection authors) { authors.forEach(this::addAcknowledgement); } public void removeAcknowledgement(String author) { this.acknowledgements.remove(author); } public void addKeyword(String keyword) { if (StringUtils.hasText(keyword)) { this.keywords.add(keyword); } } public void addKeywords(Collection keywords) { keywords.forEach(this::addKeyword); } public void removeKeyword(String keyword) { this.keywords.remove(keyword); } public void setCreateDate(Date createDate) { this.createDate = createDate; setCorrectUpdateCreateDateOrder(); } public void setUpdateDate(Date updateDate) { this.updateDate = updateDate; setCorrectUpdateCreateDateOrder(); } private void setCorrectUpdateCreateDateOrder() { if (this.updateDate != null && this.createDate != null && this.updateDate.before(this.createDate)) { final Date tmp = this.updateDate; this.updateDate = this.createDate; this.createDate = tmp; } } public void setCreateDate(long creationDate) { setCreateDate(new Date(creationDate)); } public void setUpdateDate(long lastModifiedDate) { setUpdateDate(new Date(lastModifiedDate)); } public String getTextDescription() { return description.stream().map(DescriptionParagraph::toString).collect(Collectors.joining("\n\n")); } public DescriptionParagraph getDescription(String title) { return description.stream() .filter(p -> p.getHeader().equals(title)) .findFirst() .orElse(null); } public String getDescriptionContent(String title) { final DescriptionParagraph paragraph = getDescription(title); return paragraph != null ? paragraph.getContent() : null; } public boolean hasBeenUpdatedSince(long timestamp) { final Date date = updateDate != null ? updateDate : createDate; return date != null && date.getTime() > timestamp; } public boolean hasBeenUpdatedBefore(long timestamp) { final Date date = updateDate != null ? updateDate : createDate; return date != null && date.getTime() < timestamp; } public abstract String getUrl(); public abstract String getType(); /* TYPE CONVERSION METHODS */ @Override public AdvisoryMetaData constructBaseModel() { return new AdvisoryMetaData(); } public static T fromAdvisoryMetaData(AdvisoryMetaData amd, Supplier constructor) { if (amd == null) return null; return constructor.get() .performAction(v -> v.appendFromBaseModel(amd)); } public static AdvisoryEntry fromAdvisoryMetaData(AdvisoryMetaData amd) { final AdvisoryTypeIdentifier foundType = AdvisoryTypeStore.get().fromAdvisoryMetaData(amd).getIdentifier(); return fromAdvisoryMetaData(amd, foundType.getAdvisoryFactory()); } public static T fromInputMap(Map map, Supplier constructor) { if (map == null) return null; return constructor.get() .performAction(v -> v.appendFromMap(map)); } public static T fromJson(JSONObject json, Supplier constructor) { if (json == null) return null; return fromInputMap(json.toMap(), constructor); } public static T fromJson(File file, Supplier constructor) throws IOException { if (file == null) return null; final String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8); final JSONObject json = new JSONObject(content); return fromJson(json, constructor); } public static AdvisoryEntry fromJson(JSONObject json) { final ContentIdentifierStore.SingleContentIdentifierParseResult> foundType = AdvisoryTypeStore.get().fromJsonNameAndImplementation(json); return fromJson(json, foundType.getIdentifier().getAdvisoryFactory()); } public static T fromDocument(Document document, Supplier constructor) { if (document == null) return null; return constructor.get() .performAction(v -> v.appendFromDocument(document)); } @Override public void appendFromBaseModel(AdvisoryMetaData advisoryMetaData) { super.appendFromBaseModel(advisoryMetaData); this.setId(advisoryMetaData.get(AdvisoryMetaData.Attribute.NAME)); final String source = advisoryMetaData.get(AdvisoryMetaData.Attribute.SOURCE); final String sourceImplementation = advisoryMetaData.get(AdvisoryMetaData.Attribute.SOURCE_IMPLEMENTATION); if (StringUtils.hasText(source) || StringUtils.hasText(sourceImplementation)) { this.setSourceIdentifier(AdvisoryTypeStore.get().fromNameAndImplementation(source, sourceImplementation)); } else { AdvisoryTypeStore.get().inferSourceIdentifierFromIdIfAbsent(this); } this.setSummary(advisoryMetaData.get(AdvisoryMetaData.Attribute.SUMMARY)); if (StringUtils.hasText(advisoryMetaData.get(AdvisoryMetaData.Attribute.DESCRIPTION))) { this.addDescription(DescriptionParagraph.fromJson(new JSONArray(advisoryMetaData.get(AdvisoryMetaData.Attribute.DESCRIPTION)))); } this.setThreat(advisoryMetaData.get(AdvisoryMetaData.Attribute.THREAT)); this.setRecommendations(advisoryMetaData.get(AdvisoryMetaData.Attribute.RECOMMENDATIONS)); this.setWorkarounds(advisoryMetaData.get(AdvisoryMetaData.Attribute.WORKAROUNDS)); if (StringUtils.hasText(advisoryMetaData.get(AdvisoryMetaData.Attribute.ACKNOWLEDGEMENTS))) { final JSONArray acknowledgements = new JSONArray(advisoryMetaData.get(AdvisoryMetaData.Attribute.ACKNOWLEDGEMENTS)); for (int i = 0; i < acknowledgements.length(); i++) { this.addAcknowledgement(acknowledgements.optString(i)); } } if (StringUtils.hasText(advisoryMetaData.get(AdvisoryMetaData.Attribute.KEYWORDS))) { final JSONArray keywords = new JSONArray(advisoryMetaData.get(AdvisoryMetaData.Attribute.KEYWORDS)); for (int i = 0; i < keywords.length(); i++) { this.addKeyword(keywords.optString(i)); } } final String referencesString = advisoryMetaData.get(AdvisoryMetaData.Attribute.REFERENCES); if (StringUtils.hasText(referencesString)) { final JSONArray references = new JSONArray(referencesString); for (int i = 0; i < references.length(); i++) { this.addReference(Reference.fromJson(references.optJSONObject(i))); } } this.setCreateDate(TimeUtils.tryParse(advisoryMetaData.get(AdvisoryMetaData.Attribute.CREATE_DATE))); this.setUpdateDate(TimeUtils.tryParse(advisoryMetaData.get(AdvisoryMetaData.Attribute.UPDATE_DATE))); if (StringUtils.hasText(advisoryMetaData.get(AdvisoryMetaData.Attribute.CVSS_VECTORS))) { final String cvssVectors = advisoryMetaData.get(AdvisoryMetaData.Attribute.CVSS_VECTORS); this.cvssVectors.addAllCvssVectors(CvssVectorSet.fromJson(new JSONArray(cvssVectors))); } } @Override public void appendToBaseModel(AdvisoryMetaData amd) { super.appendToBaseModel(amd); amd.set(AdvisoryMetaData.Attribute.NAME, id); amd.set(AdvisoryMetaData.Attribute.URL, getUrl()); amd.set(AdvisoryMetaData.Attribute.TYPE, getType()); amd.set(AdvisoryMetaData.Attribute.SUMMARY, summary); if (!description.isEmpty()) { amd.set(AdvisoryMetaData.Attribute.DESCRIPTION, description.stream().map(DescriptionParagraph::toJson).collect(CustomCollectors.toJsonArray()).toString()); } if (threat != null) amd.set(AdvisoryMetaData.Attribute.THREAT, threat); if (recommendations != null) amd.set(AdvisoryMetaData.Attribute.RECOMMENDATIONS, recommendations); if (workarounds != null) amd.set(AdvisoryMetaData.Attribute.WORKAROUNDS, workarounds); if (!acknowledgements.isEmpty()) { amd.set(AdvisoryMetaData.Attribute.ACKNOWLEDGEMENTS, new JSONArray(acknowledgements).toString()); } if (!references.isEmpty()) { amd.set(AdvisoryMetaData.Attribute.REFERENCES, references.stream().map(Reference::toJson).collect(CustomCollectors.toJsonArray()).toString()); } if (!keywords.isEmpty()) { amd.set(AdvisoryMetaData.Attribute.KEYWORDS, new JSONArray(keywords).toString()); } if (createDate != null) { amd.set(AdvisoryMetaData.Attribute.CREATE_DATE, Long.toString(this.createDate.getTime())); amd.set(AdvisoryMetaData.Attribute.CREATE_DATE_FORMATTED, TimeUtils.formatNormalizedDate(this.createDate)); } if (updateDate != null) { amd.set(AdvisoryMetaData.Attribute.UPDATE_DATE, Long.toString(this.updateDate.getTime())); amd.set(AdvisoryMetaData.Attribute.UPDATE_DATE_FORMATTED, TimeUtils.formatNormalizedDate(this.updateDate)); } if (!this.cvssVectors.isEmpty()) { amd.set(AdvisoryMetaData.Attribute.CVSS_VECTORS, this.cvssVectors.toJson().toString()); } } public Vulnerability toVulnerability() { final Vulnerability vulnerability = new Vulnerability(id); vulnerability.setUrl(this.getUrl()); vulnerability.setDescription(firstNonEmpty(this.summary, this.getTextDescription())); vulnerability.setCreateDate(this.createDate); vulnerability.setUpdateDate(this.updateDate); vulnerability.addReferences(new ArrayList<>(this.references)); vulnerability.addReference(Reference.fromTitleAndUrl("Advisor URL", getUrl())); vulnerability.addReferencedVulnerabilities(this.referencedVulnerabilities); vulnerability.addReferencedSecurityAdvisories(this.referencedSecurityAdvisories); vulnerability.getCvssVectors().addAllCvssVectors(this.cvssVectors); return vulnerability; } @Override public void appendFromDataClass(AdvisoryEntry dataClass) { super.appendFromDataClass(dataClass); if (StringUtils.hasText(dataClass.getSummary())) { this.setSummary(dataClass.getSummary()); } if (!dataClass.getDescription().isEmpty()) { this.addDescription(dataClass.getDescription()); } if (StringUtils.hasText(dataClass.getThreat())) { this.setThreat(dataClass.getThreat()); } if (StringUtils.hasText(dataClass.getRecommendations())) { this.setRecommendations(dataClass.getRecommendations()); } if (StringUtils.hasText(dataClass.getWorkarounds())) { this.setWorkarounds(dataClass.getWorkarounds()); } if (!dataClass.getReferences().isEmpty()) { this.addReferences(dataClass.getReferences()); } if (!dataClass.getAcknowledgements().isEmpty()) { this.addAcknowledgements(dataClass.getAcknowledgements()); } if (!dataClass.getKeywords().isEmpty()) { this.addKeywords(dataClass.getKeywords()); } if (dataClass.getCreateDate() != null) { this.setCreateDate(dataClass.getCreateDate()); } if (dataClass.getUpdateDate() != null) { this.setUpdateDate(dataClass.getUpdateDate()); } if (!dataClass.getCvssVectors().isEmpty()) { this.cvssVectors.addAllCvssVectors(dataClass.getCvssVectors()); } } @Override public void appendFromMap(Map input) { super.appendFromMap(input); if (input.containsKey("id")) { this.setId(String.valueOf(input.get("id"))); } final String source = (String) input.getOrDefault("source", null); final String sourceImplementation = (String) input.getOrDefault("sourceImplementation", null); if (source != null || sourceImplementation != null) { this.setSourceIdentifier(AdvisoryTypeStore.get().fromNameAndImplementation(source, sourceImplementation)); } this.setSummary((String) input.getOrDefault("summary", null)); final Object inputDescriptionParagraphs = input.getOrDefault("description", new ArrayList<>()); if (inputDescriptionParagraphs instanceof List) { final List preTypedDescriptionParagraphs = (List) inputDescriptionParagraphs; if (!preTypedDescriptionParagraphs.isEmpty()) { if (preTypedDescriptionParagraphs.get(0) instanceof DescriptionParagraph) { final List descriptionParagraphs = (List) inputDescriptionParagraphs; for (DescriptionParagraph descriptionParagraph : descriptionParagraphs) { this.addDescription(descriptionParagraph); } } else if (preTypedDescriptionParagraphs.get(0) instanceof Map) { final List> descriptionParagraphs = (List>) inputDescriptionParagraphs; for (Map descriptionParagraph : descriptionParagraphs) { this.addDescription(DescriptionParagraph.fromJson(new JSONObject(descriptionParagraph))); } } else { LOG.warn("Could not parse description paragraphs for [{}] [{}] from input: {}", this.getClass().getSimpleName(), this.getId(), inputDescriptionParagraphs); } } } else if (inputDescriptionParagraphs instanceof String) { final String descriptionParagraphs = (String) inputDescriptionParagraphs; this.addDescription(DescriptionParagraph.fromContent(descriptionParagraphs)); } this.setThreat((String) input.getOrDefault("threat", null)); this.setRecommendations((String) input.getOrDefault("recommendations", null)); this.setWorkarounds((String) input.getOrDefault("workarounds", null)); List> references = (List>) input.getOrDefault("references", new ArrayList<>()); for (Map referenceMap : references) { this.addReference(Reference.fromMap(referenceMap)); } List acknowledgements = (List) input.getOrDefault("acknowledgements", new ArrayList<>()); for (String acknowledgement : acknowledgements) { this.addAcknowledgement(acknowledgement); } List keywords = (List) input.getOrDefault("keywords", new ArrayList<>()); for (String keyword : keywords) { this.addKeyword(keyword); } this.setCreateDate(TimeUtils.tryParse(String.valueOf(input.getOrDefault("createDate", null)))); this.setUpdateDate(TimeUtils.tryParse(String.valueOf(input.getOrDefault("updateDate", null)))); final Object cvss = input.get("cvss"); if (cvss != null) { if (cvss instanceof List) { final JSONArray json = new JSONArray((List) cvss); this.cvssVectors.addAllCvssVectors(CvssVectorSet.fromJson(json)); } else { LOG.warn("Could not parse CVSS vectors for [{}] [{}] from input: {}", this.getClass().getSimpleName(), this.getId(), cvss); } } } @Override public void appendToJson(JSONObject json) { super.appendToJson(json); json.put("id", id); json.put("url", getUrl()); json.put("summary", summary); json.put("description", description.stream().map(DescriptionParagraph::toJson).collect(CustomCollectors.toJsonArray())); json.put("threat", threat); json.put("recommendations", recommendations); json.put("workarounds", workarounds); json.put("references", references); json.put("acknowledgements", acknowledgements); json.put("keywords", keywords); if (createDate != null) json.put("createDate", createDate.getTime()); if (updateDate != null) json.put("updateDate", updateDate.getTime()); json.put("cvss", this.cvssVectors.toJson()); } @Override public void appendFromDocument(Document document) { super.appendFromDocument(document); this.setId(document.get("id")); this.setSummary(document.get("summary")); this.addDescription(DescriptionParagraph.fromJson(new JSONArray(document.get("description")))); this.setThreat(document.get("threat")); this.setRecommendations(document.get("recommendations")); this.setWorkarounds(document.get("workarounds")); final String referencesString = document.get("references"); if (StringUtils.hasText(referencesString)) { final JSONArray references = new JSONArray(referencesString); for (int i = 0; i < references.length(); i++) { this.addReference(Reference.fromJson(references.optJSONObject(i))); } } this.addAcknowledgements(splitDocumentArray(document.get("acknowledgements"))); this.addKeywords(splitDocumentArray(document.get("keywords"))); if (document.get("createDate") != null) { this.setCreateDate(new Date(Long.parseLong(document.get("createDate")))); } if (document.get("updateDate") != null) { this.setUpdateDate(new Date(Long.parseLong(document.get("updateDate")))); } if (document.get("cvss") != null) { final String cvssVectors = document.get("cvss"); this.cvssVectors.addAllCvssVectors(CvssVectorSet.fromJson(new JSONArray(cvssVectors))); } } @Override public void appendToDocument(Document doc) { super.appendToDocument(doc); if (id != null && this instanceof GhsaAdvisorEntry) { addToDocumentAsTextFieldIfNotEmpty(doc, "id", id.toLowerCase(Locale.US)); } else { addToDocumentAsTextFieldIfNotEmpty(doc, "id", id); } addToDocumentAsTextFieldIfNotEmpty(doc, "url", getUrl()); addToDocumentAsTextFieldIfNotEmpty(doc, "summary", summary); addToDocumentAsTextFieldIfNotEmpty(doc, "description", description.stream().map(DescriptionParagraph::toJson).collect(CustomCollectors.toJsonArray()).toString()); addToDocumentAsTextFieldIfNotEmpty(doc, "threat", threat); addToDocumentAsTextFieldIfNotEmpty(doc, "recommendations", recommendations); addToDocumentAsTextFieldIfNotEmpty(doc, "workarounds", workarounds); addToDocumentAsTextFieldIfNotEmpty(doc, "references", references.stream().map(Reference::toJson).collect(CustomCollectors.toJsonArray()).toString()); addToDocumentAsTextFieldIfNotEmpty(doc, "acknowledgements", String.join(DOCUMENT_ARRAY_DELIMITER, acknowledgements)); addToDocumentAsTextFieldIfNotEmpty(doc, "keywords", String.join(DOCUMENT_ARRAY_DELIMITER, keywords)); addToDocumentAsTextFieldIfNotEmpty(doc, "createDate", createDate == null ? null : Long.toString(createDate.getTime())); addToDocumentAsTextFieldIfNotEmpty(doc, "updateDate", updateDate == null ? null : Long.toString(updateDate.getTime())); addToDocumentAsTextFieldIfNotEmpty(doc, "cvss", this.cvssVectors.isEmpty() ? null : this.cvssVectors.toJson().toString()); } protected void addToDocumentAsTextFieldIfNotEmpty(Document doc, String fieldName, String value) { if (StringUtils.hasText(value)) { doc.add(new TextField(fieldName, value, Field.Store.YES)); } } public final static String DOCUMENT_ARRAY_DELIMITER = ";;"; @Override public String toString() { return "{" + id + (summary == null ? "" : ": " + summary) + "}"; } /* UTILITY METHODS FOR PARSING DOWNLOAD DATA */ protected static void extractReferenceIdsFromStringIfPresent(String string, AdvisoryEntry entry, AdvisoryTypeIdentifier contentIdentifier) { if (StringUtils.hasText(string)) { entry.addReferencedSecurityAdvisories(Collections.singletonMap(contentIdentifier, contentIdentifier.fromFreeText(string))); } } protected static void extractReferenceIdsFromStringIfPresent(String string, AdvisoryEntry entry, VulnerabilityTypeIdentifier contentIdentifier) { if (StringUtils.hasText(string)) { entry.addReferencedVulnerabilities(Collections.singletonMap(contentIdentifier, contentIdentifier.fromFreeText(string))); } } protected static String trimNewlines(String s) { return s.replaceAll("(^\\s*)|(\\s*$)", ""); } protected static List splitDocumentArray(String array) { if (array == null) { return Collections.emptyList(); } return Arrays.asList(array.split(AdvisoryEntry.DOCUMENT_ARRAY_DELIMITER)); } protected static String firstNonEmpty(String... items) { return Arrays.stream(items) .filter(Objects::nonNull) .filter(i -> !i.isEmpty()) .findFirst() .orElse(null); } protected static String longestNonEmpty(String... items) { return Arrays.stream(items) .filter(Objects::nonNull) .filter(i -> !i.isEmpty()) .max(Comparator.comparingInt(String::length)) .orElse(null); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy