com.metaeffekt.artifact.analysis.utils.InventoryUtils Maven / Gradle / Ivy
/*
* 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.artifact.analysis.utils;
import com.metaeffekt.artifact.analysis.metascan.Constants;
import com.metaeffekt.artifact.terms.TermsMetaDataResolver;
import com.metaeffekt.artifact.terms.model.NormalizationMetaData;
import com.metaeffekt.artifact.terms.model.TermsMetaData;
import com.metaeffekt.resource.InventoryResource;
import org.apache.commons.lang.StringEscapeUtils;
import org.metaeffekt.core.inventory.processor.model.*;
import org.metaeffekt.core.inventory.processor.report.InventoryReport;
import org.metaeffekt.core.inventory.processor.report.ReportContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import static com.metaeffekt.artifact.analysis.metascan.Constants.*;
import static org.metaeffekt.core.inventory.processor.model.Constants.DELIMITER_NEWLINE;
public class InventoryUtils extends org.metaeffekt.core.inventory.InventoryUtils {
private static final Logger LOG = LoggerFactory.getLogger(InventoryUtils.class);
public static final String INVENTORY_KEY_LICENSE_DIFF = "License / Derived Src/Bin License Diff";
public static final String INVENTORY_KEY_LICENSE_DIFF_SRC_BIN = "Src/Bin Derived Licenses Diff";
public static NormalizationMetaData NORMALIZATION_META_DATA;
public static void initialize(NormalizationMetaData normalizationMetaData) {
NORMALIZATION_META_DATA = normalizationMetaData;
}
public static NormalizationMetaData getNormalizationMetaData() {
if (NORMALIZATION_META_DATA == null) {
synchronized (InventoryUtils.class) {
LOG.warn("Implicitly discovering TermsMetaData. Please consider explicitly initializing.");
NORMALIZATION_META_DATA = TermsMetaDataResolver.get();
}
}
return NORMALIZATION_META_DATA;
}
/**
* Creates a License Diff column. Compare the columns License with KEY_DERIVED_LICENSES and KEY_DERIVED_LICENSES__SOURCE.
*
* @param inventory The inventory do create the column from and in.
*/
public static void diffDerivedLicenses(Inventory inventory) {
// add license diff columns (artifacts)
if (inventory == null) return;
for (Artifact artifact : inventory.getArtifacts()) {
String referenceLicense = artifact.getLicense();
if (StringUtils.isEmpty(referenceLicense)) {
referenceLicense = artifact.getLicense();
}
// FIXME: currently only comparing Binary Artifact and Source Artifact Licenses
String derivedLicenses = artifact.get(KEY_BINARY_ARTIFACT_DERIVED_LICENSES);
final String sourceDerivedLicenses = artifact.get(KEY_SOURCE_ARTIFACT_DERIVED_LICENSES);
if (!StringUtils.isEmpty(sourceDerivedLicenses)) {
if (StringUtils.isEmpty(derivedLicenses)) {
derivedLicenses = sourceDerivedLicenses;
} else {
derivedLicenses = derivedLicenses + ", " + sourceDerivedLicenses;
}
}
String licenseDiff = diffLicenses(derivedLicenses, referenceLicense, true);
artifact.set(INVENTORY_KEY_LICENSE_DIFF, licenseDiff);
}
}
public static String diffLicenses(String lhsLicense, String rhsLicense, boolean commaSeparatorOnly) {
lhsLicense = normalizeLicenseOrderAndName(lhsLicense, true, commaSeparatorOnly);
rhsLicense = normalizeLicenseOrderAndName(rhsLicense, true, commaSeparatorOnly);
List licenseTokens = tokenizeLicense(lhsLicense, true, commaSeparatorOnly);
// do not generate a diff, when there is no curated data
if (licenseTokens.isEmpty()) {
return "";
}
List derivedLicenseTokens = tokenizeLicense(rhsLicense, true, commaSeparatorOnly);
List addedTokens = new ArrayList<>();
List removedTokens = new ArrayList<>();
for (String s : licenseTokens) {
if (!derivedLicenseTokens.contains(s)) {
removedTokens.add(s + " (r)");
}
}
for (String s : derivedLicenseTokens) {
if (!licenseTokens.contains(s)) {
addedTokens.add(s + " (a)");
}
}
List diffTokens = new ArrayList<>();
diffTokens.addAll(removedTokens);
diffTokens.addAll(addedTokens);
return String.join(", ", diffTokens);
}
public static String normalizeLicenseOrderAndName(String license, boolean reorder, boolean commaSeparatorOnly) {
if (license == null) return "";
final List licenses = tokenizeLicense(license, reorder, commaSeparatorOnly);
return joinLicenses(licenses);
}
public static void createReportFiles(Inventory inventory, File workDir, String inventoryId, File referenceInventoryDir) {
InventoryReport report = new InventoryReport();
report.setReportContext(new ReportContext(inventoryId, null, inventoryId));
report.setFailOnUnknown(false);
report.setFailOnUnknownVersion(false);
// repository and global inventory are the same
report.setInventory(inventory);
report.setReferenceInventoryDir(referenceInventoryDir);
report.setReferenceInventoryIncludes("**/*-inventory.xls");
report.setReferenceComponentPath(new File(referenceInventoryDir, "components").getAbsolutePath());
report.setReferenceLicensePath(new File(referenceInventoryDir, "licenses").getAbsolutePath());
FileUtils.forceMkDirQuietly(workDir);
report.setFailOnBanned(false);
report.setFailOnDevelopment(false);
report.setFailOnDowngrade(false);
report.setFailOnError(false);
report.setFailOnInternal(false);
report.setFailOnMissingLicense(false);
report.setFailOnMissingLicenseFile(false);
report.setFailOnMissingNotice(false);
report.setTargetReportDir(workDir);
try {
report.createReport();
} catch (Exception e) {
LOG.warn(e.getMessage(), e);
}
}
public static String joinLicenses(Collection licenses) {
return licenses.stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(", "));
}
public static String joinOredLicenses(Collection licenses) {
return licenses.stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(" + "));
}
public static void normalize(List licenses) {
Collections.sort(licenses, String.CASE_INSENSITIVE_ORDER);
}
public static void removeMarkers(Collection licenseList, NormalizationMetaData normalizationMetaData) {
for (String license : new ArrayList<>(licenseList)) {
TermsMetaData termsMetaData = normalizationMetaData.findTermsMetaData(license);
if (termsMetaData != null && termsMetaData.isMarker()) {
licenseList.remove(license);
}
}
}
public static List extractMarkers(Collection licenseList, NormalizationMetaData normalizationMetaData) {
final List markers = new ArrayList<>();
for (String license : new ArrayList<>(licenseList)) {
final TermsMetaData termsMetaData = normalizationMetaData.findTermsMetaData(license);
if (termsMetaData != null && termsMetaData.isMarker()) {
markers.add(license);
}
}
return markers;
}
public static void removeUnspecific(Collection licenseList, NormalizationMetaData normalizationMetaData) {
List del = new ArrayList<>();
for (String license : licenseList) {
TermsMetaData lmd = normalizationMetaData.getTermsMetaData(license);
if (lmd != null) {
if (lmd.isUnspecific()) {
del.add(license);
}
}
}
licenseList.removeAll(del);
}
/**
* Currently naiive implementation to remove redundant licenses. Should use License Metadata.
*
* @param derivedLicenses The derived licenses.
*
* @return Removable licenses that are covered by more specific licenses in the set.
*/
public static Set collectCoveredRemovableLicenses(Set derivedLicenses) {
final Set removableLicenses = new HashSet<>();
for (String l : derivedLicenses) {
if (l.endsWith(" (undefined)")) {
String lm = l.substring(0, l.indexOf(" (undefined)"));
for (String r : derivedLicenses) {
if (!r.equalsIgnoreCase(l) && r.startsWith(lm)) {
removableLicenses.add(l);
}
}
} else if (l.equalsIgnoreCase("BSD alike")) {
for (String r : derivedLicenses) {
if (!r.equalsIgnoreCase(l) && r.startsWith("BSD ") && r.endsWith("-Clause License")) {
removableLicenses.add(l);
}
}
} else if (l.equalsIgnoreCase("MIT alike")) {
for (String r : derivedLicenses) {
if (!r.equalsIgnoreCase(l) && r.equals("MIT License")) {
removableLicenses.add(l);
}
}
}
}
return removableLicenses;
}
@Deprecated // revise
public static void diffBinaryAndSourceDerivedLicenses(Inventory inventory) {
for (Artifact a : inventory.getArtifacts()) {
String derivedLicenseSource = a.get(KEY_SOURCE_ARTIFACT_DERIVED_LICENSES);
String derivedLicenseBinary = a.get(KEY_BINARY_ARTIFACT_DERIVED_LICENSES);
derivedLicenseSource = derivedLicenseSource == null ? "" : derivedLicenseSource.trim();
derivedLicenseBinary = derivedLicenseBinary == null ? "" : derivedLicenseBinary.trim();
if (derivedLicenseSource.equalsIgnoreCase(derivedLicenseBinary)) {
a.set(INVENTORY_KEY_LICENSE_DIFF_SRC_BIN, "-");
} else {
List tokenizedDerivedBinary = InventoryUtils.tokenizeLicense(derivedLicenseBinary, true, true);
List tokenizedDerivedSource = InventoryUtils.tokenizeLicense(derivedLicenseSource, true, true);
List tmp = new ArrayList<>(tokenizedDerivedBinary);
tokenizedDerivedBinary.removeAll(tokenizedDerivedSource);
tokenizedDerivedSource.removeAll(tmp);
List filteredMappedDerivedSource = tokenizedDerivedSource.stream().map(s -> "src: " + s).collect(Collectors.toList());
List filteredMappedDerivedBinary = tokenizedDerivedBinary.stream().map(s -> "bin: " + s).collect(Collectors.toList());
List diff = new ArrayList<>(filteredMappedDerivedSource);
diff.addAll(filteredMappedDerivedBinary);
Collections.sort(diff);
a.set(INVENTORY_KEY_LICENSE_DIFF_SRC_BIN, String.join("\n", diff));
}
}
}
public static String deriveEffectiveLicenses(final String license) {
if (StringUtils.isEmpty(license)) {
return "";
}
String effectiveLicense = license.replace(",", "|").replace("| ", "|");
// apply effective license rules
List licenses = new ArrayList<>(Arrays.asList(effectiveLicense.split("\\|")));
return deriveEffectiveLicenses(licenses);
}
public static String deriveEffectiveLicenses(Collection associatedLicenses) {
List licenses = new ArrayList<>(associatedLicenses);
licenses.remove(MARKER_LICENSING_OPTION);
// FIXME: include generic step that eliminates undefined
// FIXME: (remove duplicates before applying mappings)
String gplUndefined = "GNU General Public License (undefined)";
String gpl3OrLater = "GNU General Public License 3.0 (or any later version)";
String gpl2OrLater = "GNU General Public License 2.0 (or any later version)";
String gpl1OrLater = "GNU General Public License 1.0 (or any later version)";
String gpl3 = "GNU General Public License 3.0";
String gpl2 = "GNU General Public License 2.0";
String gpl1 = "GNU General Public License 1.0";
String lgplUndefined = "GNU Lesser General Public License (undefined)";
String lgpl3OrLater = "GNU Lesser General Public License 3.0 (or any later version)";
String lgpl21OrLater = "GNU Lesser General Public License 2.1 (or any later version)";
String lgpl2OrLater = "GNU Library General Public License 2.0 (or any later version)";
String lgpl2 = "GNU Library General Public License 2.0";
String lgpl3 = "GNU Lesser General Public License 3.0";
String lgpl21 = "GNU Lesser General Public License 2.1";
{
if (licenses.contains(gplUndefined)) {
if (licenses.contains(gpl3) || licenses.contains(gpl3OrLater)) {
replace(licenses, gplUndefined, gpl3);
} else if (licenses.contains(lgpl2) || licenses.contains(lgpl2OrLater)) {
replace(licenses, gplUndefined, gpl2);
} else if (licenses.contains(gpl2) || licenses.contains(gpl2OrLater)) {
replace(licenses, gplUndefined, gpl2);
} else if (licenses.contains(lgpl21) || licenses.contains(lgpl21OrLater)) {
replace(licenses, gplUndefined, gpl2);
} else if (licenses.contains(lgpl3) || licenses.contains(lgpl3OrLater)) {
replace(licenses, gplUndefined, gpl3);
}
replace(licenses, gplUndefined, gpl3);
}
if (licenses.contains(gpl3OrLater) || licenses.contains(gpl3)) {
licenses.remove(gpl2OrLater);
licenses.remove(gpl1OrLater);
replace(licenses, gpl3OrLater, gpl3);
}
if (licenses.contains(gpl2OrLater) || licenses.contains(gpl2)) {
licenses.remove(gpl1OrLater);
replace(licenses, gpl2OrLater, gpl2);
}
if (licenses.contains(gpl1OrLater)) {
replace(licenses, gpl1OrLater, gpl1);
}
}
{
if (licenses.contains(lgplUndefined)) {
if (licenses.contains(lgpl21) || licenses.contains(lgpl21OrLater)) {
if (licenses.contains(lgpl21)) {
replace(licenses, lgplUndefined, lgpl21);
} else {
replace(licenses, lgplUndefined, lgpl21OrLater);
}
} else {
if (licenses.contains(gpl3)) {
replace(licenses, lgplUndefined, lgpl3);
} else {
if (licenses.contains(gpl2)) {
replace(licenses, lgplUndefined, lgpl21);
} else {
replace(licenses, lgplUndefined, lgpl3);
}
}
}
}
// 3.0 or later --> 3.0
if (licenses.contains(lgpl3OrLater) || licenses.contains(lgpl3)) {
licenses.remove(lgpl21OrLater);
licenses.remove(lgpl2OrLater);
replace(licenses, lgpl3OrLater, lgpl3);
}
// 2.1 or later + GPL 3 --> 3.0
if (licenses.contains(lgpl21OrLater) && licenses.contains(gpl3)) {
licenses.remove(lgpl2OrLater);
replace(licenses, lgpl21OrLater, lgpl3);
}
// 2.1 or later + GPL 2 --> 2.1
if (licenses.contains(lgpl21OrLater) && licenses.contains(gpl2)) {
licenses.remove(lgpl2OrLater);
replace(licenses, lgpl21OrLater, lgpl21);
}
// 2.1 or later --> 2.1
if (licenses.contains(lgpl21OrLater) || licenses.contains(lgpl21)) {
licenses.remove(lgpl2OrLater);
replace(licenses, lgpl21OrLater, lgpl21);
}
// 2.1 or later & GPL 3 --> 3.0
if (licenses.contains(lgpl2OrLater) && licenses.contains(gpl3)) {
replace(licenses, lgpl2OrLater, lgpl3);
}
// 2.1 or later & GPL 2 --> 2.1
if (licenses.contains(lgpl2OrLater) && licenses.contains(gpl2)) {
replace(licenses, lgpl2OrLater, lgpl21);
}
// 2.0 or later --> 2.1
if (licenses.contains(lgpl2OrLater)) {
replace(licenses, lgpl2OrLater, lgpl21);
}
}
{
String gfdlUndefined = "GNU Free Documentation License (undefined)";
String gfdl13OrLater = "GNU Free Documentation License 1.3 (or any later version)";
String gfdl12OrLater = "GNU Free Documentation License 1.2 (or any later version)";
String gfdl11OrLater = "GNU Free Documentation License 1.1 (or any later version)";
String gfdl13 = "GNU Free Documentation License 1.3";
String gfdl12 = "GNU Free Documentation License 1.2";
String gfdl11 = "GNU Free Documentation License 1.1";
if (licenses.contains(gfdlUndefined)) {
replace(licenses, gfdlUndefined, gfdl13);
}
if (licenses.contains(gfdl13OrLater) || licenses.contains(gfdl13)) {
licenses.remove(gfdl12OrLater);
licenses.remove(gfdl11OrLater);
replace(licenses, gfdl13OrLater, gfdl13);
}
if (licenses.contains(gfdl12OrLater) || licenses.contains(gfdl12)) {
licenses.remove(gfdl12OrLater);
replace(licenses, gfdl12OrLater, gfdl12);
}
if (licenses.contains(gfdl11OrLater)) {
replace(licenses, gfdl11OrLater, gfdl11);
}
}
{
String lpplUndefined = "LaTeX Project Public License (undefined)";
String lppl12OrLater = "LaTeX Project Public License 1.2 (or any later version)";
String lppl11OrLater = "LaTeX Project Public License 1.1 (or any later version)";
String lppl10OrLater = "LaTeX Project Public License 1.0 (or any later version)";
String lppl12 = "LaTeX Project Public License 1.2";
String lppl11 = "LaTeX Project Public License 1.1";
String lppl10 = "LaTeX Project Public License 1.0";
if (licenses.contains(lpplUndefined)) {
replace(licenses, lpplUndefined, lppl12);
}
if (licenses.contains(lppl12OrLater) || licenses.contains(lppl12)) {
licenses.remove(lppl11OrLater);
licenses.remove(lppl10OrLater);
replace(licenses, lppl12OrLater, lppl12);
}
if (licenses.contains(lppl11OrLater) || licenses.contains(lppl11)) {
licenses.remove(lppl10OrLater);
replace(licenses, lppl11OrLater, lppl11);
}
if (licenses.contains(lppl10OrLater)) {
replace(licenses, lppl10OrLater, lppl10);
}
}
{
String beopen = "BeOpen Python Open Source License Agreement 1.0";
String cnri = "CNRI License Agreement";
String permission = "Permission Terms (no advertising; no warranty; no liability)"; // CWI permission
String phyton = "Python Software Foundation License 2.0";
if (licenses.contains(beopen) && licenses.contains(cnri) && licenses.contains(permission) && licenses.contains(phyton)) {
licenses.remove(beopen);
licenses.remove(cnri);
licenses.remove(permission);
}
}
{
String bsdUndefined = "BSD (undefined)";
String bsd3Clause = "BSD 3-Clause License";
if (licenses.contains(bsdUndefined)) {
licenses.remove(bsdUndefined);
licenses.add(bsd3Clause);
}
}
{
String apacheLicenseUndefined = "Apache License (undefined)";
String apacheLicense20 = "Apache License 2.0";
if (licenses.contains(apacheLicenseUndefined)) {
licenses.remove(apacheLicenseUndefined);
licenses.add(apacheLicense20);
}
}
{
String licenseUndefined = "Mozilla Public License (undefined)";
String license20 = "Mozilla Public License 2.0";
if (licenses.contains(licenseUndefined)) {
licenses.remove(licenseUndefined);
licenses.add(license20);
}
}
{
String cddlUndefined = "CDDL (undefined)";
String cddl10 = "CDDL 1.0";
String cddl11 = "CDDL 1.1";
// remove unspecific if specific are available
if (licenses.contains(cddl10) && licenses.contains(cddl11)) {
licenses.remove(cddlUndefined);
}
// replace unspecific with 1.0
if (licenses.contains(cddlUndefined)) {
replace(licenses, cddlUndefined, cddl10);
}
}
for (String l : new ArrayList<>(licenses)) {
replaceLicense(licenses, l, "FreeType Project License + GNU General Public License 2.0 (or any later version)", "FreeType Project License");
replaceLicense(licenses, l, "GNU Library General Public License 2.0 (or any later version) + GNU General Public License 2.0 (or any later version) + Mozilla Public License (undefined)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Netscape + GNU General Public License 2.0 (or any later version) + GNU Library General Public License 2.0 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "BSD 3-Clause License (variant 003) + GNU General Public License (undefined)", "BSD 3-Clause License (variant 003)");
replaceLicense(licenses, l, "BSD 3-Clause License (variant 003) + GNU General Public License 2.0", "BSD 3-Clause License (variant 003)");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 (or any later version), GNU Library General Public License 2.0 (or any later version) + GNU General Public License 2.0 (or any later version) + Mozilla Public License (undefined)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Netscape + GNU General Public License 2.0 (or any later version) + GNU Library General Public License 2.0 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Apache License 2.0 + CC0 Universal 1.0", "Apache License 2.0");
replaceLicense(licenses, l, "Mozilla Public License 2.0 + GNU General Public License 2.0 (or any later version)", "Mozilla Public License 2.0");
replaceLicense(licenses, l, "Mozilla Public License 1.1 + GNU Lesser General Public License 2.1 (or any later version) + GNU General Public License 2.0 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Academic Free License 2.1", "GNU General Public License 2.0");
replaceLicense(licenses, l, "Apache License 2.0 + MIT License", "Apache License 2.0");
replaceLicense(licenses, l, "GNU General Public License 3.0 (or any later version) + MIT License", "MIT License");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Academic Free License 2.0", "GNU General Public License 2.0");
// xx
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + GNU Lesser General Public License 3.0 (or any later version)", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "Mozilla Public License 1.1 + GNU General Public License 2.0 + GNU Lesser General Public License 2.1", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "GNU Lesser General Public License 3.0 + GNU General Public License 2.0", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 + GNU Lesser General Public License 2.1", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 + Mozilla Public License 2.0 + GNU General Public License 2.0", " GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "MIT License + GNU Genral Public License 3.0", "MIT License");
replaceLicense(licenses, l, "MIT License + GNU General Public License 3.0", "MIT License");
replaceLicense(licenses, l, "GNU General Public License 2.0 + GNU Lesser General Public License 3.0", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "Mozilla Public License 1.1 + GNU General Public License 2.0 + GNU Lesser General Public License 2.1", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "MIT License + GNU General Public License 3.0", "MIT License");
replaceLicense(licenses, l, "GNU General Public License 2.0 + GNU Lesser General Public License 3.0", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "MIT License + GNU General Public License 3.0", "MIT License");
replaceLicense(licenses, l, "MIT License + GNU General Public License 3.0 (or any later version)", "MIT License");
replaceLicense(licenses, l, "Apache License 2.0 + CC0 Universal (undefined)", "Apache License 2.0");
replaceLicense(licenses, l, "Mozilla Public License 1.1 + GNU General Public License 2.0 (or any later version) + GNU Lesser General Public License 2.1 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "GNU Lesser General Public License 3.0 (or any later version) + GNU General Public License 2.0 (or any later version)", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + GNU Lesser General Public License 2.1 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 (or any later version) + Mozilla Public License 2.0 + GNU General Public License 2.0 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "GNU General Public License 1.0 (or any later version) + Artistic License (undefined)", "GNU General Public License 2.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + X11 License", "X11 License");
replaceLicense(licenses, l, "GNU General Public License 2.0 + GNU Free Documentation License 1.1 (or any later version)", "GNU General Public License 2.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Transitive Grace Period Public Licence 1.0 (or any later version)", "GNU General Public License 2.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + GNU Lesser General Public License 3.0 (or any later version)", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + GNU Lesser General Public License version 3.0 (or any later version)", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + GNU Lesser General Public License 3.0 (or any later version)", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "MIT License + GNU Genral Public License 3.0 (or any later version)", "MIT License");
replaceLicense(licenses, l, "MIT License + GNU General Public License 3.0 (or any later version)", "MIT License");
replaceLicense(licenses, l, "MIT License + GNU General Public License 2.0 (or any later version)", "MIT License");
replaceLicense(licenses, l, "MIT License + GNU General Public License 2.0", "MIT License");
replaceLicense(licenses, l, "GNU Lesser General Public License (undefined)", "GNU Lesser General Public License 2.1");
// review with TLS
replaceLicense(licenses, l, "Artistic License (undefined) + GNU General Public License 1.0", "Artistic License 1.0");
replaceLicense(licenses, l, "Artistic License 1.0 + GNU General Public License 1.0", "Artistic License 1.0");
replaceLicense(licenses, l, "GNU Lesser General Public License 3.0 + Creative Commons BY-SA 3.0", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "Frontier Artistic License (undefined) + GNU General Public License (undefined)", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "Frontier Artistic License (undefined) + GNU General Public License 1.0", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "Frontier Artistic License 1.0 + GNU General Public License (undefined)", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "Frontier Artistic License 1.0 + GNU General Public License 3.0", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "Frontier Artistic License 1.0 + GNU General Public License 2.0", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "Frontier Artistic License 1.0 + GNU General Public License 1.0", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "GNU General Public License 1.0 + Artistic License (undefined)", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "Artistic License (undefined) + GNU General Public License 1.0 (or any later version)", "Artistic License 1.0");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 + Mozilla Public License 1.1", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Artistic License 1.0 + GNU General Public License 1.0", "Artistic License 1.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 + GNU Lesser General Public License 2.1 + Mozilla Public License 1.1", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "HSIEH-DERIVATIVE + HSIEH-BSD + GNU Lesser General Public License 2.1", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Artistic License 1.0 (Perl)", "Artistic License 1.0 (Perl)");
replaceLicense(licenses, l, "GNU General Public License 1.0 (or any later version) + Artistic License 1.0 (Perl)", "Artistic License 1.0 (Perl)");
replaceLicense(licenses, l, "GNU General Public License 1.0 + Artistic License 1.0 (Perl)", "Artistic License 1.0 (Perl)");
replaceLicense(licenses, l, "Expat License + GNU General Public License 1.0 + Artistic License 1.0 (Perl)", "Expat License");
replaceLicense(licenses, l, "Expat License + GNU General Public License 1.0 (or any later version) + Artistic License 1.0 (Perl)", "Expat License");
replaceLicense(licenses, l, "GNU General Public License 3.0 (or any later version) + GNU Free Documentation License 1.2 (or any later version)", "GNU General Public License 3.0 (or any later version)");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + FreeType Project License", "GNU General Public License 2.0 (or any later version)");
replaceLicense(licenses, l, "Mozilla Public License 1.1 + GNU General Public License 2.0 + Apache License 2.0", "Apache License 2.0");
replaceLicense(licenses, l, "CDDL 1.1 + GPL 2.0 with classpath exception", "CDDL 1.1");
replaceLicense(licenses, l, "CDDL 1.1 + GNU General License 2.0", "CDDL 1.1");
replaceLicense(licenses, l, "CDDL 1.1 + GNU General Public License 2.0", "CDDL 1.1");
replaceLicense(licenses, l, "CDDL 1.0 + GNU General Public License 2.0", "CDDL 1.0");
replaceLicense(licenses, l, "Apache License 2.0 + GNU General Public License 3.0 (or any later version)", "Apache License 2.0");
replaceLicense(licenses, l, "BSD 3-Clause License + GNU General Public License 3.0 (or any later version)", "BSD 3-Clause License");
replaceLicense(licenses, l, "BSD 3-Clause License (variant 013) + GNU General Public License (undefined)", "BSD 3-Clause License (variant 013)");
replaceLicense(licenses, l, "CDDL 1.0 + GNU General Public License 2.0 (with classpath exception)", "CDDL 1.0");
replaceLicense(licenses, l, "CDDL 1.0 + GNU General Public License 2.0 (with Oracle classpath exception)", "CDDL 1.0");
replaceLicense(licenses, l, "CDDL 1.1 + GNU General Public License 2.0 (with Oracle classpath exception)", "CDDL 1.1");
replaceLicense(licenses, l, "CDDL 1.1 + GNU General Public License 2.0 (with classpath exception)", "CDDL 1.1");
replaceLicense(licenses, l, "CDDL 1.0 + GNU General Public License 2.0 (with Sun classpath exception)", "CDDL 1.0");
replaceLicense(licenses, l, "CDDL 1.1 + GPL 2 (with classpath exception)", "CDDL 1.1");
replaceLicense(licenses, l, "CDDL 1.0 + GPL 2 (with classpath exception)", "CDDL 1.0");
replaceLicense(licenses, l, "CDDL 1.1 + GPL 2 with classpath exception", "CDDL 1.1");
replaceLicense(licenses, l, "CDDL 1.0 + GPL 2 with classpath exception", "CDDL 1.0");
replaceLicense(licenses, l, "Apache License 2.0 + GNU Lesser General Public License 2.1 (or any later version)", "Apache License 2.0");
replaceLicense(licenses, l, "Apache License 2.0 + GNU Lesser General Public License 3.0 (or any later version)", "Apache License 2.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Mozilla Public License 1.1", "Mozilla Public License 1.1");
replaceLicense(licenses, l, "Eclipse Public License 1.0 + Mozilla Public License 2.0", "Eclipse Public License 1.0");
replaceLicense(licenses, l, "Eclipse Public License 1.0 + GNU Lesser General Public License 2.1", "Eclipse Public License 1.0");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 + Creative Commons BY-SA 4.0", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Eclipse Public License 2.0 + GNU General Public License 2.0 (with classpath exception)", "Eclipse Public License 2.0");
replaceLicense(licenses, l, "Eclipse Public License 1.0 + GNU General Public License 2.0 (with classpath exception)", "Eclipse Public License 1.0");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Eclipse Public License 1.0 + Apache License 2.0", "Apache License 2.0");
replaceLicense(licenses, l, "GNU General Public License (undefined) + Frontier Artistic License", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "Frontier Artistic License", "Frontier Artistic License 1.0");
replaceLicense(licenses, l, "MIT License + NCSA License", "MIT License");
replaceLicense(licenses, l, "Public Domain + BSD alike", "Public Domain");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + gSOAP Public License + Genivia's Commercial License", "gSOAP Public License");
replaceLicense(licenses, l, "Mozilla Public License 1.1 + GNU Library General Public License 2.0 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Mozilla Public License 1.1 + GNU Library General Public License 2.0 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Eclipse Public License 1.0 + Mozilla Public License 2.0", "Eclipse Public License 2.0");
replaceLicense(licenses, l, "Eclipse Public License 1.0 + GNU Lesser General Public License 3.0 (or any later version) + Mozilla Public License 2.0", "Eclipse Public License 2.0");
replaceLicense(licenses, l, "Apache License 2.0 + Mozilla Public License 1.1 + GNU Lesser General Public License 2.1 (or any later version)", "Apache License 2.0");
replaceLicense(licenses, l, "Mozilla Public License 1.1 + GNU Lesser General Public License 2.1 (or any later version) + Apache License 2.0", "Apache License 2.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 + GNU General Public License 2.0 (with classpath exception)", "GNU General Public License 2.0 (with classpath exception)");
replaceLicense(licenses, l, "Apache License 2.0 + GNU Lesser General Public License 3.0", "Apache License 2.0");
replaceLicense(licenses, l, "CDDL 1.1 + GNU General Public License 2.0 (with classpath exception)", "CDDL 1.1");
replaceLicense(licenses, l, "BSD 3-Clause License (copyright variant) + GNU General Public License (undefined)", "BSD 3-Clause License (copyright holder variant)");
replaceLicense(licenses, l, "BSD 3-Clause License (copyright holder variant) + GNU General Public License (undefined)", "BSD 3-Clause License (copyright holder variant)");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 + Eclipse Public License 1.0", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "CDDL (undefined) + GNU General Public License 2.0 (with classpath exception), CDDL 1.0", "CDDL 1.0");
replaceLicense(licenses, l, "Apache License 2.0 + GNU Lesser General Public License 2.1 (or any later version) + Mozilla Public License 1.1", "Apache License 2.0");
replaceLicense(licenses, l, "Academic Free License 2.1 + GNU Library General Public License 2.0", "GNU Library General Public License 2.0");
replaceLicense(licenses, l, "GNU General Public License 1.0 (or any later version) + MIT License", "MIT License");
replaceLicense(licenses, l, "CDDL 1.0 + GNU General Public License 2.0 (with classpath exception 2.0)", "CDDL 1.0");
replaceLicense(licenses, l, "CDDL (undefined) + GNU General Public License 2.0 (with classpath exception 2.0)", "CDDL 1.0");
replaceLicense(licenses, l, "BSD 2-Clause License (copyright holder variant) + GNU General Public License (undefined) 002", "BSD 2-Clause License (copyright holder variant)");
replaceLicense(licenses, l, "GNU General Public License (undefined) 002", "GNU General Public License (undefined)");
replaceLicense(licenses, l, "GNU General Public License 3.0 002", "GNU General Public License 3.0");
replaceLicense(licenses, l, "Eclipse Public License 1.0 + GNU Lesser General Public License 2.1", "Eclipse Public License 1.0");
replaceLicense(licenses, l, "MIT License + CC0 Universal 1.0", "MIT License");
replaceLicense(licenses, l, "Eclipse Public License 2.0 + GNU General Public License 2.0 (with classpath exception)", "Eclipse Public License 2.0");
replaceLicense(licenses, l, "Eclipse Public License 2.0 + GNU General Public License 2.0 (with classpath exception)", "Eclipse Public License 2.0");
replaceLicense(licenses, l, "Eclipse Public License 2.0 + GNU General Public License 2.0", "Eclipse Public License 2.0");
replaceLicense(licenses, l, "CDDL 1.1 + GNU General Public License 2.0 (with classpath exception 2.0)", "CDDL 1.1");
replaceLicense(licenses, l, "GNU Lesser General Public License 3.0 (or any later version) + GNU General Public License 2.0 (or any later version)", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "GNU General Public License 1.0 + Artistic License (undefined)", "GNU General Public License 1.0");
replaceLicense(licenses, l, "BSD 3-Clause License (variant 003) + GNU General Public License (undefined)", "BSD 3-Clause License (variant 003)");
replaceLicense(licenses, l, "Apache License 2.0 + GNU General Public License 2.0", "Apache License 2.0");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 + Eclipse Public License 2.0", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Apache License 1.1 + Apache License 2.0 + BSD (undefined) + Public Domain + Indiana University Extreme! Lab Software License 1.1.1", "Apache License 2.0");
replaceLicense(licenses, l, "LGPLv2 + with exceptions", "GNU Library General Public License 2.0");
replaceLicense(licenses, l, "GPLv2 + with exceptions", "GNU General Public License 2.0 (or any later version; with exceptions)");
replaceLicense(licenses, l, "GPLv3 + with exceptions", "GNU General Public License 3.0 (or any later version; with exceptions)");
replaceLicense(licenses, l, "CDDL (undefined) + GNU General Public License 2.0 (with classpath exception), CDDL 1.0 + GNU General Public License 2.0 (with classpath exception), GNU General Public License 2.0 (with classpath exception)", "CDDL 1.0 + GNU General Public License 2.0 (with classpath exception)");
replaceLicense(licenses, l, "GNU General Public License 1.0 (or any later version) + Artistic License 1.0", "GNU General Public License 2.0");
replaceLicense(licenses, l, "GNU General Public License 1.0 (or any later version) + Artistic License (undefined)", "GNU General Public License 2.0");
replaceLicense(licenses, l, "GNU General Public License (undefined) + Artistic License (undefined)", "GNU General Public License (undefined)");
replaceLicense(licenses, l, "GNU Lesser General Public License 2.1 + Mozilla Public License 1.1 + GNU General Public License 2.0 (or any later version)", "GNU Lesser General Public License 2.1");
// Red Hat Linux
replaceLicense(licenses, l, "GNU General Public License (undefined; or any later version) + Artistic License (undefined)", "GNU General Public License 2.0"); // REVIEW
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Artistic License (undefined)", "GNU General Public License 2.0"); // REVIEW
replaceLicense(licenses, l, "Artistic License 1.0 (Perl) + GNU General Public License 1.0 (or any later version)", "GNU General Public License 2.0 (or any later version)"); // REVIEW
replaceLicense(licenses, l, "Artistic License 1.0 + GNU General Public License 1.0 (or any later version)", "GNU General Public License 2.0 (or any later version)"); // REVIEW
replaceLicense(licenses, l, "BSD 3-Clause License (copyright holder variant) + GNU General Public License 2.0", "BSD 3-Clause License (copyright holder variant)");
replaceLicense(licenses, l, "GNU General Public License 2.0 + Linux Kernel Variant of OpenIB.org License", "Linux Kernel Variant of OpenIB.org License");
replaceLicense(licenses, l, "OpenSSL License + Original SSLeay License", "OpenSSL License");
replaceLicense(licenses, l, "Academic Free License 2.1 + GNU General Public License 2.0 (or any later version)", "Academic Free License 2.1");
replaceLicense(licenses, l, "Academic Free License 2.1 + GNU General Public License 2.0", "Academic Free License 2.1");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Open Software License 2.1", "Open Software License 2.1");
replaceLicense(licenses, l, "BSD 3-Clause License + GNU General Public License 2.0", "BSD 3-Clause License");
replaceLicense(licenses, l, "MIT License + X11 License", "MIT License");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + GNU General Public License 3.0", "GNU General Public License 2.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 + GNU Lesser General Public License 3.0 (or any later version)", "GNU General Public License 2.0");
replaceLicense(licenses, l, "Cavium EULA + Apache License 2.0", "Apache License 2.0");
replaceLicense(licenses, l, "GNU Lesser General Public License 3.0 (or any later version) + GNU General Public License 2.0", "GNU Lesser General Public License 3.0");
replaceLicense(licenses, l, "Artistic License (undefined) + GNU Lesser General Public License (undefined)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "BSD 3-Clause License + GNU Lesser General Public License 2.1 (or any later version)", "BSD 3-Clause License");
replaceLicense(licenses, l, "BSD 3-Clause License + GNU General Public License 2.0 (or any later version)", "BSD 3-Clause License");
// eclipse-bundles / java
replaceLicense(licenses, l, "FreeType Project License + GNU General Public License 2.0", "FreeType Project License");
replaceLicense(licenses, l, "Eclipse Public License 1.0 (or any later version) + GNU Lesser General Public License 2.1 (or any later version) + GNU General Public License 2.0 (or any later version) + Apache License 2.0 (or any later version) + BSD 3-Clause License", "Apache License 2.0");
replaceLicense(licenses, l, "CDDL 1.1 + GNU General Public License 2.0 (with classpath exception)", "CDDL 1.1");
// 004
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Mozilla Public License (undefined)", "Mozilla Public License 2.0");
replaceLicense(licenses, l, "Academic Free License 2.1 + GNU General Public License 2.0 (or any later version)", "Academic Free License 2.1");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + Academic Free License (undefined)", "Academic Free License 2.1");
replaceLicense(licenses, l, "Apache License 2.0 + Boost Software License 1.0", "Apache License 2.0");
replaceLicense(licenses, l, "Apache License 2.0 + Eclipse Public License 1.0 + Eclipse Public License 2.0", "Apache License 2.0");
replaceLicense(licenses, l, "Apache License 2.0 + BSD (undefined)", "Apache License 2.0");
replaceLicense(licenses, l, "BSD 3-Clause License (Libcap) + GNU General Public License 2.0", "BSD 3-Clause License (Libcap)");
replaceLicense(licenses, l, "GNU Library General Public License 2.0 (or any later version) + GNU General Public License 2.0 (or any later version) + Mozilla Public License (undefined)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "Netscape Public License (undefined) + GNU General Public License 2.0 (or any later version) + GNU Library General Public License 2.0 (or any later version)", "GNU Lesser General Public License 2.1");
replaceLicense(licenses, l, "GNU General Public License 3.0 (or any later version) + BSD (undefined)", "GNU General Public License 3.0");
replaceLicense(licenses, l, "GNU General Public License 2.0 + BSD (undefined)", "GNU General Public License 2.0");
replaceLicense(licenses, l, "BSD (undefined) + GNU General Public License 2.0", "GNU General Public License 2.0");
replaceLicense(licenses, l, "BSD (undefined) + GNU General Public License 2.0 (or any later version)", "GNU General Public License 2.0");
replaceLicense(licenses, l, "BSD (undefined) + GNU General Public License (undefined; or any later version)", "GNU General Public License 3.0");
replaceLicense(licenses, l, "Apache License 2.0 + Eclipse Public License 1.0", "Apache License 2.0");
replaceLicense(licenses, l, "Eclipse Public License 2.0 + Apache License 2.0", "Apache License 2.0");
replaceLicense(licenses, l, "CDDL (undefined) + GNU General Public License 2.0 (with classpath exception)", "CDDL 1.0");
replaceLicense(licenses, l, "BSD 3-Clause License (variant 003) + GNU Library General Public License 2.0 (or any later version)", "BSD 3-Clause License (variant 003)");
replaceLicense(licenses, l, "BSD 4-Clause License (UC) + Permission Terms (variant 137)", "BSD 4-Clause License (UC)");
replaceLicense(licenses, l, "BSD 2-Clause License (copyright holder variant) + GNU General Public License 2.0 (or any later version)", "BSD 2-Clause License (copyright holder variant)");
replaceLicense(licenses, l, "GNU General Public License 2.0 (or any later version) + GNU Lesser General Public License 2.1 (or any later version) + Mozilla Public License 1.1 + BSD 2-Clause License (copyright holder variant)", "BSD 2-Clause License (copyright holder variant)");
replaceLicense(licenses, l, "OpenSSL License + BSD 3-Clause License (copyright holder variant) + GNU General Public License (undefined)", "BSD 3-Clause License (copyright holder variant)");
replaceLicense(licenses, l, "OpenSSL License + BSD 3-Clause License (copyright holder variant) + GNU General Public License 2.0", "BSD 3-Clause License (copyright holder variant)");
replaceLicense(licenses, l, "Public Domain + BSD (undefined)", "Public Domain");
}
licenses.stream().filter(l -> l.contains(" + ")).forEach(l -> LOG.info("License [{}] still contains a license option!", l));
String derived = licenses.stream().distinct().sorted().collect(Collectors.joining("|"));
// handle undefined / or any later version:
derived = derived.replace(" (undefined; or any later version)", "(undefined)");
// handle undefined:
derived = derived.replace("Artistic License (undefined)", "Artistic License 1.0");
derived = derived.replace("CC0 Universal (undefined)", "CC0 Universal 1.0");
derived = derived.replace("CC0 Universal License (undefined)", "CC0 Universal 1.0");
derived = derived.replace("GNU Lesser General Public License (undefined)", "GNU Lesser General Public License 2.1");
derived = derived.replace("GNU General Public License (undefined)", "GNU General Public License 2.0");
derived = derived.replace("Eclipse Public License (undefined)", "Eclipse Public License 2.0");
// handle EPL 1.0 to EPL 2.0
derived = derived.replace("Eclipse Public License 1.0", "Eclipse Public License 2.0");
derived = derived.replace(" (or any later version)", "");
derived = derived.replace(" (or any later version; ", " (");
return derived;
}
protected static void replaceLicense(List licenses, String l, String dual, String replace) {
if (l.equals(dual)) {
if (licenses.remove(dual)) {
// only if the removal changed something we do the addon
licenses.add(replace);
}
}
}
public static void replace(List licenses, String gpl2OrLater, String gpl2) {
int index = licenses.indexOf(gpl2OrLater);
if (index != -1) {
licenses.remove(gpl2OrLater);
licenses.add(index, gpl2);
}
}
public static void removeNonPublicArtifacts(Inventory referenceInventory) {
referenceInventory.getArtifacts().removeIf(artifact -> !isPublicArtifact(artifact));
}
/**
* Returns true in case the Public field is TRUE or null.
*
* @param artifact Artifact to check.
*
* @return Whether the artifact is public or not.
*/
public static boolean isPublicArtifact(Artifact artifact) {
String sPublic = artifact.get("Public");
// defaults to true
if (sPublic == null) {
sPublic = String.valueOf(Boolean.TRUE);
}
return String.valueOf(Boolean.TRUE).equalsIgnoreCase(sPublic);
}
public static void updatePackageLicenseNotice(org.metaeffekt.core.inventory.processor.model.LicenseMetaData lmd) {
StringBuilder sb = new StringBuilder();
String newline = String.format("%n");
String license = lmd.getLicense();
String licensesInEffect = lmd.deriveLicenseInEffect();
sb.append("The package ").
append(lmd.getComponent()).
append(" in the present version is licensed under ").
append(convertAssociatedLicenseToText(license)).
append(".
").
append(newline);
if (!tokenizeLicense(license, true, false).equals(
tokenizeLicense(licensesInEffect, true, false))) {
sb.append("As effective licenses for distribution ").
append(licensesInEffect.replace("|", ", "));
if (licensesInEffect.contains("|")) {
sb.append(" have been identified.");
} else {
sb.append(" has been identified.");
}
sb.append("
").append(newline);
if (license.contains("GNU Affero General Public License") && !licensesInEffect.contains("GNU Affero General Public License")) {
sb.append("In particular, the GNU Affero General Public License does not apply as the " +
"affected portions are not part of the distribution.
");
}
}
sb.append("Detailed licensing information can be found in the copyright file " +
"included in the software distribution annex.
").append(newline);
sb.append("The corresponding source code of the covered open source components is provided on demand.
");
lmd.setNotice(sb.toString());
if (licensesInEffect.contains(" + ")) {
throw new IllegalStateException("Undecided effective license detected " + license + " --> " + licensesInEffect);
}
}
private static String convertAssociatedLicenseToText(String license) {
int lastIndexOfComma = license.lastIndexOf(",");
if (lastIndexOfComma != -1) {
String replacement = license.substring(0, lastIndexOfComma) + ", and " + license.substring(lastIndexOfComma + 1);
replacement = replacement.replaceAll("and ", "and ");
return replacement;
}
return license;
}
public static String escapeXml(String s) {
return StringEscapeUtils.escapeXml(s);
}
public static String filterAuthors(String authors) {
final String[] split = authors.split("\\|\\n");
final List list = new ArrayList<>(Arrays.asList(split));
for (String author : new ArrayList<>(list)) {
String improved = author.replaceAll("> ", ">, ");
improved = improved.replaceAll("Patrick McHardy, ", "Patrick McHardy ");
improved = improved.replaceAll("Alexey Kuznetsov, ", "Alexey Kuznetsov ");
improved = improved.replaceAll("McHardy\\.", "McHardy");
improved = improved.replace(", ,", ", ");
improved = improved.replace(" ,", ",");
list.remove(author);
if (StringUtils.hasText(improved)) {
list.add(improved);
}
}
Collections.sort(list, String::compareToIgnoreCase);
return String.join(DELIMITER_NEWLINE, list);
}
private static final Set filterFullList = new HashSet<>();
static {
filterFullList.add("(c) MethodHandle mh MethodHandle");
filterFullList.add("(c) ECFieldElement A1");
filterFullList.add("(c) Nat224.isOne");
filterFullList.add("(c) Epsi (c)");
filterFullList.add("(c) Ia\u001AIu (c) Y");
filterFullList.add("(c) IoIof (c)");
filterFullList.add("(c) iu.'e iuiu.be");
filterFullList.add("(c) KE- (c) K");
filterFullList.add("(c) m (c) D");
filterFullList.add("(c) \u0004I (c) I\n(c) \u0005a1/2 (c) I");
filterFullList.add("(c) \u0000\u0002\u0003K\u0001IoIo\u0000\u0002\u0003K\u0001I (c) I");
filterFullList.add("(c) X\"\u0000zE (c) ID");
filterFullList.add("?");
filterFullList.add("Apache Maven");
filterFullList.add("A. (c) B. (c)");
filterFullList.add("[(c) AIQAEBnI L]");
filterFullList.add("(c) deg (c) A]");
filterFullList.add("A9 (c)");
filterFullList.add("|C/!23th'yuyPy*y,y1yoy th1/4th1/2y3/4th?yAuAnA1/2* (c) Y");
filterFullList.add("$', RegexOptions.None, abac', Pass. Group");
filterFullList.add("$? (c) Y");
filterFullList.add("$?1/2P u,O / !- http://www.wretch.cc/blog/fsj&article_id");
filterFullList.add("(c) (c) (c) (c) (c) (c) (c) (c) A989 A98A");
filterFullList.add("(c) A");
filterFullList.add("(c) and G G G");
filterFullList.add("(c) COMMA");
filterFullList.add("(c) CSTYLED");
filterFullList.add("(c) CTRLC");
filterFullList.add("(c) QUIT");
filterFullList.add("(c) UNDEFINED"); // REVIEW-MARKER
filterFullList.add("(r)+-u,o 1/4AAEEIIOOxUUThssaaaceeeiiiiddnnooouoooAoUoynyd@iiiieeecaeaaassThUUxOONIIEEAEAAAAou-a!3+- (c) Y");
filterFullList.add(",$?o2Y$?1$? <$?E'O$?1$?e3/4UoU$?I!$?EI$?I http://www.w3.org/TR/NOTE-sgml-xml'>");
filterFullList.add("(c). (c)");
filterFullList.add("(c). (R). End");
filterFullList.add("(c). .It Ar");
filterFullList.add("(c). A");
filterFullList.add("(c). C");
filterFullList.add("(c). C1B");
filterFullList.add("(c). cipher/blowfish-arm.S Ditto");
filterFullList.add("(c). D.");
filterFullList.add("(c). END T2");
filterFullList.add("(c). Explicitly");
filterFullList.add("(c). FAILED");
filterFullList.add("(c). Genera");
filterFullList.add("(c). I1 CONSTANT");
filterFullList.add("(c). inline UBool");
filterFullList.add("(c). Instead group");
filterFullList.add("(c). intel/eu Fix");
filterFullList.add("(c). Looping");
filterFullList.add("(c). LxuGAU");
filterFullList.add("(c). Op1");
filterFullList.add("(c). Seemingly");
filterFullList.add("(c). Set");
filterFullList.add("(c). Similarly");
filterFullList.add("(c). TESTS");
filterFullList.add("(c). Therefore");
filterFullList.add("(c). Thus");
filterFullList.add("(c). trans-common.c Forward");
filterFullList.add("(c). Try");
filterFullList.add("(c). UnicodeString");
filterFullList.add("(c). We'll");
filterFullList.add("(c). xT6,g MxtE99");
filterFullList.add("(c).all Sections (First).all then Group");
filterFullList.add("(c)1 a (c) I");
filterFullList.add("(c)1 e (c) I");
filterFullList.add("Copyright $y. $z Free Software Foundation");
filterFullList.add("Copyright $year Free Software Foundation, Inc.");
filterFullList.add("(c) 1947 Editions Gallimard"); // REVIEW-MARKER
filterFullList.add("(c) 2/I Capture group");
filterFullList.add("(c) <2014>");
filterFullList.add("(c) <2015>");
filterFullList.add("(c) A F0");
filterFullList.add("(c) A M1Nj");
filterFullList.add("(c) ASSERT valid, Failure");
filterFullList.add("(c) Attribut BIND");
filterFullList.add("(c) BasicBlock Entry"); // REVIEW-MARKER
filterFullList.add("(c) BasicBlock EntryBB"); // REVIEW-MARKER
filterFullList.add("(c) BLANK Fortran");
filterFullList.add("(c) Bob Smith");
filterFullList.add("(c) BOOL F1");
filterFullList.add("(c) Borrowed pragma Assert");
filterFullList.add("(c) BranchInst BI BranchInst::Create(Exit, Exit, False, Entry)");
filterFullList.add("(c) C (c) 0BA11AB");
filterFullList.add("(c) C . C");
filterFullList.add("(c) C C.Next");
filterFullList.add("(c) C EOF. Modern");
filterFullList.add("(c) C Fz");
filterFullList.add("(c) C Scope");
filterFullList.add("(c) C Temp");
filterFullList.add("(c) C/ (c) PS");
filterFullList.add("(c) CAEC/$?eEC/AIUxIC http://www.w3.org/XML");
filterFullList.add("(c) CMD Coding Method Delimiter E CNL Cursor Next Line E Pn");
filterFullList.add("(c) co");
filterFullList.add("(c) Col Col");
filterFullList.add("(c) Communication Foundation");
filterFullList.add("(c) Constant NullV2I32Ptr");
filterFullList.add("(c) Constant One");
filterFullList.add("(c) Constant PosDividendC");
filterFullList.add("(c) Constant PosDivisorC");
filterFullList.add("(c) ConstantInt C2");
filterFullList.add("(c) CopFILE (c)");
filterFullList.add("(c) CopFILESV (c)");
filterFullList.add("(c) DaI (c)");
filterFullList.add("(c) Di3jSS (c)");
filterFullList.add("(c) Dingsbums GmbH"); // TEST CASE / TEST STRING (gettext)
filterFullList.add("(c) Frobby Inc."); // TEST CASE / TEST STRING (gettext)
filterFullList.add("(c) E AIUeIACIy");
filterFullList.add("(c) Ee-EaEuE OIuI");
filterFullList.add("(c) EFa4 (c)");
filterFullList.add("(c) EO*eUxICEI http://www.w3.org/TR/NOTE-sgml-xml'");
filterFullList.add("(c) ErrMsg CodeView Error");
filterFullList.add("(c) ErrMsg DIA Error");
filterFullList.add("(c) ErrMsg MSF Error");
filterFullList.add("(c) ErrMsg Native PDB Error");
filterFullList.add("(c) ErrMsg PDB Error");
filterFullList.add("(c) ErrMsg Stream Error");
filterFullList.add("(c) ExifDataType dt ExifEntry");
filterFullList.add("(c) expose one performance counter group");
filterFullList.add("(c) EYe3ee (c)"); // JAPANESE
filterFullList.add("(c) E|ESSE|E (c) I"); // .raw
filterFullList.add("(c) FcChar16 numbers FcCharSetNumbers");
filterFullList.add("(c) FcFontSet new FcFontSetCreate");
filterFullList.add("(c) FE Found M88RS2000");
filterFullList.add("(c) FE Found Stv0288 6LME2510");
filterFullList.add("(c) FE Found Stv0299 6LME2510");
filterFullList.add("(c) Firmware Status");
filterFullList.add("(c) FOR NON-MODEL NUMBERS");
filterFullList.add("(c) FRM Changing");
filterFullList.add("(c) FRM Could");
filterFullList.add("(c) FRM Firmware Cold Reset");
filterFullList.add("(c) FRM Firmware Download Completed - Resetting Device");
filterFullList.add("(c) FRM Firmware Download Completed - Resetting Device 6LME2510");
filterFullList.add("(c) FRM Firmware Download Failed");
filterFullList.add("(c) FRM Starting Firmware Download 6LME2510");
filterFullList.add("(c) From FuncId");
filterFullList.add("(c) FunctionType FnTy");
filterFullList.add("(c) FunctionType FTy");
filterFullList.add("(c) GlobalVariable Handle");
filterFullList.add("(c) group");
filterFullList.add("(c) I Ci Es @ AEuAI");
filterFullList.add("(c) I ISSE\"I\"IaD (c) I");
filterFullList.add("(c) I Write/Read Mangled Y");
filterFullList.add("(c) I\"I (c) I");
filterFullList.add("(c) I\"I (c) ISSI");
filterFullList.add("(c) I\"I\"I (c) I");
filterFullList.add("(c) I\"I\"I\"EaI\"I (c) I");
filterFullList.add("(c) I$?iAT g3eCXMLdT g*e http://www.w3.org/XML");
filterFullList.add("(c) Ia VXefBNgIOADLL EoCh3eAC/eae$?A*BeuA Internet ExploreaWindows Media PlayerIWIT");
filterFullList.add("(c) IaeH, ANH");
filterFullList.add("(c) IaI (c)");
filterFullList.add("(c) IAvP VADLL");
filterFullList.add("(c) IDi (c)");
filterFullList.add("(c) Ie$?R\u007FO (c) R");
filterFullList.add("(c) INT Interrupt Service Started 6LME2510");
filterFullList.add("(c) INT Unable");
filterFullList.add("(c) intermediateCerts.Add");
filterFullList.add("(c) Interrupt Service Stopped");
filterFullList.add("(c) Interrupt Service Stopped 6LME2510");
filterFullList.add("(c) Ioiia (c)");
filterFullList.add("(c) ISALPHA (c) ISDIGIT");
filterFullList.add("(c) isALPHANUMERIC (c) UNDEFINED");
filterFullList.add("(c) IsDigit (c)");
filterFullList.add("(c) isdigit (c) C");
filterFullList.add("(c) ISLETTER (c) DIGIT");
filterFullList.add("(c) IsNetbiosSplChar (c)");
filterFullList.add("(c) ISSE\"ISSI I (c) E");
filterFullList.add("(c) ISSIaI (c)");
filterFullList.add("(c) ISSI|E N (c) I");
filterFullList.add("(c) isSPACE (c) UNDEFINED");
filterFullList.add("(c) isWORDCHAR (c) UNDEFINED");
filterFullList.add("(c) It's OK"); // MARKER
filterFullList.add("(c) I|ESSE|E (c) ESSE");
filterFullList.add("(c) K97I V3m");
filterFullList.add("(c) l (c) L");
filterFullList.add("(c) L'attribut BIND");
filterFullList.add("(c) Last Free"); // MARKER
filterFullList.add("(c) LIMITED"); // MARKER
filterFullList.add("(c) LLVMContextDispose (c)");
filterFullList.add("(c) mc_latency_mclk.full");
filterFullList.add("(c) MEM Error");
filterFullList.add("(c) Metadata Ops MD"); // MARKER
filterFullList.add("(c) MidLetter or MidNumLet");
filterFullList.add("(c) Mnemonic C's"); // MARKER
filterFullList.add("(c) Na o Io io Ks ks Ps");
filterFullList.add("(c) Object o Hello");
filterFullList.add("(c) Offset C- Offset");
filterFullList.add("(c) OkRaR (c)");
filterFullList.add("(c) Old Old");
filterFullList.add("(c) OR'OR'OR (c) O SR");
filterFullList.add("(c) OR'OR'OR (c) OO");
filterFullList.add("(c) OR'OR'OR c'OR co'OR (c) O SR");
filterFullList.add("(c) Outchar OO");
filterFullList.add("(c) oY X2 PAdeg\"ao+-!ap!C! degN|O$?U+-,N !!A\"A1/2DdegN|O!G ??? http://phorum.vb...");
filterFullList.add("(c) oY X2 PAdeg\"ao+-!ap!C! degN|O$?U+-,N !!A\"A1/2DdegN|O!G ??? http://phorum.vb... / property og:url content http://www.wretch.cc/blog/fsj/3269525");
filterFullList.add("(c) p type(b) bv");
filterFullList.add("(c) P2 (B) P3");
filterFullList.add("(c) Page i/o Todo/Under");
filterFullList.add("(c) Pas de branchement Pas d'appel"); // MARKER
filterFullList.add("(c) PointerType InitPtrType InitValue");
filterFullList.add("(c) pragma mangle, clock$UNIX2003");
filterFullList.add("(c) r (c) R");
filterFullList.add("(c) R Value");
filterFullList.add("(c) RaAERR (c)");
filterFullList.add("(c) readpng2$ (c) PROGHDRS");
filterFullList.add("(c) Remove (PROTO) Remove (.PHONY) Remove C and PROTO");
filterFullList.add("(c) Scale 1 Offset");
filterFullList.add("(c) SE0o OS");
filterFullList.add("(c) SelectInst SelI");
filterFullList.add("(c) SmallVector MDs");
filterFullList.add("(c) SmallVector ToErase");
filterFullList.add("(c) SmallVector Types FnPtrTy, FnPtrTy, PromiseType");
filterFullList.add("(c) State UNQUOTED");
filterFullList.add("(c) StringWriter sw HtmlTextWriter");
filterFullList.add("(c) t (c) T");
filterFullList.add("(c) Temp. (F) Summary");
filterFullList.add("(c) Th (c)");
filterFullList.add("(c) TitlecaseLetter E");
filterFullList.add("(c) TUN Found");
filterFullList.add("(c) TUN Found Frontend TDA10086");
filterFullList.add("(c) Type ArgTys Int32Ty, Int32Ty, Int32Ty FunctionType FnTy");
filterFullList.add("(c) Type ArgTys Int32Ty, Int32Ty, Int32Ty Type FnTy");
filterFullList.add("(c) Type AtExitFuncArgs VoidStar FunctionType AtExitFuncTy");
filterFullList.add("(c) Type DoubleTy");
filterFullList.add("(c) Type FloatTy");
filterFullList.add("(c) Type FnTy");
filterFullList.add("(c) Type I1Ty");
filterFullList.add("(c) Type I32PtrTy");
filterFullList.add("(c) Type I32Ty");
filterFullList.add("(c) Type Int16Ty");
filterFullList.add("(c) Type Int32PtrTy");
filterFullList.add("(c) Type Int32Ty");
filterFullList.add("(c) Type Int64PtrTy");
filterFullList.add("(c) Type Int64Ty");
filterFullList.add("(c) Type Int8Ty");
filterFullList.add("(c) Type V8x8Ty");
filterFullList.add("(c) u (c) P");
filterFullList.add("(c) u (c) U");
filterFullList.add("(c) U3269 CIRCLED");
filterFullList.add("(c) Unlock (c)");
filterFullList.add("(c) Value A");
filterFullList.add("(c) Value AllocA");
filterFullList.add("(c) Value Alloca");
filterFullList.add("(c) Value AllocaA");
filterFullList.add("(c) Value Elt0");
filterFullList.add("(c) Value RHS");
filterFullList.add("(c) Value Sd");
filterFullList.add("(c) various MONO");
filterFullList.add("(c) VectorType Int8PtrVecTy");
filterFullList.add("(c) x (c) O");
filterFullList.add("(c) X1 ... X1");
filterFullList.add("(c) Xhadcnt 1 Xcnt");
filterFullList.add("(c) YPe A"); // MARKER
filterFullList.add("(c) Yu C"); // MARKER
filterFullList.add("(c) Yu L"); // MARKER
filterFullList.add("(c) z (c) Z");
filterFullList.add("(c) ZA'-x'E1/2 JU Co");
filterFullList.add("(c) | (c) PSF"); // MARKER
filterFullList.add("(c) | (c) SS"); // MARKER
filterFullList.add("(c), (bv)- bv_len");
filterFullList.add("(c), (bv)- bv_len (dst)- bv_len (dst)- bv_val");
filterFullList.add("(c), (c)");
filterFullList.add("(c), AnsiChar Array");
filterFullList.add("(c), FcCacheDirs (c)");
filterFullList.add("(c), FcCharSetLeaves (c)");
filterFullList.add("AMDGPUMangledLibFunc (c) From");
filterFullList.add("AttrOf (c) ChAttrOf (c)");
filterFullList.add("AttrOf (c), GetPair (c)");
filterFullList.add("BeeYeaaODIUUOxOEdeaodioonooithyua (c) (c)"); // MARKER
filterFullList.add("Bind (c)");
filterFullList.add("BuildProjectForSingleTaskItem '$ (c) CheckItems");
filterFullList.add("BuildProjectForSingleTaskItem '$(D)$ (c) CheckItems");
filterFullList.add("C. copyright D. (c)");
filterFullList.add("CharOf (c) ChCharOf (c)");
filterFullList.add("Chars (c) Chars");
filterFullList.add("Context (c) LineToUnit");
filterFullList.add("Conventions, Example, Copyright, Top");
filterFullList.add("Copr GbE SKU"); // MARKER
filterFullList.add("Copr. Self-extracting PKZIP");
filterFullList.add("CopyrightText Copyright (c)"); // MARKER
filterFullList.add("CreateChangedMethodDecl (c), CreateChangingMethodDecl (c)");
filterFullList.add("Emit (c) First");
filterFullList.add("EventWatcher (c) BindingContext");
filterFullList.add("EventWatcher (c) ContextMenu");
filterFullList.add("EventWatcher (c) ContextMenuStrip");
filterFullList.add("EventWatcher (c) Font");
filterFullList.add("EventWatcher (c) Image");
filterFullList.add("EventWatcher (c) Region");
filterFullList.add("Fix (c)");
filterFullList.add("Fix copyright Make");
filterFullList.add("Foo (c) Bar");
filterFullList.add("Found bind (c)");
filterFullList.add("GetColumnName (c), GetColumnTSqlType (c)");
filterFullList.add("GvQ3O4A (c) W2");
filterFullList.add("H-c copyright H-a");
filterFullList.add("IaeH, ANH (c) IaeH");
filterFullList.add("IAo3eAAAE (c) (c)");
filterFullList.add("IdI WAOd ACfgAC/ (c) IpublicE");
filterFullList.add("Info. xref");
filterFullList.add("InitCache (c) TransferBatch");
filterFullList.add("Interface (c)");
filterFullList.add("IsHighSurrogate (c) IsLowSurrogate (c)");
filterFullList.add("Kind (c) Reference");
filterFullList.add("len (c) Explicit");
filterFullList.add("LxuG (c)");
filterFullList.add("MemTotal (c) Bytes");
filterFullList.add("Name copyright Type");
filterFullList.add("NonPod (c), Inter");
filterFullList.add("O4 (c) WCn");
filterFullList.add("Omitted (c)");
filterFullList.add("OutCopFILE (c) CopFILE (c)");
filterFullList.add("Power (c) State");
filterFullList.add("ReadOnlyCollection (c) Array");
filterFullList.add("Result (c) First");
filterFullList.add("Result (c) Last");
filterFullList.add("rr");
filterFullList.add("Scope (c) Ctyp");
filterFullList.add("Sloc (c) Ix");
filterFullList.add("Specifies Copyright Filename");
filterFullList.add("TextSyndicationContent copyright ExtensibleSyndicationObject");
filterFullList.add("ToolStripControlHost (c) ToolStrip");
filterFullList.add("UnicodeString src (c) UnicodeString");
filterFullList.add("UnicodeString srcStr (c) UnicodeString");
filterFullList.add("UnicodeString str (c) UErrorCode");
filterFullList.add("Unlock (c) Unlock");
filterFullList.add("(c) $? (c) Y");
filterFullList.add("(c) (3) public benefit corporation");
filterFullList.add("(c) (c) (c) (c) (c) (c) (c) (c) (c) A989 A98A");
filterFullList.add("(c) (c) A");
filterFullList.add("(c) (c) and G G G");
filterFullList.add("(c) (c) COMMA");
filterFullList.add("(c) (c) CSTYLED");
filterFullList.add("(c) (c) CTRLC");
filterFullList.add("(c) (c) QUIT");
filterFullList.add("(c) (c) UNDEFINED"); // HINT; REVIEW
filterFullList.add("(c) . (c)");
filterFullList.add("(c) . (R). End");
filterFullList.add("(c) . .It Ar");
filterFullList.add("(c) . A");
filterFullList.add("(c) . C");
filterFullList.add("(c) . C1B");
filterFullList.add("(c) . cipher/blowfish-arm.S Ditto");
filterFullList.add("(c) . D.");
filterFullList.add("(c) . END T2");
filterFullList.add("(c) . Explicitly");
filterFullList.add("(c) . FAILED");
filterFullList.add("(c) . Genera");
filterFullList.add("(c) . I1 CONSTANT");
filterFullList.add("(c) . inline UBool");
filterFullList.add("(c) . Instead group");
filterFullList.add("(c) . intel/eu Fix");
filterFullList.add("(c) . Looping");
filterFullList.add("(c) . LxuGAU");
filterFullList.add("(c) . Op1");
filterFullList.add("(c) . Seemingly");
filterFullList.add("(c) . Set");
filterFullList.add("(c) . Similarly");
filterFullList.add("(c) . TESTS");
filterFullList.add("(c) . Therefore");
filterFullList.add("(c) . Thus");
filterFullList.add("(c) . trans-common.c Forward");
filterFullList.add("(c) . Try");
filterFullList.add("(c) . UnicodeString");
filterFullList.add("(c) . We'll");
filterFullList.add("(c) . xT6,g MxtE99");
filterFullList.add("(c) .all Sections (First).all then Group");
filterFullList.add("(c) 1 a (c) I");
filterFullList.add("(c) 1 e (c) I");
filterFullList.add("(c) \"|C/!23th'yuyPy*y,y1yoy th1/4th1/2y3/4th?yAuAn\u0006A1/2* (c) Y");
filterFullList.add("(c) $', RegexOptions.None, abac', Pass. Group");
filterFullList.add("c) $? (c) Y");
filterFullList.add("(c) $?1/2P u,O / !- http://www.wretch.cc/blog/fsj&article_id");
filterFullList.add("(c) (r)+-u,o 1/4AAEEIIOO\u0013xUUThssaaaceeeiiiiddnnooouoooAoUoynyd@iiiieeecaeaaassThUUxOONIIEEAEAAAAou-a!3+- (c) Y");
filterFullList.add("(c) ,$?o2Y$?1$? <$?E'O$?1$?e3/4UoU$?I!$?EI$?I http://www.w3.org/TR/NOTE-sgml-xml'>");
filterFullList.add("(c) d (c) D");
filterFullList.add("(c) e (c) E");
filterFullList.add("(c) i (c) I");
filterFullList.add("(c) e+-RcEEex$?I$?ReAEAE3/4Rceekcee$?R\u007FO (c) R");
filterFullList.add("(c) U,AE:IF\u0014q BVhF'$");
filterFullList.add("(c) iX3/4\bOiMPSAi-Tss5Edeg (c) NU");
}
public static List filterCopyrightsAndAuthorsList(String copyrights) {
if (!StringUtils.hasText(copyrights)) return new ArrayList<>();
final String[] split = copyrights.split("\\|\\n");
final List copyrightList = new ArrayList<>(Arrays.asList(split));
Collections.sort(copyrightList, String::compareToIgnoreCase);
Set filterPrefixList = new HashSet<>();
filterPrefixList.add("(c) .");
Set filterSuffixList = new HashSet<>();
filterSuffixList.add("pppppp \u0010 .kawasaki.jp");
for (String copyright : new ArrayList<>(copyrightList)) {
if (fullMatch(copyright, filterFullList)) {
removeCopyright(copyright, copyrightList);
continue;
}
if (prefixMatch(copyright, filterPrefixList)) {
removeCopyright(copyright, copyrightList);
continue;
}
if (suffixMatch(copyright, filterSuffixList)) {
removeCopyright(copyright, copyrightList);
continue;
}
// correct selected copyright
if (copyright.equals("GPL. Patrick McHardy (c) 2006-2012")) {
copyrightList.remove(copyright);
copyrightList.add("Patrick McHardy (C) 2006-2012");
}
if (copyright.toLowerCase().contains("$year")) {
copyrightList.remove(copyright);
}
if (copyright.toLowerCase().contains("copyright if $contents")) {
copyrightList.remove(copyright);
}
if (copyright.toLowerCase().contains("$(year)")) {
copyrightList.remove(copyright);
}
if (copyright.toLowerCase().contains("\u0000")) {
copyrightList.remove(copyright);
}
if (copyright.toLowerCase().contains("\u0001")) {
copyrightList.remove(copyright);
}
if (copyright.toLowerCase().contains("\u0002")) {
copyrightList.remove(copyright);
}
if (copyright.toLowerCase().contains("\u0003")) {
copyrightList.remove(copyright);
}
if (copyright.toLowerCase().contains("\u0004")) {
copyrightList.remove(copyright);
}
if (copyright.toLowerCase().contains("\u0005")) {
copyrightList.remove(copyright);
}
if (copyright.startsWith("(c) Returns ")) {
copyrightList.remove(copyright);
}
}
return copyrightList;
}
protected static boolean suffixMatch(String copyright, Set filterSuffixList) {
for (String suffix : filterSuffixList) {
if (copyright.endsWith(suffix)) {
return true;
}
}
return false;
}
protected static boolean prefixMatch(String copyright, Set filterPrefixList) {
for (String prefix : filterPrefixList) {
if (copyright.endsWith(prefix)) {
return true;
}
}
return false;
}
protected static boolean fullMatch(String copyright, Set filterFullList) {
for (String candidate : filterFullList) {
if (copyright.equals(candidate)) {
return true;
}
}
return false;
}
protected static void removeCopyright(String copyright, List copyrightList) {
copyrightList.remove(copyright);
LOG.debug("Removed copyright: [{}] found in {}.", copyright, copyrightList);
}
private static String escape(String s) {
return StringEscapeUtils.escapeXml(s.trim());
}
@Deprecated // renew implementation
public static void diffScanCodeResults(Inventory inventory) {
for (Artifact a : inventory.getArtifacts()) {
String derivedLicense = a.get(KEY_DERIVED_LICENSES);
String derivedLicenseScanCode = StringUtils.stripArrayBoundaries(a.get(KEY_DERIVED_LICENSES_SCANCODE));
Set remainingScanCodeLicenses = diffLicensesWithScanCodeLicenses(derivedLicense, derivedLicenseScanCode);
String sourceDerivedLicenses = a.get(KEY_SOURCE_ARTIFACT_DERIVED_LICENSES);
String sourceDerivedLicenses_ScanCode = StringUtils.stripArrayBoundaries(a.get(KEY_SOURCE_ARTIFACT_DERIVED_LICENSES_SCANCODE));
Set remainingScanCodeLicenses_Source = diffLicensesWithScanCodeLicenses(sourceDerivedLicenses, sourceDerivedLicenses_ScanCode);
StringBuilder sb = new StringBuilder();
if (!remainingScanCodeLicenses.isEmpty()) {
sb.append("bin: ");
sb.append(remainingScanCodeLicenses);
}
if (!remainingScanCodeLicenses_Source.isEmpty()) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append("src: ");
sb.append(remainingScanCodeLicenses);
}
a.set("Diff - Derived License / Scancode", sb.toString());
}
}
protected static Set diffLicensesWithScanCodeLicenses(String derivedLicense, String derivedLicenseScanCode) {
List licenseList = tokenizeLicense(derivedLicense, false, false);
List termsList = NORMALIZATION_META_DATA.convert(licenseList);
List scanCodeLicenseList = tokenizeLicense(derivedLicenseScanCode, false, false);
Set coveredScanCodeIds = new HashSet<>();
for (TermsMetaData termsMetaData : termsList) {
List scanCodeIds = termsMetaData.getScanCodeIdentifiers();
coveredScanCodeIds.addAll(scanCodeIds);
}
Set remainingScanCodeLicenses = new HashSet<>(scanCodeLicenseList);
remainingScanCodeLicenses.removeAll(coveredScanCodeIds);
return remainingScanCodeLicenses;
}
public static void insertLicenseDataForCanonicalNames(Collection canonicalNames, Inventory projectInventory) {
for (final String canonicalName : canonicalNames) {
final LicenseData matchedLd = projectInventory.findMatchingLicenseData(canonicalName);
// check whether already inserted
if (matchedLd == null) {
final TermsMetaData termsMetaData = NORMALIZATION_META_DATA.getTermsMetaData(canonicalName);
if (termsMetaData != null) {
final LicenseData ld = new LicenseData();
transferTmdAttributesToLicenseData(ld, termsMetaData);
projectInventory.getLicenseData().add(ld);
} else {
// no validation is performed here; we just report on debug level here; validation happens elsewhere
LOG.debug("No explicit license metadata for [{}].", canonicalName);
// resolve via alternative name (assuming canonicalNameHistory is already considered)
final TermsMetaData alternativeTermsMetaData = NORMALIZATION_META_DATA.findTermsMetaData(canonicalName);
if (alternativeTermsMetaData != null) {
final String alternativeCanonicalName = alternativeTermsMetaData.getCanonicalName();
// only add in case the license is not yet covered
final LicenseData alternativeLicensData = projectInventory.findMatchingLicenseData(alternativeCanonicalName);
if (alternativeLicensData == null) {
LicenseData ld = new LicenseData();
transferTmdAttributesToLicenseData(ld, alternativeTermsMetaData);
projectInventory.getLicenseData().add(ld);
} else {
// real duplicate (since we use the original canonicalName)
}
} else {
if (canonicalName.contains(" + ")) {
// FIXME: shall we decompose the expression? Is this already done?
// do not include license expressions
} else {
LicenseData ld = new LicenseData();
ld.set(LicenseData.Attribute.CANONICAL_NAME, canonicalName);
projectInventory.getLicenseData().add(ld);
ld.set("Unknown License Type", "x");
// derive information from name
if (canonicalName.toLowerCase().contains("commercial")) {
ld.set(LicenseData.Attribute.COMMERCIAL, "x");
}
}
}
}
} else {
// already included; real duplicate
}
}
}
public static void transferTmdAttributesToLicenseData(LicenseData ld, TermsMetaData termsMetaData) {
ld.set(LicenseData.Attribute.CANONICAL_NAME, termsMetaData.getCanonicalName());
ld.set(LicenseData.Attribute.ID, termsMetaData.deriveId());
ld.set(LicenseData.Attribute.SPDX_ID, termsMetaData.getSpdxIdentifier());
ld.set(LicenseData.Attribute.REPRESENTED_AS, termsMetaData.getRepresentedAs());
final List scanCodeIds = termsMetaData.getScanCodeIdentifiers();
if (scanCodeIds != null) {
ld.set("ScanCode Ids", scanCodeIds.stream().sorted().collect(Collectors.joining(", ")));
}
// insert/manage OSI status
ld.set("OSI Status", termsMetaData.getOsiStatus());
// insert/manage Open CoDE status
ld.set("Open CoDE Status", termsMetaData.getOpenCoDEStatus());
ld.set("Open CoDE Similar License", termsMetaData.getOpenCoDESimilarLicenseId());
boolean openCodeAssessmentPending = true;
if (StringUtils.hasText(termsMetaData.getOpenCoDEStatus())) openCodeAssessmentPending = false;
if (termsMetaData.isException()) openCodeAssessmentPending = false;
if (termsMetaData.isUnspecific()) openCodeAssessmentPending = false;
if (termsMetaData.isMarker()) openCodeAssessmentPending = false;
if (termsMetaData.isExpression()) openCodeAssessmentPending = false;
if (termsMetaData.allowLaterVersions()) openCodeAssessmentPending = false;
// TODO: condition incomplete
if (StringUtils.hasText(termsMetaData.getRepresentedAs()) &&
StringUtils.isEmpty(termsMetaData.getSpdxIdentifier()) &&
(termsMetaData.getOtherIds() == null || termsMetaData.getOtherIds().isEmpty()))
openCodeAssessmentPending = false;
// mark set to indicate that an assessment from open code is not yet available
if (openCodeAssessmentPending) {
ld.set("Open CoDE Assessment Pending", "x");
} else {
ld.set("Open CoDE Assessment Pending", null);
}
// FIXME: improve; organize questions in TMD
final String licenseClassification = termsMetaData.getClassification();
if (licenseClassification != null) {
final String licenseClassificationLowerCase = licenseClassification.toLowerCase();
ld.set("C-" + licenseClassificationLowerCase, "x");
}
String type = termsMetaData.getType();
if (StringUtils.isEmpty(type)) type = "terms";
ld.set("Type", type);
if ("terms".equalsIgnoreCase(type)) {
final List matchedMarkers = termsMetaData.getMatchedMarkers();
if (matchedMarkers != null) {
for (String marker : matchedMarkers) {
TermsMetaData tmd = getNormalizationMetaData().resolveTermsMetaData(marker);
ld.set("M-" + tmd.getShortName(), "x");
}
}
}
}
public static void applyDerivedLicenses(Inventory projectInventory) {
for (Artifact artifact : projectInventory.getArtifacts()) {
if (!StringUtils.hasText(artifact.getLicense())) {
final String derivedLicense = artifact.get(KEY_DERIVED_LICENSES);
if (StringUtils.hasText(derivedLicense)) {
artifact.setLicense(derivedLicense);
}
}
}
}
// FIXME: consider moving to Artifact utils.
/**
* Currently LicenseMetaData can only be associated to an artifact if license, version and component are defined.
* This method evaluates the pre-requisites.
*
* @param artifact The artifacts to evaluate.
* @return Returns true
in case LicenseMetaData can be stored with the artifact.
*/
public static boolean canCarryLicenseMetaData(Artifact artifact) {
return StringUtils.notEmpty(artifact.getLicense()) &&
StringUtils.notEmpty(artifact.getVersion()) &&
StringUtils.notEmpty(artifact.getComponent());
}
public static void addToInventory(Inventory sourceInventory, Inventory targetInventory, boolean processAssets) {
InventorySearch inventorySearch = new InventorySearch(targetInventory);
addToInventory(sourceInventory.getArtifacts(), inventorySearch);
// FIXME: yet naive implementation; may produce duplicates
if (processAssets) {
targetInventory.getAssetMetaData().addAll(sourceInventory.getAssetMetaData());
InventoryUtils.mergeDuplicateAssets(targetInventory);
}
}
public static void addToInventory(Collection artifacts, InventorySearch inventorySearch) {
for (Artifact artifact : artifacts) {
final Artifact referenceArtifact;
if (!StringUtils.isEmpty(artifact.getChecksum())) {
referenceArtifact = inventorySearch.findArtifactByIdAndChecksum(artifact);
} else {
referenceArtifact = inventorySearch.findArtifactById(artifact);
}
if (referenceArtifact != null) {
// at the moment we do nothing; we may want to validate attributes and add projects.
// FIXME: compare columns; check for deviations; eg. architecture; think of a policy
// FIXME: fix merge method in core; inserts null string
final String value = artifact.get(Artifact.Attribute.PROJECTS);
if (!StringUtils.isEmpty(value)) {
referenceArtifact.append(Artifact.Attribute.PROJECTS.getKey(), value, Artifact.PROJECT_DELIMITER);
}
// merge / don't overwrite for other attributes
for (String attribute : artifact.getAttributes()) {
if (attribute.equals(Artifact.Attribute.PROJECTS.getKey())) continue;
if (referenceArtifact.get(attribute) == null) {
referenceArtifact.set(attribute, artifact.get(attribute));
}
}
} else {
// the artifact is not contained in the aggregated inventory yet; we add it
inventorySearch.add(artifact);
}
}
}
public static void deriveComponentNamesAndVersions(Inventory filteredInventory) {
for (Artifact a : filteredInventory.getArtifacts()) {
if (StringUtils.isEmpty(a.getComponent())) {
if (StringUtils.notEmpty(a.getId())) {
// use artifact id as component name
if (StringUtils.notEmpty(a.getVersion())) {
a.deriveArtifactId();
a.setComponent(a.getArtifactId());
}
// otherwise try to extract from id
if (StringUtils.isEmpty(a.getComponent())) {
String componentName = a.getId();
final int dashIndex = componentName.lastIndexOf("-");
if (dashIndex > 0) {
componentName = componentName.substring(0, dashIndex);
} else {
final int dotIndex = componentName.lastIndexOf(".");
if (dotIndex > 0) {
componentName = componentName.substring(0, dotIndex);
}
}
a.setComponent(componentName);
}
}
}
String proposedVersion = a.get(Constants.KEY_DESCRIPTOR_DERIVED_VERSION);
if (StringUtils.isEmpty(a.getVersion()) && StringUtils.notEmpty(proposedVersion)) {
a.setVersion(proposedVersion);
}
String proposedGroupId = a.get(Constants.KEY_DESCRIPTOR_DERIVED_GROUPID);
if (StringUtils.isEmpty(a.getGroupId()) && StringUtils.notEmpty(proposedGroupId)) {
a.setGroupId(proposedGroupId);
}
}
}
public static void inheritInformationFromReferenceInventory(Inventory inventory, InventorySearch referenceInventory) {
// NOTE: inherit...
// - requires a version (also unspecific can be supported)
// - id must either identical or must include the version
// - the longest match is the best choice (considering major.minor.patch is part of the version string)
// - currently the implementation does not evaluate the closest version but the longest string match
for (Artifact artifact : inventory.getArtifacts()) {
final String id = artifact.getId();
final String version = artifact.getVersion();
if (id == null || version == null) continue;
int index = id.indexOf(version);
final String prefix = index != -1 ? id.substring(0, index) : id;
final String suffix = index != -1 ? id.substring(index + version.length()) : "";
int count = -1;
// check whether we have an exact match (optimized)
Artifact bestMatch = referenceInventory.findArtifactByIdAndChecksum(artifact);
// fallback to wildcard matching (optimized)
if (bestMatch == null) {
bestMatch = referenceInventory.findArtifactWildcardMatchingId(artifact);
}
// check for similar versions (non-optimized)
if (bestMatch == null) {
for (Artifact a : referenceInventory.getArtifacts()) {
final String aId = a.getId();
final String aVersion = a.getVersion();
if (aId == null || a.getVersion() == null) continue;
int aIndex = aId.indexOf(a.getVersion());
final String aPrefix = aIndex != -1 ? aId.substring(0, aIndex) : id;
final String aSuffix = aIndex != -1 ? aId.substring(aIndex + aVersion.length()) : "";
if (prefix.equals(aPrefix) && suffix.equals(aSuffix)) {
// break, when the version is an exact match (should have found this eralier)
if (aVersion.equals(version)) {
bestMatch = a;
break;
}
// count common characters from left to right
for (int i = 0; i < Math.min(version.length(), aVersion.length()); i++) {
if (version.charAt(i) == aVersion.charAt(i)) {
if (count < i) {
count = i;
bestMatch = a;
}
} else {
break;
}
}
}
}
}
if (bestMatch != null) {
final String qualifier = artifact.getId() + "/" + artifact.getChecksum() + "/" + artifact.getVersion() + "/" + artifact.getGroupId();
final String bestMatchQualifier = bestMatch.getId() + "/" + bestMatch.getChecksum() + "/" + bestMatch.getVersion() + "/" + bestMatch.getGroupId();
if (!qualifier.equals(bestMatchQualifier)) {
artifact.set("Inherited Component", bestMatch.getComponent());
artifact.set("Inherited Version", bestMatch.getVersion());
artifact.set("Inherited GroupId", bestMatch.getGroupId());
artifact.set("Inherited License", bestMatch.getLicense());
artifact.set("Inherited Notice Parameter", bestMatch.get("Notice Parameter"));
artifact.set("Inherited Analysis", bestMatch.get("Analysis"));
artifact.set("Inherited Protocol of Research", bestMatch.get("Protocol of Research"));
} else {
// removal temp. disabled; removed "curated-inherited"
if (false) {
LOG.info(id + " does not inherit from any artifact.");
artifact.set("Inherited Component", null);
artifact.set("Inherited Version", null);
artifact.set("Inherited GroupId", null);
artifact.set("Inherited License", null);
artifact.set("Inherited Notice Parameter", null);
artifact.set("Inherited Analysis", null);
artifact.set("Inherited Protocol of Research", null);
}
}
}
}
}
public static void filterExceptionsFromLicenses(Inventory inventory) {
for (Artifact artifact : inventory.getArtifacts()) {
final List licenses = artifact.getLicenses();
for (String license : new ArrayList<>(licenses)) {
final TermsMetaData termsMetaData = getNormalizationMetaData().getTermsMetaData(license);
if (termsMetaData != null) {
if (termsMetaData.isException()) {
licenses.remove( license);
}
}
}
artifact.setLicense(joinLicenses(licenses));
}
}
public static void orderLicenses(Inventory inventory) {
for (Artifact artifact : inventory.getArtifacts()) {
final List licenses = tokenizeLicense(artifact.getLicense(), true, true);
final List newLicenses = new ArrayList<>();
for (String license : licenses) {
if (license.contains(" + ")) {
List orLicenses = tokenizeLicense(license, true, false);
newLicenses.add(joinOredLicenses(orLicenses));
} else {
newLicenses.add(license);
}
}
Collections.sort(newLicenses, String.CASE_INSENSITIVE_ORDER);
artifact.setLicense(joinLicenses(newLicenses));
}
}
public static void renameArtifactAttributes(Inventory inventory, String oldAttributeKey, String newAttributeKey) {
renameArtifactAttributes(inventory, oldAttributeKey, newAttributeKey, false);
}
public static void renameArtifactAttributes(Inventory inventory, String oldAttributeKey, String newAttributeKey, boolean allowOverwrites) {
for (Artifact artifact : inventory.getArtifacts()) {
String oldValue = artifact.get(oldAttributeKey);
String newValue = artifact.get(newAttributeKey);
// normalize to null
if (StringUtils.isEmpty(oldValue)) oldValue = null;
if (StringUtils.isEmpty(newValue)) newValue = null;
if (Objects.equals(oldValue, newValue)) {
// already the same value; remove old attribute key
artifact.set(oldAttributeKey, null);
} else if (newValue != null && oldValue != null) {
// new value is already set and different from the value in the old column
if (!allowOverwrites) {
final String message = String.format("Cannot rename [%s] attribute %s to %s. " +
"New attribute already exists and contains different values: old [%s] vs new [%s]",
artifact.getId(), oldAttributeKey, newAttributeKey, oldValue, newValue);
LOG.error(message);
// throw new IllegalStateException(message);
} else {
artifact.set(newAttributeKey, oldValue);
artifact.set(oldAttributeKey, null);
}
} else if (newValue == null) {
// newValue is null; replace
artifact.set(newAttributeKey, oldValue);
artifact.set(oldAttributeKey, null);
} else {
// oldValue is null; do nothing
}
}
// manage serialization context
final InventorySerializationContext serializationContext = inventory.getSerializationContext();
final ArrayList list = serializationContext.get(InventorySerializationContext.CONTEXT_ARTIFACT_COLUMN_LIST);
// manage serialization context only if available
if (list != null) {
int index = list.indexOf(oldAttributeKey);
int indexNew = list.indexOf(newAttributeKey);
// in case the new key already exists, it remains its position.
if (indexNew == -1) {
if (index != -1) {
// replace current position with new attribute key
list.set(index, newAttributeKey);
} else {
// rename does not add any new items
}
}
while (list.contains(oldAttributeKey)) {
list.remove(oldAttributeKey);
}
}
}
public static void removeArtifactInheritedAttributes(Inventory inventory) {
removeArtifactAttributeStartingWith(inventory, "Inherited ");
}
final static HashSet INTERNAL_COLUMNS = new HashSet<>();
static {
INTERNAL_COLUMNS.add("Analysis");
INTERNAL_COLUMNS.add("Projects");
INTERNAL_COLUMNS.add("Protocol of Research");
INTERNAL_COLUMNS.add("Source Project");
INTERNAL_COLUMNS.add("Source Inventory");
INTERNAL_COLUMNS.add("Inventory Source");
INTERNAL_COLUMNS.add("Src/Bin Derived Licenses Diff");
INTERNAL_COLUMNS.add("Task");
INTERNAL_COLUMNS.add("Tasks");
INTERNAL_COLUMNS.add("Validation Mode");
INTERNAL_COLUMNS.add("License Text");
INTERNAL_COLUMNS.add("MANIFEST.MF/JAR (Bundled License Information)");
INTERNAL_COLUMNS.add("Notice.txt");
INTERNAL_COLUMNS.add("Review Remark");
// classification may change
INTERNAL_COLUMNS.add("Notice Parameter");
// relevant only for internal resolving
INTERNAL_COLUMNS.add("Derived ArtifactId (POM)");
INTERNAL_COLUMNS.add("Derived Component (POM)");
INTERNAL_COLUMNS.add("Derived GroupId (POM)");
INTERNAL_COLUMNS.add("Derived Version (POM)");
// redundant
INTERNAL_COLUMNS.add("Filtered Terms");
INTERNAL_COLUMNS.add("Identified Terms");
// issue may contain free text information and expose information that is not desired
// INTERNAL_COLUMNS.add("Issue");
INTERNAL_COLUMNS.add("Comment");
INTERNAL_COLUMNS.add("Copyright Notice");
INTERNAL_COLUMNS.add("Header Text Copy");
INTERNAL_COLUMNS.add("Ignored Terms");
INTERNAL_COLUMNS.add("Latest Version");
// added 10.05.2023:
INTERNAL_COLUMNS.add("Content Checksum (MD5)");
INTERNAL_COLUMNS.add("Content MD5");
INTERNAL_COLUMNS.add("Archive Path");
// NOTE: the markers are report relevant and must not be excluded.
// INTERNAL_COLUMNS.add("Derived Markers");
// INTERNAL_COLUMNS.add("POM - Derived Markers");
// INTERNAL_COLUMNS.add("Source - Derived Licenses");
// INTERNAL_COLUMNS.add("Source - Derived Markers");
// INTERNAL_COLUMNS.add("Source - Archive Path");
INTERNAL_COLUMNS.add("Derived Notice Parameter");
INTERNAL_COLUMNS.add("Diff - Derived License / Scancode");
INTERNAL_COLUMNS.add(KEY_EXTRACTED_COPYRIGHTS_SCANCODE);
INTERNAL_COLUMNS.add(KEY_EXTRACTED_AUTHORS_SCANCODE);
INTERNAL_COLUMNS.add("License / Derived Src/Bin License Diff");
INTERNAL_COLUMNS.add("License Expressions (ScanCode)");
INTERNAL_COLUMNS.add("POM - Derived ArtifactId (POM)");
INTERNAL_COLUMNS.add("POM - Derived Component (POM)");
INTERNAL_COLUMNS.add("POM - Derived GroupId (POM)");
INTERNAL_COLUMNS.add("POM - Derived Licenses (POM)");
INTERNAL_COLUMNS.add("POM - Derived Licenses (ScanCode)");
INTERNAL_COLUMNS.add("POM - Derived POM Licenses");
INTERNAL_COLUMNS.add("POM - Derived Version (POM)");
INTERNAL_COLUMNS.add("POM - Extracted Authors (ScanCode)");
INTERNAL_COLUMNS.add("POM - Extracted Copyrights (ScanCode)");
INTERNAL_COLUMNS.add("POM - Identified Terms");
INTERNAL_COLUMNS.add("Source - Derived ArtifactId (POM)");
INTERNAL_COLUMNS.add("Source - Derived Component (POM)");
INTERNAL_COLUMNS.add("Source - Derived GroupId (POM)");
INTERNAL_COLUMNS.add("Source - Derived License (POM)");
INTERNAL_COLUMNS.add("Source - Derived Licenses (POM)");
INTERNAL_COLUMNS.add("Source - Derived Licenses (ScanCode)");
INTERNAL_COLUMNS.add("Source - Derived Version (POM)");
INTERNAL_COLUMNS.add("Source - Extracted Authors (ScanCode)");
INTERNAL_COLUMNS.add("Source - Extracted Copyrights (ScanCode)");
INTERNAL_COLUMNS.add("Source - Filtered Terms");
INTERNAL_COLUMNS.add("Source - Identified Terms");
INTERNAL_COLUMNS.add("Source - Ignored Terms");
}
public static void removeArtifactInternalAttributes(Inventory inventory) {
removeAttributes(inventory, INTERNAL_COLUMNS);
}
public static String createStringRepresentation(Artifact artifact) {
final String id = artifact.getId();
final String groupId = artifact.getGroupId();
final String version = artifact.getVersion();
String s = "";
s = id != null ? s + "/" + id : s + "/";
s = groupId != null ? s + "/" + groupId : s + "/";
s = version != null ? s + "/" + version : s + "/";
return s;
}
public static String createStringRepresentation(AssetMetaData assetMetaData) {
final String assetId = assetMetaData.get(AssetMetaData.Attribute.ASSET_ID);
String s = "";
s = assetId != null ? s + "/" + assetId : s + "/";
return s;
}
public static String createStringRepresentation(LicenseData licenseData) {
final String assetId = licenseData.get(LicenseData.Attribute.CANONICAL_NAME);
String s = "";
s = assetId != null ? s + "/" + assetId : s + "/";
return s;
}
public static void removeLicenseDataAttributeContaining(String substring, Inventory inventory) {
for (LicenseData licenseData : inventory.getLicenseData()) {
for (String key : new HashSet<>(licenseData.getAttributes())) {
if (key.contains(substring)) {
licenseData.set(key, null);
}
}
}
}
public static void removeAssetAttribute(String key, Inventory inventory) {
for (AssetMetaData assetMetaData : inventory.getAssetMetaData()) {
assetMetaData.set(key, null);
}
}
/**
* Removes all assets from an inventory, as well as their artifact attributes, if for example CONTAINS or DESCRIBES
* relationships are tracked.
* @param inventory the inventory
*/
public static void removeAssetsAndReferences(Inventory inventory) {
for (AssetMetaData asset : inventory.getAssetMetaData()) {
String assetId = asset.get(AssetMetaData.Attribute.ASSET_ID);
for (Artifact artifact : inventory.getArtifacts()) {
if (StringUtils.notEmpty(artifact.get(asset.get(AssetMetaData.Attribute.ASSET_ID)))) {
artifact.set(assetId, null);
}
}
}
inventory.setAssetMetaData(Collections.emptyList());
}
public static void mergeDuplicateAssets(Inventory mergedInventory) {
final Map> qualiferAssetMap = new HashMap<>();
for (AssetMetaData assetMetaData : mergedInventory.getAssetMetaData()) {
qualiferAssetMap.computeIfAbsent(assetMetaData.deriveQualifier(),
c -> new LinkedHashSet<>()).add(assetMetaData);
}
final Set toBeDeleted = new HashSet<>();
for (HashSet assetMetaDataSet : qualiferAssetMap.values()) {
// first item is the reference
final Iterator assetMetaDataIterator = assetMetaDataSet.iterator();
final AssetMetaData referenceAsset = assetMetaDataIterator.next();
while (assetMetaDataIterator.hasNext()) {
final AssetMetaData duplicate = assetMetaDataIterator.next();
toBeDeleted.add(duplicate);
// FIXME: expose a merge signature on artifact level
for (final String key : duplicate.getAttributes()) {
final String value = referenceAsset.get(key);
if (!StringUtils.hasText(value)) {
referenceAsset.set(key, duplicate.get(key));
}
}
}
}
toBeDeleted.forEach(mergedInventory.getAssetMetaData()::remove);
}
public static void addContentChecksum(Inventory referenceInventory) throws IOException {
final File tmpDir = new File(System.getProperty("java.io.tmpdir"), "ae-content-checksum");
for (Artifact artifact : referenceInventory.getArtifacts()) {
if (StringUtils.isEmpty(artifact.get("Content MD5"))) {
final String analysisPath = artifact.get("Analysis Path");
if (StringUtils.notEmpty(analysisPath)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Processing content checksum for " + artifact.deriveQualifier());
}
final File artifactAnalysisPath = new File(analysisPath);
if (artifactAnalysisPath.exists()) {
final String contentChecksum = FileUtils.computeContentChecksum(artifactAnalysisPath, tmpDir);
artifact.set("Content MD5", contentChecksum);
} else {
LOG.warn("Expected content in path " + artifactAnalysisPath + ". Cannot compute content checksum.");
}
}
}
}
}
public static void inheritInformationFromReferenceInventory(Inventory inventory, Inventory referenceInventory) {
for (Artifact artifact : inventory.getArtifacts()) {
final String id = artifact.getId();
for (Artifact a : referenceInventory.getArtifacts()) {
final String aId = a.getId();
if (aId == null) continue;
if (a.getVersion() == null) continue;
int index = aId.indexOf(a.getVersion());
if (index > 0) {
String prefix = aId.substring(0, index);
String suffix = aId.substring(index + a.getVersion().length());
if (id.startsWith(prefix) && id.endsWith(suffix)) {
final int startIndex = prefix.length();
final int endIndex = id.length() - suffix.length();
if (a != artifact) {
// these parts are not inherited from self
if (StringUtils.isEmpty(artifact.getComponent())) {
artifact.setComponent(a.getComponent());
}
if (StringUtils.isEmpty(artifact.getVersion())) {
if (startIndex < endIndex) {
artifact.setVersion(id.substring(startIndex, endIndex));
}
}
if (StringUtils.isEmpty(artifact.getGroupId())) {
artifact.setGroupId(a.getGroupId());
}
if (StringUtils.isEmpty(a.get("Public"))) {
artifact.set("Public", a.get("Public"));
}
if (!a.createCompareStringRepresentation().equals(artifact.createCompareStringRepresentation())) {
if (StringUtils.notEmpty(a.getLicense())) {
artifact.set("Inherited License", a.getLicense());
LOG.debug("Inherited license from {} to {}.", a.deriveQualifier(), artifact.deriveQualifier());
}
if (StringUtils.notEmpty(a.get("Notice Parameter"))) {
artifact.set("Inherited Notice Parameter", a.get("Notice Parameter"));
LOG.debug("Inherited notice parameter from {} to {}.", a.deriveQualifier(), artifact.deriveQualifier());
}
if (StringUtils.notEmpty(a.get("Analysis"))) {
artifact.set("Inherited Analysis", a.get("Analysis"));
LOG.debug("Inherited analysis from {} to {}.", a.deriveQualifier(), artifact.deriveQualifier());
}
if (StringUtils.notEmpty(a.get("Protocol of Research"))) {
artifact.set("Inherited Protocol of Research", a.get("Protocol of Research"));
LOG.debug("Inherited protocol of research from {} to {}.", a.deriveQualifier(), artifact.deriveQualifier());
}
}
}
// include legacy columns; remove once inventories have been consolidated
if (StringUtils.notEmpty(a.get("Protocol of Research - OLD"))) {
artifact.set("Inherited Protocol of Research", a.get("Protocol of Research - OLD"));
LOG.debug("Inherited protocol of research from {} to {}.", a.deriveQualifier(), artifact.deriveQualifier());
}
if (StringUtils.notEmpty(a.get("Risk Log - Aufgaben zur Klärung"))) {
artifact.set("Inherited Protocol of Research", a.get("Risk Log - Aufgaben zur Klärung"));
LOG.debug("Inherited protocol of research from {} to {}.", a.deriveQualifier(), artifact.deriveQualifier());
}
if (StringUtils.notEmpty(a.get("Protokoll"))) {
artifact.set("Inherited Protocol of Research", a.get("Protokoll"));
LOG.debug("Inherited protocol of research from {} to {}.", a.deriveQualifier(), artifact.deriveQualifier());
}
}
}
}
}
for (Artifact artifact : inventory.getArtifacts()) {
if (StringUtils.isEmpty(artifact.getVersion()) && StringUtils.notEmpty(artifact.getId())) {
String artifactId = artifact.getId();
if (artifactId.contains("_")) {
artifact.setArtifactId(artifactId.substring(0, artifactId.lastIndexOf("_")));
artifact.setVersion(artifactId.substring(artifactId.lastIndexOf("_") + 1, artifactId.length() - 4));
}
}
}
}
/**
* Effectively removes empty columns in the inventory.
*
* @param inventory Inventory to remove empty attributes from
*/
public static void removeEmptyAttributes(Inventory inventory) {
final Set attributes = collectArtifactAttributes(inventory);
for (String attribute : new ArrayList<>(attributes)) {
final Optional first = inventory.getArtifacts().stream()
.map(a -> a.get(attribute))
.filter(StringUtils::hasText)
.findFirst();
if (!first.isPresent()) {
InventoryUtils.removeArtifactAttribute(attribute, inventory);
attributes.remove(attribute);
}
}
}
/**
* Matches artifacts from sourceInventoryResource with artifacts in the referenceInventoryResource. Only uses
* equivalent matches.
*
* @param sourceInventoryResource The source {@link InventoryResource}.
* @param referenceInventoryResource The reference {@link InventoryResource}.
* @param includeIdMatches Boolean indicating whether to include matches only on id level.
*/
public static void mergeReferenceArtifactAttributes(InventoryResource sourceInventoryResource,
InventoryResource referenceInventoryResource, boolean includeIdMatches) {
final Inventory referenceInventory = referenceInventoryResource.getInventory();
for (final Artifact artifact : sourceInventoryResource.getInventory().getArtifacts()) {
final Artifact referenceArtifact = matchIdentifiedArtifact(artifact, referenceInventory, includeIdMatches);
if (referenceArtifact != null) {
System.out.println("Merging artifact: " + artifact.getId());
artifact.merge(referenceArtifact);
}
}
}
public static Artifact matchIdentifiedArtifact(final Artifact artifact, final Inventory referenceInventory, boolean includeIdMatches) {
// find by id/checksum
Artifact referenceMatch = referenceInventory.findArtifactByIdAndChecksum(artifact.getId(), artifact.getChecksum());
// FIXME: better find by PURL; requires PURLs in reference inventory
if (referenceMatch == null && StringUtils.hasText(artifact.getGroupId())) {
artifact.deriveArtifactId();
if (StringUtils.hasText(artifact.getArtifactId())) {
referenceMatch = referenceInventory.findArtifact(artifact.getGroupId(), artifact.getArtifactId());
}
}
// find by id only (first match); this anticipates that
if (referenceMatch == null && includeIdMatches) {
final List allWithId = referenceInventory.findAllWithId(artifact.getId());
if (allWithId.size() != 0) {
referenceMatch = allWithId.get(0);
if (allWithId.size() > 1) {
LOG.warn("Multiple artifacts in reference inventory matching id-only: [{}]. Picking first match.", artifact.getId());
}
}
}
return referenceMatch;
}
}