com.metaeffekt.artifact.analysis.metascan.MergedScanResult Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2021-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.metaeffekt.artifact.analysis.metascan;
import com.metaeffekt.artifact.analysis.utils.FileUtils;
import com.metaeffekt.artifact.analysis.utils.StringUtils;
import com.metaeffekt.artifact.terms.model.MergedSegmentResult;
import com.metaeffekt.artifact.terms.model.Variables;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class MergedScanResult {
private static final Logger LOG = LoggerFactory.getLogger(MergedScanResult.class);
private List mergedScanResult = new ArrayList<>();
public void setMergedScanResult(List mergedScanResult) {
this.mergedScanResult = mergedScanResult;
}
public List getMergedScanResult() {
return mergedScanResult;
}
public void mergeResults(Artifact artifact, File sourceDir) throws IOException {
if (sourceDir == null) return;
final File analysisDir = sourceDir.getParentFile();
final String sourceFolderName = sourceDir.getName();
// input
final File targetFolder = new File(analysisDir, sourceFolderName + "-analysis");
final File metaScanResultJson = FileUtils.findSingleFile(targetFolder, "*_metascan.json");
final File scancodeResultJson = FileUtils.findSingleFile(targetFolder, "*_scancode.json");
// validate all input folders available
FileUtils.validateExists(analysisDir);
if (metaScanResultJson == null || scancodeResultJson == null) {
LOG.debug("No scan result found for artifact {}.", artifact.deriveQualifier());
artifact.append("Errors", "Missing scan result", "|\n");
return;
}
JSONArray segments;
try {
segments = new JSONObject(FileUtils.readFileToString(scancodeResultJson, StandardCharsets.UTF_8)).optJSONArray("files");
} catch (JSONException e) {
LOG.error("Cannot parse json file: " + scancodeResultJson.getAbsolutePath());
throw new IllegalStateException(e.getMessage(), e);
}
// FIXME-KKL: when we have high-level artifacts, the number of segments may enormous. I expect that generating
// a notice parameter for an asset with 1000 segments is not beneficial. For the moment we log the size
LOG.debug("Number of segments used for deriving notice parameter: [{}]", segments.length());
JSONArray result;
try {
result = new JSONArray(FileUtils.readFileToString(metaScanResultJson, StandardCharsets.UTF_8));
} catch (JSONException e) {
LOG.error("Cannot parse json file: " + metaScanResultJson.getAbsolutePath());
throw new IllegalStateException(e.getMessage(), e);
}
for (int i = 0; i < result.length(); i++) {
final JSONObject file = result.optJSONObject(i);
JSONObject segmentsMetascan = file.optJSONObject("segments");
final int segmentCount = file.optInt("segmentCount");
for (int j = 0; j < segmentCount; j++) {
final String segmentName = "segment-" + j;
final JSONObject segmentMetascan = segmentsMetascan.optJSONObject(segmentName);
final String filePath = file.optString("file");
final String scancodePath = sourceFolderName + "-intermediate/" + filePath + "/" + segmentName + ".txt";
final JSONObject segmentScancode = getSegmentFromScancode(segments, scancodePath);
MergedSegmentResult mergedSegmentResult = new MergedSegmentResult();
boolean add = false;
if (segmentMetascan != null) {
mergedSegmentResult.setResolvedLicenses(extractFromMetascanResult(segmentMetascan.optJSONArray("resolvedLicenses")));
mergedSegmentResult.setNameMatches(extractFromMetascanResult(segmentMetascan.optJSONArray("nameMatches")));
mergedSegmentResult.setTextMatches(extractFromMetascanResult(segmentMetascan.optJSONArray("textMatches")));
mergedSegmentResult.setVariables(extractVariables(segmentMetascan.optJSONArray("variables")));
add = true;
}
if (segmentScancode != null) {
mergedSegmentResult.setCopyrights(extractCopyrights(segmentScancode));
mergedSegmentResult.setScancodeLicenses(extractScancodeLicenses(segmentScancode));
mergedSegmentResult.setScancodeLicenseKeys(extractScancodeLicenseKeys(segmentScancode));
mergedSegmentResult.setPath(scancodePath);
add = true;
}
if (add) {
mergedScanResult.add(mergedSegmentResult);
}
}
}
}
private static JSONObject getSegmentFromScancode(JSONArray segments, String path) throws IOException {
for (int i = 0; i < segments.length(); i++) {
JSONObject segment = segments.optJSONObject(i);
if (segment.optString("path").equals(path)) {
return segment;
}
}
return null;
}
private List extractCopyrights(JSONObject segment) throws IOException {
final JSONArray copyrightsJson = segment.optJSONArray("copyrights");
if (copyrightsJson != null) {
final List copyrights = new ArrayList<>();
for (int i = 0; i < copyrightsJson.length(); i++) {
StringUtils.addNonEmptyString(copyrightsJson.getJSONObject(i).optString("copyright"), copyrights);
}
if (!copyrights.isEmpty()) {
return copyrights;
}
}
return Collections.emptyList();
}
private List extractScancodeLicenses(JSONObject segmentScancode) throws IOException {
final List licenses = new ArrayList<>();
final JSONArray licenseJson = segmentScancode.optJSONArray("licenses");
if (licenseJson != null) {
for (int k = 0; k < licenseJson.length(); k++) {
StringUtils.addNonEmptyString(licenseJson.getJSONObject(k).optString("name"), licenses);
}
if (!licenses.isEmpty()) {
return licenses;
}
}
return Collections.emptyList();
}
private Map extractScancodeLicenseKeys(JSONObject segmentScancode) throws IOException {
final Map keyValues = new HashMap<>();
final JSONArray licenseJson = segmentScancode.optJSONArray("licenses");
if (licenseJson != null) {
for (int k = 0; k < licenseJson.length(); k++) {
String key = licenseJson.getJSONObject(k).getString("key");
Float value = licenseJson.getJSONObject(k).getFloat("score");
if (StringUtils.notEmpty(key) && StringUtils.notEmpty(String.valueOf(value))) {
keyValues.put(key, value);
}
}
if (!keyValues.isEmpty()) {
return keyValues;
}
}
return Collections.emptyMap();
}
private List extractFromMetascanResult(JSONArray array) {
List list = new ArrayList<>();
if (array != null) {
for (int i = 0; i < array.length(); i++) {
list.add(array.optString(i));
}
}
return list;
}
private List extractVariables(JSONArray array) {
List list = new ArrayList<>();
if (array != null) {
for (int i = 0; i < array.length(); i++) {
//input
JSONObject variable = array.optJSONObject(i);
String license = variable.keySet().toArray()[0].toString();
JSONObject values = variable.optJSONObject(license);
//output
Variables variableObj = new Variables();
for (String s : values.keySet()) {
variableObj.putValues(s, values.optString(s));
}
variableObj.setLicense(license);
list.add(variableObj);
}
}
return list;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy