diff --git a/backend/src-common/pom.xml b/backend/src-common/pom.xml index fe223ceaf3..c2a23ca490 100644 --- a/backend/src-common/pom.xml +++ b/backend/src-common/pom.xml @@ -37,11 +37,24 @@ + + + com.googlecode.json-simple + json-simple + 1.1.1 + compile + org.spdx spdx-tools compile + + org.spdx + tools-java + 1.0.2 + compile + org.apache.logging.log4j diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ChangeLogsDatabaseHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ChangeLogsDatabaseHandler.java index 13eb4b284c..757469216d 100644 --- a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ChangeLogsDatabaseHandler.java +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ChangeLogsDatabaseHandler.java @@ -59,7 +59,6 @@ public List getChangeLogsByDocumentId(User user, String docId) { changeLogsByDocId = changeLogsByDocId.stream().filter(Objects::nonNull).filter(changeLog -> isNotEmptyChangeLog(changeLog)) .collect(Collectors.toList()); Collections.sort(changeLogsByDocId, Comparator.comparing(ChangeLogs::getChangeTimestamp).reversed()); - changeLogsByDocId.stream().forEach(cl -> cl.setChangeTimestamp(cl.getChangeTimestamp().split(" ")[0])); return changeLogsByDocId; } diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ComponentDatabaseHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ComponentDatabaseHandler.java index e71ef9797b..97d3f54465 100644 --- a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ComponentDatabaseHandler.java +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ComponentDatabaseHandler.java @@ -62,10 +62,21 @@ import org.eclipse.sw360.spdx.SpdxBOMImporterSink; import org.jetbrains.annotations.NotNull; import org.spdx.rdfparser.InvalidSPDXAnalysisException; - +import org.spdx.tools.SpdxConverter; +import org.spdx.tools.SpdxConverterException; +import org.spdx.tools.TagToRDF; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.net.MalformedURLException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -160,6 +171,7 @@ public ComponentDatabaseHandler(Supplier httpClient, String dbNa attachmentConnector = new AttachmentConnector(httpClient, attachmentDbName, durationOf(30, TimeUnit.SECONDS)); DatabaseConnectorCloudant dbChangeLogs = new DatabaseConnectorCloudant(httpClient, DatabaseSettings.COUCH_DB_CHANGE_LOGS); this.dbHandlerUtil = new DatabaseHandlerUtil(dbChangeLogs); + } public ComponentDatabaseHandler(Supplier httpClient, String dbName, String changeLogsDbName, String attachmentDbName, ComponentModerator moderator, ReleaseModerator releaseModerator, ProjectModerator projectModerator) throws MalformedURLException { @@ -513,12 +525,26 @@ public AddDocumentRequestSummary addRelease(Release release, User user) throws S } private boolean isDuplicate(Component component, boolean caseInsenstive){ - Set duplicates = componentRepository.getComponentIdsByName(component.getName(), caseInsenstive); - return duplicates.size()>0; + return isDuplicate(component.getName(), caseInsenstive); } private boolean isDuplicate(Release release){ - List duplicates = releaseRepository.searchByNameAndVersion(release.getName(), release.getVersion()); + return isDuplicate(release.getName(), release.getVersion()); + } + + private boolean isDuplicate(String componentName, boolean caseInsenstive) { + if (isNullEmptyOrWhitespace(componentName)) { + return false; + } + Set duplicates = componentRepository.getComponentIdsByName(componentName, caseInsenstive); + return duplicates.size()>0; + } + + private boolean isDuplicate(String releaseName, String releaseVersion) { + if (isNullEmptyOrWhitespace(releaseName)) { + return false; + } + List duplicates = releaseRepository.searchByNameAndVersion(releaseName, releaseVersion); return duplicates.size()>0; } @@ -1680,6 +1706,7 @@ public RequestStatus deleteRelease(String id, User user) throws SW360Exception { // Remove release id from component removeReleaseId(id, release.componentId); Component componentAfter=removeReleaseAndCleanUp(release, user); + dbHandlerUtil.addChangeLogs(null, release, user.getEmail(), Operation.DELETE, attachmentConnector, Lists.newArrayList(), null, null); dbHandlerUtil.addChangeLogs(componentAfter, componentBefore, user.getEmail(), Operation.UPDATE, @@ -2363,21 +2390,191 @@ private void sendMailNotificationsForReleaseUpdate(Release release, String user) release.getName(), release.getVersion()); } - public RequestSummary importBomFromAttachmentContent(User user, String attachmentContentId) throws SW360Exception { + public ImportBomRequestPreparation prepareImportBom(User user, String attachmentContentId) throws SW360Exception { final AttachmentContent attachmentContent = attachmentConnector.getAttachmentContent(attachmentContentId); final Duration timeout = Duration.durationOf(30, TimeUnit.SECONDS); + String sourceFilePath = null; + String targetFilePath = null; try { final AttachmentStreamConnector attachmentStreamConnector = new AttachmentStreamConnector(timeout); try (final InputStream inputStream = attachmentStreamConnector.unsafeGetAttachmentStream(attachmentContent)) { final SpdxBOMImporterSink spdxBOMImporterSink = new SpdxBOMImporterSink(user, null, this); final SpdxBOMImporter spdxBOMImporter = new SpdxBOMImporter(spdxBOMImporterSink); - return spdxBOMImporter.importSpdxBOMAsRelease(inputStream, attachmentContent); + + InputStream spdxInputStream = null; + String fileType = getFileType(attachmentContent.getFilename()); + + if (!fileType.equals("rdf")) { + final String ext = "." + fileType; + final File sourceFile = DatabaseHandlerUtil.saveAsTempFile(user, inputStream, attachmentContentId, ext); + sourceFilePath = sourceFile.getAbsolutePath(); + targetFilePath = sourceFilePath.replace(ext, ".rdf"); + File targetFile = null; + try { + if (fileType.equals("spdx")) { + targetFile = convertTagToRdf(sourceFile, targetFilePath); + } else { + SpdxConverter.convert(sourceFilePath, targetFilePath); + targetFile = new File(targetFilePath); + } + spdxInputStream = new FileInputStream(targetFile); + } catch (SpdxConverterException e) { + log.error("Can not convert to RDF \n" + e); + ImportBomRequestPreparation importBomRequestPreparation = new ImportBomRequestPreparation(); + importBomRequestPreparation.setRequestStatus(RequestStatus.FAILURE); + importBomRequestPreparation.setMessage("error-convert"); + return importBomRequestPreparation; + + } finally { + Files.delete(Paths.get(sourceFilePath)); + } + } else { + final String ext = "." + fileType; + final File sourceFile = DatabaseHandlerUtil.saveAsTempFile(user, inputStream, attachmentContentId, ext); + sourceFilePath = sourceFile.getAbsolutePath(); + cutFileInformation(sourceFilePath); + File targetFile = new File (sourceFilePath); + spdxInputStream = new FileInputStream(targetFile); + targetFilePath = sourceFilePath; + } + + ImportBomRequestPreparation importBomRequestPreparation = spdxBOMImporter.prepareImportSpdxBOMAsRelease(spdxInputStream, attachmentContent); + if (RequestStatus.SUCCESS.equals(importBomRequestPreparation.getRequestStatus())) { + String name = importBomRequestPreparation.getName(); + String version = importBomRequestPreparation.getVersion(); + if (!isDuplicate(name, true)) { + importBomRequestPreparation.setIsComponentDuplicate(false); + importBomRequestPreparation.setIsReleaseDuplicate(false); + } else if (!isDuplicate(name, version)) { + importBomRequestPreparation.setIsComponentDuplicate(true); + importBomRequestPreparation.setIsReleaseDuplicate(false); + } else { + importBomRequestPreparation.setIsComponentDuplicate(true); + importBomRequestPreparation.setIsReleaseDuplicate(true); + } + importBomRequestPreparation.setMessage(targetFilePath); + } + + return importBomRequestPreparation; } } catch (InvalidSPDXAnalysisException | IOException e) { throw new SW360Exception(e.getMessage()); } } + private void cutFileInformation(String pathFile) { + try { + log.info("Run command cut File information from RDF file from line"); + String command = "file=\"" + pathFile + "\" " + + "&& start=$(cat $file | grep -nF \"spdx:hasFile>\" | head -1 | cut -d \":\" -f1) " + + "&& end=$(cat $file | grep -nF \"/spdx:hasFile>\" | tail -1 | cut -d \":\" -f1) " + + "&& echo $start to $end " + + "&& sed -i \"${start},${end}d\" $file "; + Process process = Runtime.getRuntime().exec(new String[] { "/bin/bash", "-c", command }); + printResults(process); + } catch (IOException e) { + log.error("Error when cut File information"); + e.printStackTrace(); + } + } + + public static void printResults(Process process) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line = ""; + while ((line = reader.readLine()) != null) { + log.info(line); + } + } + + private File convertTagToRdf(File sourceFile, String targetFilePath) { + FileInputStream spdxTagStream = null; + + try { + spdxTagStream = new FileInputStream(sourceFile); + } catch (FileNotFoundException e2) { + e2.printStackTrace(); + } + + File spdxRDFFile = new File(targetFilePath); + String outputFormat = "RDF/XML"; + FileOutputStream outStream = null; + try { + outStream = new FileOutputStream(spdxRDFFile); + } catch (FileNotFoundException e1) { + try { + spdxTagStream.close(); + } catch (IOException e) { + log.error("Warning: Unable to close input file on error."); + } + log.error("Could not write to the new SPDX RDF file " + spdxRDFFile.getPath() + "due to error " + e1.getMessage()); + } + + List warnings = new ArrayList(); + try { + TagToRDF.convertTagFileToRdf(spdxTagStream, outStream, outputFormat, warnings); + if (!warnings.isEmpty()) { + log.warn("The following warnings and or verification errors were found:"); + for (String warning:warnings) { + log.warn("\t" + warning); + } + } + } catch (Exception e) { + log.error("Error creating SPDX Analysis: " + e.getMessage()); + } finally { + if (outStream != null) { + try { + outStream.close(); + } catch (IOException e) { + log.error("Error closing RDF file: " + e.getMessage()); + } + } + if (spdxTagStream != null) { + try { + spdxTagStream.close(); + } catch (IOException e) { + log.error("Error closing Tag/Value file: " + e.getMessage()); + } + } + } + return spdxRDFFile; + } + + public RequestSummary importBomFromAttachmentContent(User user, String attachmentContentId, String newReleaseVersion, String releaseId, String rdfFilePath) throws SW360Exception { + final AttachmentContent attachmentContent = attachmentConnector.getAttachmentContent(attachmentContentId); + try { + final SpdxBOMImporterSink spdxBOMImporterSink = new SpdxBOMImporterSink(user, null, this); + final SpdxBOMImporter spdxBOMImporter = new SpdxBOMImporter(spdxBOMImporterSink); + InputStream spdxInputStream = null; + if (!isNullEmptyOrWhitespace(rdfFilePath)) { + spdxInputStream = new FileInputStream(new File(rdfFilePath)); + Files.delete(Paths.get(rdfFilePath)); + } else { + spdxInputStream = attachmentConnector.unsafeGetAttachmentStream(attachmentContent); + } + return spdxBOMImporter.importSpdxBOMAsRelease(spdxInputStream, attachmentContent, newReleaseVersion, releaseId); + } catch (IOException e) { + throw new SW360Exception(e.getMessage()); + } + } + + private String getFileType(String fileName) { + if (isNullEmptyOrWhitespace(fileName) || !fileName.contains(".")) { + log.error("Can not get file type from file name - no file extension"); + return null; + } + String ext = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); + if ("xml".equals(ext)) { + if (fileName.endsWith("rdf.xml")) { + ext = "rdf"; + } + } + return ext; + } + + private boolean isJSONFile(String fileType) { + return (!isNullEmptyOrWhitespace(fileType) && fileType.equals("json")); + } + private void removeLeadingTrailingWhitespace(Release release) { DatabaseHandlerUtil.trimStringFields(release, listOfStringFieldsInReleaseToTrim); diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/DatabaseHandlerUtil.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/DatabaseHandlerUtil.java index 37a24af415..c8e0be10d8 100644 --- a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/DatabaseHandlerUtil.java +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/DatabaseHandlerUtil.java @@ -10,6 +10,7 @@ package org.eclipse.sw360.datahandler.db; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -44,6 +45,7 @@ import java.util.stream.Collectors; import org.apache.logging.log4j.Level; +import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.LoggerContext; @@ -75,6 +77,7 @@ import org.eclipse.sw360.datahandler.couchdb.DatabaseMixInForChangeLog.RepositoryMixin; import org.eclipse.sw360.datahandler.couchdb.DatabaseMixInForChangeLog.VendorMixin; import org.eclipse.sw360.datahandler.couchdb.DatabaseMixInForChangeLog.ObligationMixin; +import org.eclipse.sw360.datahandler.couchdb.DatabaseMixInForChangeLog.*; import org.eclipse.sw360.datahandler.thrift.ProjectReleaseRelationship; import org.eclipse.sw360.datahandler.thrift.RequestStatus; import org.eclipse.sw360.datahandler.thrift.SW360Exception; @@ -124,6 +127,7 @@ public class DatabaseHandlerUtil { private static final boolean IS_STORE_ATTACHMENT_TO_FILE_SYSTEM_ENABLED; private static final String ATTACHMENT_STORE_FILE_SYSTEM_LOCATION; private static final String ATTACHMENT_STORE_FILE_SYSTEM_PERMISSION; + // private static final String TEMPLE_FILE_LOCATION; private static ExecutorService ATTACHMENT_FILE_SYSTEM_STORE_THREAD_POOL = Executors.newFixedThreadPool(5); private static final String ATTACHMENT_DELETE_NO_OF_DAYS; private static final boolean IS_SW360CHANGELOG_ENABLED; @@ -139,6 +143,7 @@ public class DatabaseHandlerUtil { "/opt/sw360tempattachments"); ATTACHMENT_STORE_FILE_SYSTEM_PERMISSION = props.getProperty("attachment.store.file.system.permission", "rwx------"); + // TEMPLE_FILE_LOCATION = props.getProperty("temp.dir", "../temp") IS_STORE_ATTACHMENT_TO_FILE_SYSTEM_ENABLED = Boolean.parseBoolean(props.getProperty("enable.attachment.store.to.file.system", "false")); ATTACHMENT_DELETE_NO_OF_DAYS = props.getProperty("attachemnt.delete.no.of.days", "30"); @@ -411,8 +416,6 @@ public static void trimStringFields(T obj, List listOfStrFields) { changeLog.setDbName(DatabaseSettings.COUCH_DB_DATABASE); } - log.info("Initialize ChangeLogs for Document Id : " + changeLog.getDocumentId()); - if (parentOperation != null) info.put("PARENT_OPERATION", parentOperation.name()); if (!info.isEmpty()) @@ -690,7 +693,7 @@ private static boolean isTwoCollectionSame(Collection col1, Collection col } private static String getTimeStamp() { - SimpleDateFormat timestampPattern = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat timestampPattern = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); Date timeNow = new Date(System.currentTimeMillis()); return timestampPattern.format(timeNow); } @@ -979,5 +982,14 @@ private static void configureLog4J(String outputpath, String liferayhome) { .add( builder.newAppenderRef("ChangeLogFile"))); Configurator.reconfigure(builder.build()); } + public static File saveAsTempFile(User user, InputStream inputStream, String prefix, String suffix) throws IOException { + final File tempFile = File.createTempFile(prefix, suffix); + tempFile.deleteOnExit(); + // Set append to false, overwrite if file existed + try (FileOutputStream outputStream = new FileOutputStream(tempFile, false)) { + IOUtils.copy(inputStream, outputStream); + } + return tempFile; + } } diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/spdx/SpdxBOMImporter.java b/backend/src-common/src/main/java/org/eclipse/sw360/spdx/SpdxBOMImporter.java index d8695e3450..30d31caa56 100644 --- a/backend/src-common/src/main/java/org/eclipse/sw360/spdx/SpdxBOMImporter.java +++ b/backend/src-common/src/main/java/org/eclipse/sw360/spdx/SpdxBOMImporter.java @@ -1,5 +1,7 @@ /* * Copyright Siemens AG, 2019. Part of the SW360 Portal Project. + * Copyright TOSHIBA CORPORATION, 2021. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2021. Part of the SW360 Portal Project. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -14,12 +16,14 @@ import org.eclipse.sw360.datahandler.thrift.attachments.Attachment; import org.eclipse.sw360.datahandler.thrift.attachments.AttachmentContent; import org.eclipse.sw360.datahandler.thrift.attachments.AttachmentType; +import org.eclipse.sw360.datahandler.thrift.attachments.CheckStatus; import org.eclipse.sw360.datahandler.thrift.components.Component; import org.eclipse.sw360.datahandler.thrift.components.Release; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.spdx.rdfparser.InvalidSPDXAnalysisException; import org.spdx.rdfparser.SPDXDocumentFactory; import org.spdx.rdfparser.model.*; +import org.spdx.rdfparser.model.pointer.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -28,6 +32,8 @@ import java.util.*; import java.util.stream.Collectors; +import static org.eclipse.sw360.datahandler.common.CommonUtils.isNotNullEmptyOrWhitespace; + public class SpdxBOMImporter { private static final Logger log = LogManager.getLogger(SpdxBOMImporter.class); private final SpdxBOMImporterSink sink; @@ -36,9 +42,41 @@ public SpdxBOMImporter(SpdxBOMImporterSink sink) { this.sink = sink; } - public RequestSummary importSpdxBOMAsRelease(InputStream inputStream, AttachmentContent attachmentContent) + public ImportBomRequestPreparation prepareImportSpdxBOMAsRelease(InputStream inputStream, AttachmentContent attachmentContent) throws InvalidSPDXAnalysisException, SW360Exception { - return importSpdxBOM(inputStream, attachmentContent, SW360Constants.TYPE_RELEASE); + final ImportBomRequestPreparation requestPreparation = new ImportBomRequestPreparation(); + final SpdxDocument spdxDocument = openAsSpdx(inputStream); + final List describedPackages = Arrays.stream(spdxDocument.getDocumentDescribes()) + .filter(item -> item instanceof SpdxPackage) + .collect(Collectors.toList()); + + if (describedPackages.size() == 0) { + requestPreparation.setMessage("The provided BOM did not contain any top level packages."); + requestPreparation.setRequestStatus(RequestStatus.FAILURE); + return requestPreparation; + } else if (describedPackages.size() > 1) { + requestPreparation.setMessage("The provided BOM file contained multiple described top level packages. This is not allowed here."); + requestPreparation.setRequestStatus(RequestStatus.FAILURE); + return requestPreparation; + } + + final SpdxItem spdxItem = describedPackages.get(0); + if (spdxItem instanceof SpdxPackage) { + final SpdxPackage spdxPackage = (SpdxPackage) spdxItem; + + requestPreparation.setName(spdxPackage.getName()); + requestPreparation.setVersion(spdxPackage.getVersionInfo()); + requestPreparation.setRequestStatus(RequestStatus.SUCCESS); + } else { + requestPreparation.setMessage("Failed to get spdx package from the provided BOM file."); + requestPreparation.setRequestStatus(RequestStatus.FAILURE); + } + return requestPreparation; + } + + public RequestSummary importSpdxBOMAsRelease(InputStream inputStream, AttachmentContent attachmentContent, String newReleaseVersion, String releaseId) + throws SW360Exception { + return importSpdxBOM(inputStream, attachmentContent, SW360Constants.TYPE_RELEASE, newReleaseVersion, releaseId); } public RequestSummary importSpdxBOMAsProject(InputStream inputStream, AttachmentContent attachmentContent) @@ -48,11 +86,22 @@ public RequestSummary importSpdxBOMAsProject(InputStream inputStream, Attachment private RequestSummary importSpdxBOM(InputStream inputStream, AttachmentContent attachmentContent, String type) throws InvalidSPDXAnalysisException, SW360Exception { + return importSpdxBOM(inputStream, attachmentContent, type, null, null); + } + + private RequestSummary importSpdxBOM(InputStream inputStream, AttachmentContent attachmentContent, String type, String newReleaseVersion, String releaseId) + throws SW360Exception { final RequestSummary requestSummary = new RequestSummary(); - final SpdxDocument spdxDocument = openAsSpdx(inputStream); - final List describedPackages = Arrays.stream(spdxDocument.getDocumentDescribes()) - .filter(item -> item instanceof SpdxPackage) - .collect(Collectors.toList()); + SpdxDocument spdxDocument = null; + List describedPackages = new ArrayList<>(); + try { + spdxDocument = openAsSpdx(inputStream); + describedPackages = Arrays.stream(spdxDocument.getDocumentDescribes()) + .filter(item -> item instanceof SpdxPackage) + .collect(Collectors.toList()); + } catch (InvalidSPDXAnalysisException e) { + log.error("Can not open file to SpdxDocument " +e); + } if (describedPackages.size() == 0) { requestSummary.setTotalAffectedElements(0); @@ -73,7 +122,7 @@ private RequestSummary importSpdxBOM(InputStream inputStream, AttachmentContent if (SW360Constants.TYPE_PROJECT.equals(type)) { response = importAsProject(spdxItem, attachmentContent); } else if (SW360Constants.TYPE_RELEASE.equals(type)) { - response = importAsRelease(spdxItem, attachmentContent); + response = importAsRelease(spdxItem, attachmentContent, spdxDocument, newReleaseVersion, releaseId); } else { throw new SW360Exception("Unsupported type=[" + type + "], can not import BOM"); } @@ -121,29 +170,71 @@ private Release createReleaseFromSpdxPackage(SpdxPackage spdxPackage) { return release; } + // refer to rangeToStr function of spdx-tools + private String[] rangeToStrs(StartEndPointer rangePointer) throws InvalidSPDXAnalysisException { + SinglePointer startPointer = rangePointer.getStartPointer(); + if (startPointer == null) { + throw new InvalidSPDXAnalysisException("Missing start pointer"); + } + SinglePointer endPointer = rangePointer.getEndPointer(); + if (endPointer == null) { + throw new InvalidSPDXAnalysisException("Missing end pointer"); + } + String start = null; + if (startPointer instanceof ByteOffsetPointer) { + start = String.valueOf(((ByteOffsetPointer)startPointer).getOffset()); + } else if (startPointer instanceof LineCharPointer) { + start = String.valueOf(((LineCharPointer)startPointer).getLineNumber()); + } else { + log.error("Unknown pointer type for start pointer "+startPointer.toString()); + throw new InvalidSPDXAnalysisException("Unknown pointer type for start pointer"); + } + String end = null; + if (endPointer instanceof ByteOffsetPointer) { + end = String.valueOf(((ByteOffsetPointer)endPointer).getOffset()); + } else if (endPointer instanceof LineCharPointer) { + end = String.valueOf(((LineCharPointer)endPointer).getLineNumber()); + } else { + log.error("Unknown pointer type for start pointer "+startPointer.toString()); + throw new InvalidSPDXAnalysisException("Unknown pointer type for start pointer"); + } + return new String[] { start, end }; + } + private Attachment makeAttachmentFromContent(AttachmentContent attachmentContent) { Attachment attachment = new Attachment(); attachment.setAttachmentContentId(attachmentContent.getId()); - attachment.setAttachmentType(AttachmentType.OTHER); + attachment.setAttachmentType(AttachmentType.SBOM); attachment.setCreatedComment("Used for SPDX Bom import"); attachment.setFilename(attachmentContent.getFilename()); + attachment.setCheckStatus(CheckStatus.NOTCHECKED); return attachment; } private Optional importAsRelease(SpdxElement relatedSpdxElement) throws SW360Exception { - return importAsRelease(relatedSpdxElement, null); + return importAsRelease(relatedSpdxElement, null, null, null, null); } - private Optional importAsRelease(SpdxElement relatedSpdxElement, AttachmentContent attachmentContent) throws SW360Exception { + private Optional importAsRelease(SpdxElement relatedSpdxElement, AttachmentContent attachmentContent, + SpdxDocument spdxDocument, String newReleaseVersion, String releaseId) throws SW360Exception { if (relatedSpdxElement instanceof SpdxPackage) { final SpdxPackage spdxPackage = (SpdxPackage) relatedSpdxElement; - SpdxBOMImporterSink.Response component = importAsComponent(spdxPackage); - final String componentId = component.getId(); - - final Release release = createReleaseFromSpdxPackage(spdxPackage); - release.setComponentId(componentId); + final Release release; + SpdxBOMImporterSink.Response component; + if (isNotNullEmptyOrWhitespace(releaseId)) { + release = sink.getRelease(releaseId); + component = new SpdxBOMImporterSink.Response(release.getComponentId(), true); + } else { + component = importAsComponent(spdxPackage); + final String componentId = component.getId(); + + release = createReleaseFromSpdxPackage(spdxPackage); + if (isNotNullEmptyOrWhitespace(newReleaseVersion)) + release.setVersion(newReleaseVersion); + release.setComponentId(componentId); + } final Relationship[] relationships = spdxPackage.getRelationships(); List releases = importAsReleases(relationships); @@ -157,6 +248,7 @@ private Optional importAsRelease(SpdxElement relat final SpdxBOMImporterSink.Response response = sink.addRelease(release); + response.addChild(component); return Optional.of(response); } else { @@ -237,4 +329,147 @@ private Optional importAsProject(SpdxElement spdxE return Optional.empty(); } } + + + private String verifyOrSetDefault(String value) { + return (isNotNullEmptyOrWhitespace(value)) ? value : ""; + } + + private String[] verifyOrSetDefault(String[] values) { + return (values != null && values.length > 0) ? values : new String[0]; + } + + + public RequestSummary importSpdxBOMAsReleaseForTest(InputStream inputStream, AttachmentContent attachmentContent) + throws InvalidSPDXAnalysisException, SW360Exception { + return importSpdxBOMForTest(inputStream, attachmentContent, SW360Constants.TYPE_RELEASE); + } + + public RequestSummary importSpdxBOMAsProjectForTest(InputStream inputStream, AttachmentContent attachmentContent) + throws InvalidSPDXAnalysisException, SW360Exception { + return importSpdxBOMForTest(inputStream, attachmentContent, SW360Constants.TYPE_PROJECT); + } + private RequestSummary importSpdxBOMForTest(InputStream inputStream, AttachmentContent attachmentContent, String type) + throws InvalidSPDXAnalysisException, SW360Exception { + final RequestSummary requestSummary = new RequestSummary(); + final SpdxDocument spdxDocument = openAsSpdx(inputStream); + final List describedPackages = Arrays.stream(spdxDocument.getDocumentDescribes()) + .filter(item -> item instanceof SpdxPackage) + .collect(Collectors.toList()); + + if (describedPackages.size() == 0) { + requestSummary.setTotalAffectedElements(0); + requestSummary.setTotalElements(0); + requestSummary.setMessage("The provided BOM did not contain any top level packages."); + requestSummary.setRequestStatus(RequestStatus.FAILURE); + return requestSummary; + } else if (describedPackages.size() > 1) { + requestSummary.setTotalAffectedElements(0); + requestSummary.setTotalElements(0); + requestSummary.setMessage("The provided BOM file contained multiple described top level packages. This is not allowed here."); + requestSummary.setRequestStatus(RequestStatus.FAILURE); + return requestSummary; + } + + final SpdxItem spdxItem = describedPackages.get(0); + final Optional response; + if (SW360Constants.TYPE_PROJECT.equals(type)) { + response = importAsProjectForTest(spdxItem, attachmentContent); + } else if (SW360Constants.TYPE_RELEASE.equals(type)) { + response = importAsReleaseForTest(spdxItem, attachmentContent); + } else { + throw new SW360Exception("Unsupported type=[" + type + "], can not import BOM"); + } + + if (response.isPresent()) { + requestSummary.setRequestStatus(RequestStatus.SUCCESS); + requestSummary.setTotalAffectedElements(response.get().countAffected()); + requestSummary.setTotalElements(response.get().count()); + requestSummary.setMessage(response.get().getId()); + } else { + requestSummary.setRequestStatus(RequestStatus.FAILURE); + requestSummary.setTotalAffectedElements(-1); + requestSummary.setTotalElements(-1); + requestSummary.setMessage("Failed to import the BOM as type=[" + type + "]."); + } + return requestSummary; + } + private Optional importAsReleaseForTest(SpdxElement relatedSpdxElement) throws SW360Exception { + return importAsReleaseForTest(relatedSpdxElement, null); + } + private Optional importAsReleaseForTest(SpdxElement relatedSpdxElement, AttachmentContent attachmentContent) throws SW360Exception { + if (relatedSpdxElement instanceof SpdxPackage) { + final SpdxPackage spdxPackage = (SpdxPackage) relatedSpdxElement; + + SpdxBOMImporterSink.Response component = importAsComponent(spdxPackage); + final String componentId = component.getId(); + + final Release release = createReleaseFromSpdxPackage(spdxPackage); + release.setComponentId(componentId); + + final Relationship[] relationships = spdxPackage.getRelationships(); + List releases = importAsReleasesForTest(relationships); + Map releaseIdToRelationship = makeReleaseIdToRelationship(releases); + release.setReleaseIdToRelationship(releaseIdToRelationship); + + if(attachmentContent != null) { + Attachment attachment = makeAttachmentFromContent(attachmentContent); + release.setAttachments(Collections.singleton(attachment)); + } + + + final SpdxBOMImporterSink.Response response = sink.addRelease(release); + response.addChild(component); + return Optional.of(response); + } else { + log.debug("Unsupported SpdxElement: " + relatedSpdxElement.getClass().getCanonicalName()); + return Optional.empty(); + } + } + private List importAsReleasesForTest(Relationship[] relationships) throws SW360Exception { + List releases = new ArrayList<>(); + + Map typeToSupplierMap = new HashMap<>(); + typeToSupplierMap.put(Relationship.RelationshipType.CONTAINS, ReleaseRelationship.CONTAINED); + + for (Relationship relationship : relationships) { + final Relationship.RelationshipType relationshipType = relationship.getRelationshipType(); + if(! typeToSupplierMap.keySet().contains(relationshipType)) { + log.debug("Unsupported RelationshipType: " + relationshipType.toString()); + continue; + } + + final SpdxElement relatedSpdxElement = relationship.getRelatedSpdxElement(); + final Optional releaseId = importAsReleaseForTest(relatedSpdxElement); + releaseId.map(response -> { + response.setReleaseRelationship(typeToSupplierMap.get(relationshipType)); + return response; + }).ifPresent(releases::add); + } + return releases; + } + private Optional importAsProjectForTest(SpdxElement spdxElement, AttachmentContent attachmentContent) throws SW360Exception { + if (spdxElement instanceof SpdxPackage) { + final SpdxPackage spdxPackage = (SpdxPackage) spdxElement; + + final Project project = creatProjectFromSpdxPackage(spdxPackage); + + final Relationship[] relationships = spdxPackage.getRelationships(); + List releases = importAsReleasesForTest(relationships); + Map releaseIdToProjectRelationship = makeReleaseIdToProjectRelationship(releases); + project.setReleaseIdToUsage(releaseIdToProjectRelationship); + + if(attachmentContent != null) { + Attachment attachment = makeAttachmentFromContent(attachmentContent); + project.setAttachments(Collections.singleton(attachment)); + } + + final SpdxBOMImporterSink.Response response = sink.addProject(project); + response.addChilds(releases); + return Optional.of(response); + } else { + log.debug("Unsupported SpdxElement: " + spdxElement.getClass().getCanonicalName()); + return Optional.empty(); + } + } } diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/spdx/SpdxBOMImporterSink.java b/backend/src-common/src/main/java/org/eclipse/sw360/spdx/SpdxBOMImporterSink.java index 8a1f07ee13..d7cea0bf91 100644 --- a/backend/src-common/src/main/java/org/eclipse/sw360/spdx/SpdxBOMImporterSink.java +++ b/backend/src-common/src/main/java/org/eclipse/sw360/spdx/SpdxBOMImporterSink.java @@ -22,6 +22,7 @@ import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.users.User; +import java.net.MalformedURLException; import java.util.*; import java.util.stream.Collectors; @@ -32,7 +33,7 @@ public class SpdxBOMImporterSink { private final ComponentDatabaseHandler componentDatabaseHandler; private final User user; - public SpdxBOMImporterSink(User user, ProjectDatabaseHandler projectDatabaseHandler, ComponentDatabaseHandler componentDatabaseHandler) { + public SpdxBOMImporterSink(User user, ProjectDatabaseHandler projectDatabaseHandler, ComponentDatabaseHandler componentDatabaseHandler) throws MalformedURLException { this.projectDatabaseHandler = projectDatabaseHandler; this.componentDatabaseHandler = componentDatabaseHandler; this.user = user; @@ -68,6 +69,7 @@ public Response addRelease(Release release) throws SW360Exception { return new Response(releaseId, AddDocumentRequestStatus.SUCCESS.equals(addDocumentRequestSummary.getRequestStatus())); } + public Response addProject(Project project) throws SW360Exception { log.debug("create Project { name='" + project.getName() + "', version='" + project.getVersion() + "' }"); @@ -91,6 +93,10 @@ public Response addProject(Project project) throws SW360Exception { return new Response(projectId, AddDocumentRequestStatus.SUCCESS.equals(addDocumentRequestSummary.getRequestStatus())); } + public Release getRelease(String id) throws SW360Exception { + return componentDatabaseHandler.getRelease(id, user); + } + public static class Response { private final String id; private final List childs; diff --git a/backend/src-common/src/test/java/org/eclipse/sw360/spdx/SpdxBOMImporterTest.java b/backend/src-common/src/test/java/org/eclipse/sw360/spdx/SpdxBOMImporterTest.java index 7a26e3adea..2b82f58113 100644 --- a/backend/src-common/src/test/java/org/eclipse/sw360/spdx/SpdxBOMImporterTest.java +++ b/backend/src-common/src/test/java/org/eclipse/sw360/spdx/SpdxBOMImporterTest.java @@ -41,7 +41,6 @@ public class SpdxBOMImporterTest { @Before public void before() throws Exception { spdxBOMImporter = new SpdxBOMImporter(spdxBOMImporterSink); - inputStream = getClass() .getClassLoader().getResourceAsStream("bom.spdx.rdf"); @@ -73,7 +72,7 @@ public void after() throws Exception { @Test public void testProject() throws Exception { - final RequestSummary requestSummary = spdxBOMImporter.importSpdxBOMAsProject(inputStream, attachmentContent); + final RequestSummary requestSummary = spdxBOMImporter.importSpdxBOMAsProjectForTest(inputStream, attachmentContent); assertNotNull(requestSummary); verify(spdxBOMImporterSink, times(1)).addProject(Matchers.any()); @@ -83,7 +82,7 @@ public void testProject() throws Exception { @Test public void testRelease() throws Exception { - final RequestSummary requestSummary = spdxBOMImporter.importSpdxBOMAsRelease(inputStream, attachmentContent); + final RequestSummary requestSummary = spdxBOMImporter.importSpdxBOMAsReleaseForTest(inputStream, attachmentContent); assertNotNull(requestSummary); verify(spdxBOMImporterSink, times(4)).addComponent(Matchers.any()); diff --git a/backend/src/src-components/src/main/java/org/eclipse/sw360/components/ComponentHandler.java b/backend/src/src-components/src/main/java/org/eclipse/sw360/components/ComponentHandler.java index 431e3968c6..28260d847b 100644 --- a/backend/src/src-components/src/main/java/org/eclipse/sw360/components/ComponentHandler.java +++ b/backend/src/src-components/src/main/java/org/eclipse/sw360/components/ComponentHandler.java @@ -619,10 +619,17 @@ public String getCyclicLinkedReleasePath(Release release, User user) throws TExc } @Override - public RequestSummary importBomFromAttachmentContent(User user, String attachmentContentId) throws TException { + public ImportBomRequestPreparation prepareImportBom(User user, String attachmentContentId) throws TException { assertNotNull(attachmentContentId); assertUser(user); - return handler.importBomFromAttachmentContent(user, attachmentContentId); + return handler.prepareImportBom(user, attachmentContentId); + } + + @Override + public RequestSummary importBomFromAttachmentContent(User user, String attachmentContentId, String newReleaseVersion, String releaseId, String rdfFilePath) throws TException { + assertNotNull(attachmentContentId); + assertUser(user); + return handler.importBomFromAttachmentContent(user, attachmentContentId, newReleaseVersion, releaseId, rdfFilePath); } @Override diff --git a/backend/src/src-fossology/src/main/java/org/eclipse/sw360/fossology/rest/FossologyRestClient.java b/backend/src/src-fossology/src/main/java/org/eclipse/sw360/fossology/rest/FossologyRestClient.java index cfeafd4b29..050b978720 100644 --- a/backend/src/src-fossology/src/main/java/org/eclipse/sw360/fossology/rest/FossologyRestClient.java +++ b/backend/src/src-fossology/src/main/java/org/eclipse/sw360/fossology/rest/FossologyRestClient.java @@ -219,6 +219,7 @@ public int startScanning(int uploadId) { headers.set("Authorization", "Bearer " + token); headers.set("folderId", folderId); headers.set("uploadId", uploadId + ""); + headers.set("Content-Type", "application/json"); ObjectNode analysis = objectMapper.createObjectNode(); analysis.put("bucket", true); diff --git a/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/ModerationDatabaseHandler.java b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/ModerationDatabaseHandler.java index 36fa89e849..17aee583d2 100644 --- a/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/ModerationDatabaseHandler.java +++ b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/ModerationDatabaseHandler.java @@ -583,6 +583,15 @@ public void createRequest(User user) { addOrUpdate(request, user); } + private Set getSPDXDocumentModerators(String department, String createdBy) { + // Define moderators + Set moderators = new HashSet<>(); + CommonUtils.add(moderators, createdBy); + CommonUtils.addAll(moderators, getUsersAtLeast(UserGroup.ECC_ADMIN, department, false, true)); + CommonUtils.addAll(moderators, getUsersAtLeast(UserGroup.ADMIN)); + return moderators; + } + private String getDepartmentByUserEmail(String userEmail) throws TException { UserService.Iface client = (new ThriftClients()).makeUserClient(); return client.getDepartmentByEmail(userEmail); diff --git a/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/ReleaseModerationRequestGenerator.java b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/ReleaseModerationRequestGenerator.java index b868bfe792..0b61604f4e 100644 --- a/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/ReleaseModerationRequestGenerator.java +++ b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/ReleaseModerationRequestGenerator.java @@ -24,8 +24,6 @@ */ public class ReleaseModerationRequestGenerator extends ModerationRequestGenerator { - private static final String DUMMY_VALUE = "Dummy_Value"; - @Override public ModerationRequest setAdditionsAndDeletions(ModerationRequest request, Release updateRelease, Release actualRelease){ updateDocument = updateRelease; @@ -34,13 +32,13 @@ public ModerationRequest setAdditionsAndDeletions(ModerationRequest request, Rel documentAdditions = new Release(); documentDeletions = new Release(); //required fields: - documentAdditions.setName(DUMMY_VALUE); + documentAdditions.setName(updateRelease.getName()); documentAdditions.setId(updateRelease.getId()); - documentAdditions.setVersion(DUMMY_VALUE); + documentAdditions.setVersion(updateRelease.getVersion()); documentAdditions.setComponentId(updateRelease.getComponentId()); - documentDeletions.setName(DUMMY_VALUE); + documentDeletions.setName(actualRelease.getName()); documentDeletions.setId(actualRelease.getId()); - documentDeletions.setVersion(DUMMY_VALUE); + documentDeletions.setVersion(actualRelease.getVersion()); documentDeletions.setComponentId(actualRelease.getComponentId()); for (Release._Fields field : Release._Fields.values()) { diff --git a/build-configuration/test-resources/couchdb-test.properties b/build-configuration/test-resources/couchdb-test.properties index 4bc303fb06..ce99b80782 100644 --- a/build-configuration/test-resources/couchdb-test.properties +++ b/build-configuration/test-resources/couchdb-test.properties @@ -8,7 +8,7 @@ # SPDX-License-Identifier: EPL-2.0 # -# N.B this is the build property file, copied from module build-configuration +# N.B this is the build property file, copied from module build-configurationshould_document_get_projects_releases couchdb.url = http://localhost:5984 couchdb.user = diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/ChangeLogsPortletUtils.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/ChangeLogsPortletUtils.java index 3da089e1a9..ba68addd77 100644 --- a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/ChangeLogsPortletUtils.java +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/ChangeLogsPortletUtils.java @@ -22,6 +22,7 @@ import java.util.Comparator; import java.util.List; import java.util.Optional; +import java.util.Set; import javax.portlet.PortletRequest; import javax.portlet.ResourceRequest; @@ -38,6 +39,7 @@ import org.eclipse.sw360.datahandler.thrift.changelogs.ChangeLogs; import org.eclipse.sw360.datahandler.thrift.changelogs.ChangeLogsService; import org.eclipse.sw360.datahandler.thrift.changelogs.ChangeLogsService.Iface; +import org.eclipse.sw360.datahandler.thrift.components.ComponentService; import org.eclipse.sw360.datahandler.thrift.changelogs.ChangedFields; import org.eclipse.sw360.datahandler.thrift.changelogs.ReferenceDocData; import org.eclipse.sw360.datahandler.thrift.users.User; diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/PortalConstants.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/PortalConstants.java index c628411a41..4c27776d7a 100644 --- a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/PortalConstants.java +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/PortalConstants.java @@ -304,7 +304,6 @@ public class PortalConstants { public static final String PROJECT_OBLIGATIONS_INFO_BY_RELEASE = "projectObligationsInfoByRelease"; public static final String LINKED_OBLIGATIONS = "linkedObligations"; public static final String APPROVED_OBLIGATIONS_COUNT = "approvedObligationsCount"; - public static final String OBLIGATION_FROM_README_OSS = "obligationFromReadmeOSS"; public static final String EXCLUDED_RELEASES = "excludedReleases"; public static final String RELATIONSHIPS = "relations"; public static final String PROJECT_RELEASE_TO_RELATION = "projectReleaseToRelation"; @@ -501,7 +500,11 @@ public class PortalConstants { public static final String PARENT_SCOPE_GROUP_ID = "parentScopeGroupId"; // bom import + public static final String PREPARE_IMPORT_BOM = "prepareImportBom"; public static final String IMPORT_BOM = "importBom"; + public static final String IMPORT_BOM_AS_NEW = "importBomAsNew"; + public static final String NEW_RELEASE_VERSION = "newRleaseVersion"; + public static final String RDF_FILE_PATH = "rdfFilePath"; // project actions public static final String VIEW_LINKED_PROJECTS = "view_linked_projects"; @@ -662,6 +665,18 @@ public class PortalConstants { public static final boolean SSO_LOGIN_ENABLED; public static final boolean IS_COMPONENT_VISIBILITY_RESTRICTION_ENABLED; + //! Specialized keys for SPDX + public static final String SPDXDOCUMENT = "spdxDocument"; + public static final String SPDX_DOCUMENT_CREATION_INFO = "spdxDocumentCreationInfo"; + public static final String SPDX_PACKAGE_INFO = "spdxPackageInfo"; + public static final String SPDX_DOCUMENT_ID = "spdxDocumentId"; + public static final String SPDX_DOCUMENT_CREATION_INFO_ID = "spdxDocumentCreationInfoId"; + public static final String SPDX_PACKAGE_INFO_ID = "spdxPackageInfoId"; + public static final String ACTUAL_SPDXDOCUMENT = "actual_SPDXDocument"; + public static final String ACTUAL_DOCUMENT_CREATION_INFO = "actual_DocumentCreationInfo"; + public static final String ACTUAL_PACKAGE_INFO = "actual_PackageInfo"; + public static final Set SET_RELATIONSHIP_TYPE; + static { Properties props = CommonUtils.loadProperties(PortalConstants.class, PROPERTIES_FILE_PATH); @@ -700,6 +715,7 @@ public class PortalConstants { CLEARING_REPORT_TEMPLATE_FORMAT = props.getProperty("org.eclipse.sw360.licensinfo.projectclearing.templateformat", "docx"); PREDEFINED_TAGS = props.getProperty("project.tag", "[]"); SSO_LOGIN_ENABLED = Boolean.parseBoolean(props.getProperty("sso.login.enabled", "false")); + SET_RELATIONSHIP_TYPE = CommonUtils.splitToSet(props.getProperty("relationship.type", "DESCRIBES,DESCRIBED_BY,CONTAINS,CONTAINED_BY,DEPENDS_ON,DEPENDENCY_OF,DEPENDENCY_MANIFEST_OF,BUILD_DEPENDENCY_OF,DEV_DEPENDENCY_OF,OPTIONAL_DEPENDENCY_OF,PROVIDED_DEPENDENCY_OF,TEST_DEPENDENCY_OF,RUNTIME_DEPENDENCY_OF,EXAMPLE_OF,GENERATES,GENERATED_FROM,ANCESTOR_OF,DESCENDANT_OF,VARIANT_OF,DISTRIBUTION_ARTIFACT,PATCH_FOR,PATCH_APPLIED,COPY_OF,FILE_ADDED,FILE_DELETED,FILE_MODIFIED,EXPANDED_FROM_ARCHIVE,DYNAMIC_LINK,STATIC_LINK,DATA_FILE_OF,TEST_CASE_OF,BUILD_TOOL_OF,DEV_TOOL_OF,TEST_OF,TEST_TOOL_OF,DOCUMENTATION_OF,OPTIONAL_COMPONENT_OF,METAFILE_OF,PACKAGE_OF,AMENDS,PREREQUISITE_FOR,HAS_PREREQUISITE,OTHER")); IS_COMPONENT_VISIBILITY_RESTRICTION_ENABLED = Boolean.parseBoolean( System.getProperty("RunComponentVisibilityRestrictionTest", props.getProperty("component.visibility.restriction.enabled", "false"))); DISABLE_CLEARING_REQUEST_FOR_PROJECT_WITH_GROUPS = props.getProperty("org.eclipse.sw360.disable.clearing.request.for.project.group", ""); diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/Sw360Portlet.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/Sw360Portlet.java index dcbe519363..c199d8e9d5 100644 --- a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/Sw360Portlet.java +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/Sw360Portlet.java @@ -152,6 +152,27 @@ protected void renderRequestSummary(PortletRequest request, MimeResponse respons } } + protected void renderRequestPreparation(PortletRequest request, MimeResponse response, ImportBomRequestPreparation requestPreparation) { + JSONObject jsonObject = JSONFactoryUtil.createJSONObject(); + jsonObject.put(PortalConstants.RESULT, requestPreparation.requestStatus.toString()); + if (requestPreparation.isSetIsComponentDuplicate()) + jsonObject.put("isComponentDuplicate", requestPreparation.isComponentDuplicate); + if (requestPreparation.isSetIsReleaseDuplicate()) + jsonObject.put("isReleaseDuplicate", requestPreparation.isReleaseDuplicate); + if (requestPreparation.isSetName()) + jsonObject.put("name", requestPreparation.name); + if (requestPreparation.isSetVersion()) + jsonObject.put("version", requestPreparation.version); + if (requestPreparation.isSetMessage()) + jsonObject.put("message", requestPreparation.message); + + try { + writeJSON(request, response, jsonObject); + } catch (IOException e) { + log.error("Problem rendering RequestStatus", e); + } + } + protected void renderRequestStatus(PortletRequest request, MimeResponse response, RequestStatus requestStatus) { JSONObject jsonObject = JSONFactoryUtil.createJSONObject(); jsonObject.put(PortalConstants.RESULT, requestStatus.toString()); diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/components/ComponentPortlet.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/components/ComponentPortlet.java index 5de8a27343..89b483c0e2 100644 --- a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/components/ComponentPortlet.java +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/components/ComponentPortlet.java @@ -76,7 +76,6 @@ import org.apache.thrift.TSerializer; import org.osgi.service.component.annotations.ConfigurationPolicy; import org.apache.commons.lang.StringUtils; - import javax.portlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -105,22 +104,22 @@ import org.apache.thrift.transport.TTransportException; @org.osgi.service.component.annotations.Component( - immediate = true, - properties = { - "/org/eclipse/sw360/portal/portlets/base.properties", - "/org/eclipse/sw360/portal/portlets/default.properties" - }, - property = { - "javax.portlet.name=" + COMPONENT_PORTLET_NAME, - - "javax.portlet.display-name=Components", - "javax.portlet.info.short-title=Components", - "javax.portlet.info.title=Components", - "javax.portlet.resource-bundle=content.Language", - "javax.portlet.init-param.view-template=/html/components/view.jsp", - }, - service = Portlet.class, - configurationPolicy = ConfigurationPolicy.REQUIRE + immediate = true, + properties = { + "/org/eclipse/sw360/portal/portlets/base.properties", + "/org/eclipse/sw360/portal/portlets/default.properties" + }, + property = { + "javax.portlet.name=" + COMPONENT_PORTLET_NAME, + + "javax.portlet.display-name=Components", + "javax.portlet.info.short-title=Components", + "javax.portlet.info.title=Components", + "javax.portlet.resource-bundle=content.Language", + "javax.portlet.init-param.view-template=/html/components/view.jsp", + }, + service = Portlet.class, + configurationPolicy = ConfigurationPolicy.REQUIRE ) public class ComponentPortlet extends FossologyAwarePortlet { @@ -211,13 +210,13 @@ public void serveResource(ResourceRequest request, ResourceResponse response) th serveLinkedReleases(request, response); } else if (PortalConstants.PROJECT_SEARCH.equals(action)) { serveProjectSearch(request, response); - } else if (PortalConstants.UPDATE_VULNERABILITIES_RELEASE.equals(action)){ - updateVulnerabilitiesRelease(request,response); - } else if (PortalConstants.UPDATE_VULNERABILITIES_COMPONENT.equals(action)){ - updateVulnerabilitiesComponent(request,response); + } else if (PortalConstants.UPDATE_VULNERABILITIES_RELEASE.equals(action)) { + updateVulnerabilitiesRelease(request, response); + } else if (PortalConstants.UPDATE_VULNERABILITIES_COMPONENT.equals(action)) { + updateVulnerabilitiesComponent(request, response); } else if (PortalConstants.UPDATE_ALL_VULNERABILITIES.equals(action)) { updateAllVulnerabilities(request, response); - } else if (PortalConstants.UPDATE_VULNERABILITY_VERIFICATION.equals(action)){ + } else if (PortalConstants.UPDATE_VULNERABILITY_VERIFICATION.equals(action)) { updateVulnerabilityVerification(request, response); } else if (PortalConstants.EXPORT_TO_EXCEL.equals(action)) { exportExcel(request, response); @@ -233,10 +232,14 @@ public void serveResource(ResourceRequest request, ResourceResponse response) th loadAssessmentSummaryInfo(request, response); } else if (PortalConstants.WRITE_SPDX_LICENSE_INFO_INTO_RELEASE.equals(action)) { writeSpdxLicenseInfoIntoRelease(request, response); - } else if (PortalConstants.IMPORT_BOM.equals(action)) { + }else if (PortalConstants.IMPORT_BOM.equals(action)) { importBom(request, response); } else if (PortalConstants.LICENSE_TO_SOURCE_FILE.equals(action)) { serveLicenseToSourceFileMapping(request, response); + } else if (PortalConstants.IMPORT_BOM_AS_NEW.equals(action)) { + importBomAsNew(request, response); + } else if (PortalConstants.PREPARE_IMPORT_BOM.equals(action)) { + prepareImportBom(request, response); } else if (isGenericAction(action)) { dealWithGenericAction(request, response, action); } else if (PortalConstants.LOAD_CHANGE_LOGS.equals(action) || PortalConstants.VIEW_CHANGE_LOGS.equals(action)) { @@ -245,8 +248,6 @@ public void serveResource(ResourceRequest request, ResourceResponse response) th JSONObject dataForChangeLogs = changeLogsPortletUtilsPortletUtils.serveResourceForChangeLogs(request, response, action); writeJSON(request, response, dataForChangeLogs); - } else if (PortalConstants.EVALUATE_CLI_ATTACHMENTS.equals(action)) { - evaluateCLIAttachments(request, response); } } @@ -327,9 +328,10 @@ private void importBom(ResourceRequest request, ResourceResponse response) { final ComponentService.Iface componentClient = thriftClients.makeComponentClient(); User user = UserCacheHolder.getUserFromRequest(request); String attachmentContentId = request.getParameter(ATTACHMENT_CONTENT_ID); + String rdfFilePath = request.getParameter(RDF_FILE_PATH); try { - final RequestSummary requestSummary = componentClient.importBomFromAttachmentContent(user, attachmentContentId); + final RequestSummary requestSummary = componentClient.importBomFromAttachmentContent(user, attachmentContentId, null, null, rdfFilePath); LiferayPortletURL releaseUrl = createDetailLinkTemplate(request); releaseUrl.setParameter(PortalConstants.PAGENAME, PortalConstants.PAGENAME_RELEASE_DETAIL); @@ -344,6 +346,28 @@ private void importBom(ResourceRequest request, ResourceResponse response) { } } + private void importBomAsNew(ResourceRequest request, ResourceResponse response) { + final ComponentService.Iface componentClient = thriftClients.makeComponentClient(); + User user = UserCacheHolder.getUserFromRequest(request); + String attachmentContentId = request.getParameter(ATTACHMENT_CONTENT_ID); + String newReleaseVersion = request.getParameter(NEW_RELEASE_VERSION); + String rdfFilePath = request.getParameter(RDF_FILE_PATH); + + try { + final RequestSummary requestSummary = componentClient.importBomFromAttachmentContent(user, attachmentContentId, newReleaseVersion, null, rdfFilePath); + + LiferayPortletURL releaseUrl = createDetailLinkTemplate(request); + releaseUrl.setParameter(PortalConstants.PAGENAME, PortalConstants.PAGENAME_RELEASE_DETAIL); + releaseUrl.setParameter(RELEASE_ID, requestSummary.getMessage()); + JSONObject jsonObject = JSONFactoryUtil.createJSONObject(); + jsonObject.put("redirectUrl", releaseUrl.toString()); + + renderRequestSummary(request, response, requestSummary, jsonObject); + } catch (TException e) { + log.error("Failed to import BOM.", e); + response.setProperty(ResourceResponse.HTTP_STATUS_CODE, Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); + } + } @Override protected void dealWithFossologyAction(ResourceRequest request, ResourceResponse response, String action) throws IOException, PortletException { @@ -414,6 +438,19 @@ private void serveAddVendor(ResourceRequest request, ResourceResponse response) } } + private void prepareImportBom(ResourceRequest request, ResourceResponse response) { + final ComponentService.Iface componentClient = thriftClients.makeComponentClient(); + User user = UserCacheHolder.getUserFromRequest(request); + String attachmentContentId = request.getParameter(ATTACHMENT_CONTENT_ID); + try { + final ImportBomRequestPreparation importBomRequestPreparation = componentClient.prepareImportBom(user, attachmentContentId); + renderRequestPreparation(request, response, importBomRequestPreparation); + } catch (TException e) { + log.error("Failed to import BOM.", e); + response.setProperty(ResourceResponse.HTTP_STATUS_CODE, Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); + } + } + private void serveCheckComponentName(ResourceRequest request, ResourceResponse response) throws IOException { List resultComponents = new ArrayList<>(); List errors = new ArrayList<>(); @@ -461,7 +498,7 @@ private void serveCheckComponentName(ResourceRequest request, ResourceResponse r } private void respondSimilarComponentsResponseJson(ResourceRequest request, ResourceResponse response, - List similarComponents, List errors) throws IOException { + List similarComponents, List errors) throws IOException { response.setContentType(ContentTypes.APPLICATION_JSON); JsonGenerator jsonGenerator = JSON_FACTORY.createGenerator(response.getWriter()); @@ -737,19 +774,25 @@ private void loadSpdxLicenseInfo(ResourceRequest request, ResourceResponse respo JsonGenerator jsonGenerator = JSON_FACTORY.createGenerator(response.getWriter()); jsonGenerator.writeStartObject(); if (concludedLicenseIds.size() > 0) { - jsonGenerator.writeStringField(LICENSE_PREFIX, LanguageUtil.get(resourceBundle,"concluded.license.ids")); + jsonGenerator.writeStringField(LICENSE_PREFIX, LanguageUtil.get(resourceBundle, "concluded.license.ids")); jsonGenerator.writeArrayFieldStart(LICENSE_IDS); - concludedLicenseIds.forEach(licenseId -> wrapException(() -> { jsonGenerator.writeString(licenseId); })); + concludedLicenseIds.forEach(licenseId -> wrapException(() -> { + jsonGenerator.writeString(licenseId); + })); jsonGenerator.writeEndArray(); } else if (CommonUtils.isNotEmpty(mainLicenseNames)) { - jsonGenerator.writeStringField(LICENSE_PREFIX, LanguageUtil.get(resourceBundle,"main.license.id")); + jsonGenerator.writeStringField(LICENSE_PREFIX, LanguageUtil.get(resourceBundle, "main.license.id")); jsonGenerator.writeArrayFieldStart(LICENSE_IDS); - mainLicenseNames.forEach(licenseId -> wrapException(() -> { jsonGenerator.writeString(licenseId); })); + mainLicenseNames.forEach(licenseId -> wrapException(() -> { + jsonGenerator.writeString(licenseId); + })); jsonGenerator.writeEndArray(); } jsonGenerator.writeStringField("otherLicense", LanguageUtil.get(resourceBundle,"other.license.ids")); jsonGenerator.writeArrayFieldStart("otherLicenseIds"); - otherLicenseNames.forEach(licenseId -> wrapException(() -> { jsonGenerator.writeString(licenseId); })); + otherLicenseNames.forEach(licenseId -> wrapException(() -> { + jsonGenerator.writeString(licenseId); + })); jsonGenerator.writeEndArray(); if (AttachmentType.INITIAL_SCAN_REPORT.equals(attachmentType)) { jsonGenerator.writeStringField(LICENSE_PREFIX, LanguageUtil.get(resourceBundle, "possible.main.license.ids")); @@ -819,6 +862,7 @@ private void loadAssessmentSummaryInfo(ResourceRequest request, ResourceResponse private void writeSpdxLicenseInfoIntoRelease(ResourceRequest request, ResourceResponse response) { User user = UserCacheHolder.getUserFromRequest(request); String releaseId = request.getParameter(PortalConstants.RELEASE_ID); + String attachmentContentId = request.getParameter(PortalConstants.ATTACHMENT_ID); ComponentService.Iface componentClient = thriftClients.makeComponentClient(); RequestStatus result = null; @@ -846,6 +890,7 @@ private void writeSpdxLicenseInfoIntoRelease(ResourceRequest request, ResourceRe } } result = componentClient.updateRelease(release, user); + componentClient.importBomFromAttachmentContent(user, attachmentContentId, null, releaseId, null); } catch (TException | IOException e) { log.error("Cannot write license info into release " + releaseId + ".", e); response.setProperty(ResourceResponse.HTTP_STATUS_CODE, "500"); @@ -942,7 +987,7 @@ private void prepareComponentEdit(RenderRequest request) { PortletUtils.setCustomFieldsEdit(request, user, component); setUsingDocs(request, user, null, component.getReleaseIds()); setAttachmentsInRequest(request, component); - SessionMessages.add(request, "request_processed", LanguageUtil.get(resourceBundle,"new.component")); + SessionMessages.add(request, "request_processed", LanguageUtil.get(resourceBundle, "new.component")); } } } @@ -955,7 +1000,6 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) final User user = UserCacheHolder.getUserFromRequest(request); request.setAttribute(DOCUMENT_TYPE, SW360Constants.TYPE_RELEASE); request.setAttribute(IS_USER_AT_LEAST_CLEARING_ADMIN, PermissionUtils.isUserAtLeast(UserGroup.CLEARING_ADMIN, user)); - if (isNullOrEmpty(id) && isNullOrEmpty(releaseId)) { throw new PortletException("Component or Release ID not set!"); } @@ -964,7 +1008,6 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) ComponentService.Iface client = thriftClients.makeComponentClient(); Component component; Release release; - if (!isNullOrEmpty(releaseId)) { release = client.getAccessibleReleaseByIdForEdit(releaseId, user); Map sortedAdditionalData = getSortedMap(release.getAdditionalData(), true); @@ -983,11 +1026,10 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) id = release.getComponentId(); } component = client.getAccessibleComponentById(id, user); - } else { component = client.getAccessibleComponentById(id, user); release = (Release) request.getAttribute(RELEASE); - if(release == null) { + if (release == null) { release = new Release(); release.setComponentId(id); release.setClearingState(ClearingState.NEW_CLEARING); @@ -997,7 +1039,7 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) putDirectlyLinkedReleaseRelationsWithAccessibilityInRequest(request, release, user); setAttachmentsInRequest(request, release); setUsingDocs(request, null, user, client); - SessionMessages.add(request, "request_processed", LanguageUtil.get(resourceBundle,"new.license")); + SessionMessages.add(request, "request_processed", LanguageUtil.get(resourceBundle, "new.license")); } } @@ -1021,7 +1063,7 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) request.setAttribute(COMPONENT, component); request.setAttribute(IS_USER_AT_LEAST_ECC_ADMIN, PermissionUtils.isUserAtLeast(UserGroup.ECC_ADMIN, user) || PermissionUtils.isUserAtLeastDesiredRoleInSecondaryGroup(UserGroup.ECC_ADMIN, allSecRoles) ? "Yes" : "No"); - + } catch (TException e) { if (e instanceof SW360Exception) { SW360Exception sw360Exp = (SW360Exception)e; @@ -1172,7 +1214,7 @@ private void generateComponentMergeWizardStep0Response(ActionRequest request, Js jsonGenerator.writeStartObject(); jsonGenerator.writeArrayFieldStart("components"); - componentSummary.stream().filter( component -> !component.getId().equals(srcId)).forEach(component -> { + componentSummary.stream().filter(component -> !component.getId().equals(srcId)).forEach(component -> { try { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("id", component.getId()); @@ -1216,7 +1258,7 @@ private void generateComponentMergeWizardStep2Response(ActionRequest request, Js jsonGenerator.writeStartObject(); // adding common title - jsonGenerator.writeRaw("\""+ COMPONENT_SELECTION +"\":" + JSON_THRIFT_SERIALIZER.toString(componentSelection) + ","); + jsonGenerator.writeRaw("\"" + COMPONENT_SELECTION + "\":" + JSON_THRIFT_SERIALIZER.toString(componentSelection) + ","); jsonGenerator.writeStringField(COMPONENT_SOURCE_ID, componentSourceId); jsonGenerator.writeEndObject(); @@ -1242,7 +1284,7 @@ private void generateComponentMergeWizardStep3Response(ActionRequest request, Js // write response JSON jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("redirectUrl", componentUrl.toString()); - if (status == RequestStatus.IN_USE){ + if (status == RequestStatus.IN_USE) { jsonGenerator.writeStringField("error", "Cannot merge when one of the components has an active moderation request."); } else if (status == RequestStatus.ACCESS_DENIED) { jsonGenerator.writeStringField("error", "You do not have sufficient permissions."); @@ -1350,11 +1392,11 @@ private void generateReleaseMergeWizardStep0Response(ActionRequest request, Json ComponentService.Iface cClient = thriftClients.makeComponentClient(); List releases = cClient.getReleasesByComponentId(componentId, sessionUser); - + jsonGenerator.writeStartObject(); jsonGenerator.writeArrayFieldStart("releases"); - releases.stream().filter( release -> !release.getId().equals(targetId) ).forEach(release -> { + releases.stream().filter(release -> !release.getId().equals(targetId)).forEach(release -> { try { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("id", release.getId()); @@ -1384,15 +1426,15 @@ private void generateReleaseMergeWizardStep1Response(ActionRequest request, Json boolean matchingPair = false; boolean foundSourceAttachments = false; Set attachmentHashes = new HashSet<>(); - for(Attachment attachment : nullToEmptySet(releaseTarget.getAttachments())) { - if(attachment.getAttachmentType().equals(AttachmentType.SOURCE) || attachment.getAttachmentType().equals(AttachmentType.SOURCE_SELF)) { + for (Attachment attachment : nullToEmptySet(releaseTarget.getAttachments())) { + if (attachment.getAttachmentType().equals(AttachmentType.SOURCE) || attachment.getAttachmentType().equals(AttachmentType.SOURCE_SELF)) { attachmentHashes.add(attachment.getSha1()); foundSourceAttachments = true; } } - for(Attachment attachment : nullToEmptySet(releaseSource.getAttachments())) { - if(attachment.getAttachmentType().equals(AttachmentType.SOURCE) || attachment.getAttachmentType().equals(AttachmentType.SOURCE_SELF)) { - if(attachmentHashes.contains(attachment.getSha1())) { + for (Attachment attachment : nullToEmptySet(releaseSource.getAttachments())) { + if (attachment.getAttachmentType().equals(AttachmentType.SOURCE) || attachment.getAttachmentType().equals(AttachmentType.SOURCE_SELF)) { + if (attachmentHashes.contains(attachment.getSha1())) { matchingPair = true; break; } @@ -1400,7 +1442,7 @@ private void generateReleaseMergeWizardStep1Response(ActionRequest request, Json } } - if(foundSourceAttachments && !matchingPair) { + if (foundSourceAttachments && !matchingPair) { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("error", "Both releases must have at least one pair of same source attachments or no source attachments at all. Otherwise a merge is not possible."); jsonGenerator.writeEndObject(); @@ -1408,17 +1450,17 @@ private void generateReleaseMergeWizardStep1Response(ActionRequest request, Json } Map> displayInformation = new HashMap<>(); - + addToMap(displayInformation, "mainlineState", releaseTarget.getMainlineState()); addToMap(displayInformation, "mainlineState", releaseSource.getMainlineState()); addToMap(displayInformation, "repositorytype", releaseTarget.getRepository() != null ? releaseTarget.getRepository().getRepositorytype() : null); addToMap(displayInformation, "repositorytype", releaseSource.getRepository() != null ? releaseSource.getRepository().getRepositorytype() : null); addToMap(displayInformation, "eccStatus", releaseTarget.getEccInformation().getEccStatus()); addToMap(displayInformation, "eccStatus", releaseSource.getEccInformation().getEccStatus()); - for(Attachment attachment : nullToEmptySet(releaseSource.getAttachments())) { + for (Attachment attachment : nullToEmptySet(releaseSource.getAttachments())) { addToMap(displayInformation, "attachmentType", attachment.getAttachmentType()); } - for(Attachment attachment : nullToEmptySet(releaseTarget.getAttachments())) { + for (Attachment attachment : nullToEmptySet(releaseTarget.getAttachments())) { addToMap(displayInformation, "attachmentType", attachment.getAttachmentType()); } @@ -1427,11 +1469,11 @@ private void generateReleaseMergeWizardStep1Response(ActionRequest request, Json releaseIds.addAll(nullToEmptyMap(releaseTarget.getReleaseIdToRelationship()).keySet()); List releases = cClient.getReleasesById(releaseIds, sessionUser); Map releaseToNameMap = new HashMap(); - for(Release release : releases) { + for (Release release : releases) { releaseToNameMap.put(release.getId(), release.getName() + " (" + release.getVersion() + ")"); } displayInformation.put("release", releaseToNameMap); - + jsonGenerator.writeStartObject(); // adding common title @@ -1445,7 +1487,7 @@ private void generateReleaseMergeWizardStep1Response(ActionRequest request, Json private void addToMap(Map> map, String key, TEnum value) { Map subMap = map.getOrDefault(key, new HashMap()); - if(value != null) { + if (value != null) { subMap.put(value.getValue() + "", ThriftEnumUtils.enumToString(value)); } map.put(key, subMap); @@ -1471,7 +1513,7 @@ private Map getUsageInformationForReleaseMerge(String releaseSo usageInformation.put("releaseVulnerabilities", releaseVulnerabilities.size()); List projectRatings = vulnerabilityClient.getProjectVulnerabilityRatingsByReleaseId(releaseSourceId, sessionUser); usageInformation.put("projectRatings", projectRatings.size()); - + return usageInformation; } @@ -1485,7 +1527,7 @@ private void generateReleaseMergeWizardStep2Response(ActionRequest request, Json jsonGenerator.writeStartObject(); // adding common title - jsonGenerator.writeRaw("\""+ RELEASE_SELECTION +"\":" + JSON_THRIFT_SERIALIZER.toString(releaseSelection) + ","); + jsonGenerator.writeRaw("\"" + RELEASE_SELECTION + "\":" + JSON_THRIFT_SERIALIZER.toString(releaseSelection) + ","); jsonGenerator.writeStringField(RELEASE_SOURCE_ID, releaseSourceId); jsonGenerator.writeEndObject(); @@ -1512,7 +1554,7 @@ private void generateReleaseMergeWizardStep3Response(ActionRequest request, Json // write response JSON jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("redirectUrl", releaseUrl.toString()); - if (status == RequestStatus.IN_USE){ + if (status == RequestStatus.IN_USE) { jsonGenerator.writeStringField("error", "Cannot merge when one of the releases has an active moderation request."); } else if (status == RequestStatus.ACCESS_DENIED) { jsonGenerator.writeStringField("error", "You do not have sufficient permissions."); @@ -1650,7 +1692,7 @@ private void prepareReleaseDetailView(RenderRequest request, RenderResponse resp } Map permissions = release.getPermissions(); - + request.setAttribute(PortalConstants.WRITE_ACCESS_USER, permissions.get(RequestedAction.WRITE)); if (isNullOrEmpty(id)) { id = release.getComponentId(); @@ -1690,7 +1732,7 @@ private void prepareReleaseDetailView(RenderRequest request, RenderResponse resp } private String createFossologyJobViewLink(ExternalToolProcessStep processStep, - Map> configKeyToValues, String fossologyJobsViewLink) { + Map> configKeyToValues, String fossologyJobsViewLink) { String uploadId = null; if (processStep != null) { uploadId = processStep.getResult(); @@ -1704,7 +1746,7 @@ private String createFossologyJobViewLink(ExternalToolProcessStep processStep, URI fossologyRestURI = new URI(url); fossologyHostName = fossologyRestURI.getHost(); fossologyPath = fossologyRestURI.getPath(); - fossologyPath = fossologyPath.substring(0,fossologyPath.indexOf("/api/v")); + fossologyPath = fossologyPath.substring(0, fossologyPath.indexOf("/api/v")); protocol = fossologyRestURI.getScheme(); int port = fossologyRestURI.getPort(); portStr = port == -1 ? StringUtils.EMPTY : ":" + port; @@ -1738,7 +1780,7 @@ private void setSpdxAttachmentsInRequest(RenderRequest request, Release release) request.setAttribute(PortalConstants.SPDX_ATTACHMENTS, spdxAttachments); } - private String formatedMessageForVul(List infoHistory){ + private String formatedMessageForVul(List infoHistory) { return CommonVulnerabilityPortletUtils.formatedMessageForVul(infoHistory, e -> e.getVerificationState().name(), e -> e.getCheckedOn(), @@ -1759,7 +1801,7 @@ private void putVulnerabilitiesInRequestRelease(RenderRequest request, String re putVulnerabilitiesInRequest(request, vuls, user); } - private void putVulnerabilitiesInRequestComponent(RenderRequest request, String componentId, User user, boolean isVulEditable) throws TException{ + private void putVulnerabilitiesInRequestComponent(RenderRequest request, String componentId, User user, boolean isVulEditable) throws TException { VulnerabilityService.Iface vulClient = thriftClients.makeVulnerabilityClient(); List vuls; if (isVulEditable) { @@ -1779,14 +1821,14 @@ private void putVulnerabilitiesInRequest(RenderRequest request, List> vulnerabilityVerifications, Map> vulnerabilityTooltips, - VulnerabilityDTO vulnerability){ + VulnerabilityDTO vulnerability) { String vulnerabilityId = vulnerability.getExternalId(); String releaseId = vulnerability.getIntReleaseId(); Map vulnerabilityVerification = vulnerabilityVerifications.computeIfAbsent(vulnerabilityId, k -> new HashMap<>()); Map vulnerabilityTooltip = vulnerabilityTooltips.computeIfAbsent(vulnerabilityId, k -> new HashMap<>()); ReleaseVulnerabilityRelation relation = vulnerability.getReleaseVulnerabilityRelation(); - if (! relation.isSetVerificationStateInfo()) { + if (!relation.isSetVerificationStateInfo()) { vulnerabilityVerification.put(releaseId, VerificationState.NOT_CHECKED); vulnerabilityTooltip.put(releaseId, "Not checked yet."); } else { @@ -1805,7 +1847,7 @@ private void putVulnerabilityMetadatasInRequest(RenderRequest request, List ! VerificationState.INCORRECT.equals(getVerificationState(vul))) + .filter(vul -> !VerificationState.INCORRECT.equals(getVerificationState(vul))) .map(VulnerabilityDTO::getExternalId) .collect(Collectors.toSet()) .size(); @@ -1823,8 +1865,8 @@ private void putVulnerabilityMetadatasInRequest(RenderRequest request, List> getComponentFilterMap(PortletRequest request) { String query = new StringBuilder("[%s ").append(PortalConstants.TO).append(" %s]").toString(); DateRange range = ThriftEnumUtils.stringToEnum(dateRange, DateRange.class); switch (range) { - case EQUAL: - break; - case LESS_THAN_OR_EQUAL_TO: - parameter = String.format(query, PortalConstants.EPOCH_DATE, parameter); - break; - case GREATER_THAN_OR_EQUAL_TO: - parameter = String.format(query, parameter, upperLimit); - break; - case BETWEEN: - String endDate = request.getParameter(PortalConstants.END_DATE); - if (isNullEmptyOrWhitespace(endDate)) { - endDate = upperLimit; - } - parameter = String.format(query, parameter, endDate); - break; + case EQUAL: + break; + case LESS_THAN_OR_EQUAL_TO: + parameter = String.format(query, PortalConstants.EPOCH_DATE, parameter); + break; + case GREATER_THAN_OR_EQUAL_TO: + parameter = String.format(query, parameter, upperLimit); + break; + case BETWEEN: + String endDate = request.getParameter(PortalConstants.END_DATE); + if (isNullEmptyOrWhitespace(endDate)) { + endDate = upperLimit; + } + parameter = String.format(query, parameter, endDate); + break; } } Set values = CommonUtils.splitToSet(parameter); @@ -1983,7 +2025,7 @@ public void updateComponent(ActionRequest request, ActionResponse response) thro setSessionMessage(request, requestStatus, "Component", "update", component.getName()); if (RequestStatus.DUPLICATE.equals(requestStatus) || RequestStatus.DUPLICATE_ATTACHMENT.equals(requestStatus) || RequestStatus.NAMINGERROR.equals(requestStatus)) { - if(RequestStatus.DUPLICATE.equals(requestStatus)) + if (RequestStatus.DUPLICATE.equals(requestStatus)) setSW360SessionError(request, ErrorMessages.COMPONENT_DUPLICATE); else if (RequestStatus.NAMINGERROR.equals(requestStatus)) setSW360SessionError(request, ErrorMessages.COMPONENT_NAMING_ERROR); @@ -2007,7 +2049,7 @@ else if (RequestStatus.NAMINGERROR.equals(requestStatus)) AddDocumentRequestSummary summary = client.addComponent(component, user); AddDocumentRequestStatus status = summary.getRequestStatus(); - switch(status){ + switch (status) { case SUCCESS: String successMsg = "Component " + component.getName() + " added successfully"; SessionMessages.add(request, "request_processed", successMsg); @@ -2076,7 +2118,7 @@ public void updateRelease(ActionRequest request, ActionResponse response) throws setSessionMessage(request, requestStatus, "Release", "update", printName(release)); if (RequestStatus.DUPLICATE.equals(requestStatus) || RequestStatus.DUPLICATE_ATTACHMENT.equals(requestStatus) || RequestStatus.NAMINGERROR.equals(requestStatus)) { - if(RequestStatus.DUPLICATE.equals(requestStatus)) + if (RequestStatus.DUPLICATE.equals(requestStatus)) setSW360SessionError(request, ErrorMessages.RELEASE_DUPLICATE); else if (RequestStatus.NAMINGERROR.equals(requestStatus)) setSW360SessionError(request, ErrorMessages.RELEASE_NAME_VERSION_ERROR); @@ -2124,7 +2166,7 @@ else if (RequestStatus.NAMINGERROR.equals(requestStatus)) AddDocumentRequestSummary summary = client.addRelease(release, user); AddDocumentRequestStatus status = summary.getRequestStatus(); - switch(status){ + switch (status) { case SUCCESS: response.setRenderParameter(RELEASE_ID, summary.getId()); String successMsg = "Release " + printName(release) + " added successfully"; @@ -2165,7 +2207,7 @@ private void prepareRequestForReleaseEditAfterDuplicateError(ActionRequest reque } private void fillVendor(Release release) throws TException { - if(!isNullOrEmpty(release.getVendorId()) && release.isSetVendorId()) { + if (!isNullOrEmpty(release.getVendorId()) && release.isSetVendorId()) { VendorService.Iface client = thriftClients.makeVendorClient(); Vendor vendor = client.getByID(release.getVendorId()); release.setVendor(vendor); @@ -2212,7 +2254,7 @@ private void updateVulnerabilitiesRelease(ResourceRequest request, ResourceRespo JSONObject responseData = PortletUtils.importStatusToJSON(importStatus); PrintWriter writer = response.getWriter(); writer.write(responseData.toString()); - } catch (TException e){ + } catch (TException e) { log.error("Error updating CVEs for release in backend.", e); } } diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/moderation/ModerationPortlet.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/moderation/ModerationPortlet.java index 9cd2cc0279..3d6ea364ef 100644 --- a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/moderation/ModerationPortlet.java +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/moderation/ModerationPortlet.java @@ -599,7 +599,6 @@ private void acceptModerationRequest(User user, User requestingUser, ModerationR case USER: { UserUtils.activateLiferayUser(request, moderationRequest.getUser()); } - break; } } diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/projects/ProjectPortlet.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/projects/ProjectPortlet.java index a99f2dbca4..cf9611ee24 100644 --- a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/projects/ProjectPortlet.java +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/portlets/projects/ProjectPortlet.java @@ -2691,8 +2691,6 @@ private Map setLicenseInfoWithObligations(PortletR obligationStatusMap = licenseObligation.getObligationStatusMap(); request.setAttribute(APPROVED_OBLIGATIONS_COUNT, getFulfilledObligationsCount(obligationStatusMap)); - request.setAttribute(OBLIGATION_FROM_README_OSS, getObligationsFromReadmeOSSCount(obligationStatusMap)); - request.setAttribute(EXCLUDED_RELEASES, excludedReleases); request.setAttribute(PROJECT_OBLIGATIONS_INFO_BY_RELEASE, filterAndSortLicenseInfo(licenseObligation.getLicenseInfoResults())); } catch (TException e) { @@ -2735,17 +2733,8 @@ private List filterAndSortLicenseInfo(List obligationStatusMap) { if (CommonUtils.isNotEmpty(obligationStatusMap.keySet())) { - return Math.toIntExact( - obligationStatusMap.values().stream().filter(obligation -> obligation.getStatus() != null - && !ObligationStatus.OPEN.equals(obligation.getStatus())).count()); - } - return 0; - } - - private int getObligationsFromReadmeOSSCount(Map obligationStatusMap) { - if (CommonUtils.isNotEmpty(obligationStatusMap.keySet())) { - return Math.toIntExact( - obligationStatusMap.values().stream().filter(obligation -> obligation.getObligationLevel() == null).count()); + return Math.toIntExact(obligationStatusMap.values().stream() + .filter(obligation -> ObligationStatus.ACKNOWLEDGED_OR_FULFILLED.equals(obligation.getStatus())).count()); } return 0; } diff --git a/frontend/sw360-portlet/src/main/resources/META-INF/customTags.tld b/frontend/sw360-portlet/src/main/resources/META-INF/customTags.tld index 7d686cb68c..6d80ae738e 100644 --- a/frontend/sw360-portlet/src/main/resources/META-INF/customTags.tld +++ b/frontend/sw360-portlet/src/main/resources/META-INF/customTags.tld @@ -1217,6 +1217,12 @@ java.lang.Boolean true + + hashSet + false + java.lang.Boolean + true + maxChar false @@ -1390,6 +1396,7 @@ printUserName org.eclipse.sw360.datahandler.common.SW360Utils + org.eclipse.sw360.datahandler.common.SW360Utils java.lang.String printName(org.eclipse.sw360.datahandler.thrift.users.User) diff --git a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/changelogs/elementView.jsp b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/changelogs/elementView.jsp index 284cdf4fbd..313eec77ea 100644 --- a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/changelogs/elementView.jsp +++ b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/changelogs/elementView.jsp @@ -251,6 +251,8 @@ if(fieldValueOld === null || fieldValueOld === undefined || fieldValueNew === null || fieldValueNew === undefined ) { + removeIndexFields(fieldValueOld); + removeIndexFields(fieldValueNew); jsonStrOld = JSON.stringify(fieldValueOld, undefined, 5).replace(/\\n/g, '\n').replace(/\\r/g, '\r'); jsonStrNew = JSON.stringify(fieldValueNew, undefined, 5).replace(/\\n/g, '\n').replace(/\\r/g, '\r'); } @@ -310,10 +312,13 @@ for (let primaryValue of primaryField) { if(typeof primaryValue === 'object') { let matched = false; + let indexKey = "index"; for(let secondaryValue of secondaryField) { - if(secondaryValue[selector] === primaryValue[selector]) { + if (isEqualObject(secondaryValue, primaryValue, selector, indexKey)) { matched = true; if(differentiateObject) { + delete primaryValue[indexKey]; + delete secondaryValue[indexKey]; diffObject(primaryValue, secondaryValue, primarySpanHightlighter, secondarySpanHighlighter, indentlevel); primaryFieldTmp.push(primaryValue); secondaryFieldTmp.push(secondaryValue); @@ -322,7 +327,8 @@ } } if(!matched) { - let jsonString = JSON.stringify(primaryValue, undefined, 5*indentlevel); + removeIndexFields(primaryValue); + let jsonString = JSON.stringify(primaryValue, undefined, 10*indentlevel); jsonString = jsonString.substring(0, jsonString.length-1) + spaceForClosingBraces + jsonString.substring(jsonString.length-1); primaryFieldTmp.push($($.parseHTML(primarySpanHightlighter)).text(jsonString)[0].outerHTML); } @@ -336,6 +342,33 @@ } } + function isEqualObject(secondaryValue, primaryValue, selector, indexKey) { + if (primaryValue[selector] === secondaryValue[selector] && typeof primaryValue[indexKey] === 'undefined') { + return true; + } + if (primaryValue[indexKey] === secondaryValue[indexKey] && typeof primaryValue[selector] === 'undefined') { + return true; + } + return false; + } + + function removeIndexFields(object) { + if (Array.isArray(object)) { + for (let objectValue of object) { + removeIndexFields(objectValue); + } + } else if (typeof object === 'object') { + for (key in object) { + if (key === 'index') { + delete object[key]; + } + if (typeof object[key] === 'object') { + removeIndexFields(object[key]); + } + } + } + } + function copyFromSourceToDestinationArray(srcArr, destArr) { destArr.length = 0; for (obj of srcArr) { @@ -354,6 +387,11 @@ function highlightObject(fieldValuePrimary, fieldValueSecondary, primarySpanHightlighter, secondarySpanHighlighter, differentiateCommonObject, spaceForClosingBraces, indentlevel) { for(key in fieldValuePrimary) { + if (key === 'index') { + delete fieldValuePrimary[key]; + delete fieldValueSecondary[key]; + continue; + } if(fieldValueSecondary[key] === null || fieldValueSecondary[key] === undefined) { let highlighted = fieldValuePrimary[key]; if(typeof fieldValuePrimary[key] === 'object') { diff --git a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/edit.jsp b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/edit.jsp index 0aa0a72a30..a889a22959 100644 --- a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/edit.jsp +++ b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/edit.jsp @@ -152,6 +152,7 @@ + <%@include file="/html/utils/includes/importBomForComponent.jspf" %>
active show"> @@ -208,7 +209,6 @@ <%@include file="/html/components/includes/vendors/searchVendor.jspf" %> - diff --git a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/utils/includes/usingProjectsTable.jspf b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/utils/includes/usingProjectsTable.jspf index 055175035a..9cc0052d5a 100644 --- a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/utils/includes/usingProjectsTable.jspf +++ b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/utils/includes/usingProjectsTable.jspf @@ -15,7 +15,7 @@ (${usingProjects.size()} visible / ${allUsingProjectsCount - usingProjects.size()} restricted) projects.
- +
@@ -44,7 +44,7 @@ ]); - datatables.create('#usingProjectsTable', { + datatables.create('#${tableId}', { data: result, lengthChange: false, language: { diff --git a/frontend/sw360-portlet/src/main/resources/content/Language.properties b/frontend/sw360-portlet/src/main/resources/content/Language.properties index 0001d9164d..89c57ab528 100644 --- a/frontend/sw360-portlet/src/main/resources/content/Language.properties +++ b/frontend/sw360-portlet/src/main/resources/content/Language.properties @@ -673,7 +673,7 @@ import=Import import.export=Import & Export import.failed=Import failed. import.projects=Import Projects -import.spdx.bom=Import SPDX BOM +import.spdx.bom=Import SBOM import.spdx.information=Import SPDX Information import.spdx.licenses=Import SPDX licenses incorrect=Incorrect @@ -1523,6 +1523,7 @@ object=Object import.obligation.element=Import Obligation Element input=Input an.obligation.with.the.same.name.already.exists=An Obligation with the same name already exists. +## spdx multi language obligation.change.log.is.unavailable.because.obligation.does.not.exist=Obligation Change Log is unavailable because Obligation does not exist. excel.report.generation.has.started.we.will.send.you.an.email.with.download.link.once.completed=Excel report generation has started. We will send you an email with download link once completed. ## Refer to http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/ and add your datatables language diff --git a/frontend/sw360-portlet/src/main/resources/content/Language_ja.properties b/frontend/sw360-portlet/src/main/resources/content/Language_ja.properties index 12a58c6075..42728f45e7 100644 --- a/frontend/sw360-portlet/src/main/resources/content/Language_ja.properties +++ b/frontend/sw360-portlet/src/main/resources/content/Language_ja.properties @@ -673,7 +673,7 @@ import=インポート import.export=インポート& エクスポート import.failed=インポートに失敗しました。 import.projects=プロジェクトのインポート -import.spdx.bom=SPDX BOMのインポート +import.spdx.bom=SBOMのインポート import.spdx.information=SPDX情報のインポート import.spdx.licenses=SPDXライセンスのインポート incorrect=間違い diff --git a/frontend/sw360-portlet/src/main/resources/content/Language_vi.properties b/frontend/sw360-portlet/src/main/resources/content/Language_vi.properties index 3040a91335..e3a843bb98 100644 --- a/frontend/sw360-portlet/src/main/resources/content/Language_vi.properties +++ b/frontend/sw360-portlet/src/main/resources/content/Language_vi.properties @@ -677,7 +677,7 @@ import=Nhập import.export=Nhập và xuất import.failed=Nhập thất bại. import.projects=Nhập các dự án -import.spdx.bom=Nhập SPDX BOM +import.spdx.bom=Nhập SBOM import.spdx.information=Nhập thông tin SPDX import.spdx.licenses=Nhập giấy phép SPDX incorrect=Sai @@ -1529,6 +1529,10 @@ import.obligation.element=Nhập nghĩa vụ thành phần input=Nhập an.obligation.with.the.same.name.already.exists=Nghĩa vụ có cùng tên đã tồn tại. obligation.change.log.is.unavailable.because.obligation.does.not.exist=Không xem được lịch sử thay đổi vì Obligation này không tồn tại. +excel.report.generation.has.started.we.will.send.you.an.email.with.download.link.once.completed=Excel report generation has started. We will send you an email with download link once completed. +obligation.change.log.is.unavailable.because.obligation.does.not.exist=Không xem được lịch sử thay đổi vì Obligation này không tồn tại. + + excel.report.generation.has.started.we.will.send.you.an.email.with.download.link.once.completed=Excel report generation has started. We will send you an email with download link once completed. ## Refer to http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/ and add your datatables language diff --git a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/common/Moderator.java b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/common/Moderator.java index 8372a812ae..6d9c9bd321 100644 --- a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/common/Moderator.java +++ b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/common/Moderator.java @@ -17,7 +17,6 @@ import org.eclipse.sw360.datahandler.thrift.ThriftClients; import org.eclipse.sw360.datahandler.thrift.attachments.Attachment; import org.eclipse.sw360.datahandler.thrift.attachments.AttachmentContent; -import org.eclipse.sw360.datahandler.thrift.components.Release; import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; import org.eclipse.sw360.datahandler.thrift.moderation.ModerationService; import org.apache.logging.log4j.LogManager; @@ -84,10 +83,6 @@ protected T updateBasicField(U field, FieldMetaData fieldMetaData, T document, T case TType.STRING: case TType.ENUM: - if (document instanceof Release && ((field == Release._Fields.NAME || field == Release._Fields.VERSION) - && "Dummy_Value".equals(documentAdditions.getFieldValue(field)))) { - break; - } document.setFieldValue(field, documentAdditions.getFieldValue(field)); break; case TType.I32: diff --git a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/common/ThriftEnumUtils.java b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/common/ThriftEnumUtils.java index a118a18a64..0e5fbe550d 100644 --- a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/common/ThriftEnumUtils.java +++ b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/common/ThriftEnumUtils.java @@ -113,6 +113,7 @@ private ThriftEnumUtils() { .put(AttachmentType.README_OSS, "ReadMe OSS") .put(AttachmentType.OTHER, "Other") .put(AttachmentType.SECURITY_ASSESSMENT, "Security Assessment") + .put(AttachmentType.SBOM, "SBOM") .put(AttachmentType.INITIAL_SCAN_REPORT, "Initial Scan Report") .build(); @@ -138,6 +139,7 @@ private ThriftEnumUtils() { .put(AttachmentType.README_OSS, "RDM") .put(AttachmentType.OTHER, "OTH") .put(AttachmentType.SECURITY_ASSESSMENT, "SECA") + .put(AttachmentType.SBOM, "SBOM") .put(AttachmentType.INITIAL_SCAN_REPORT, "ISR") .build(); diff --git a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/couchdb/DatabaseMixInForChangeLog.java b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/couchdb/DatabaseMixInForChangeLog.java index 8fafe839bb..3e7d976dd2 100644 --- a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/couchdb/DatabaseMixInForChangeLog.java +++ b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/couchdb/DatabaseMixInForChangeLog.java @@ -239,11 +239,12 @@ public static abstract class ProjectProjectRelationshipMixin extends ProjectProj @JsonInclude(JsonInclude.Include.NON_NULL) @JsonIgnoreProperties({ - "node", - "distribution", - "development", - "obligationType" + "node", + "distribution", + "development", + "obligationType" }) public static abstract class ObligationMixin extends Obligation { } + } diff --git a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/permissions/ComponentPermissions.java b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/permissions/ComponentPermissions.java index bce510de7b..927ddf8d96 100644 --- a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/permissions/ComponentPermissions.java +++ b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/permissions/ComponentPermissions.java @@ -147,9 +147,6 @@ protected Set getUserEquivalentOwnerGroup(){ departments.addAll(user.getSecondaryDepartmentsAndRoles().keySet()); } departments.add(user.getDepartment()); - if(!PermissionUtils.IS_COMPONENT_VISIBILITY_RESTRICTION_ENABLED) { - return departments; - } Set finalDepartments = new HashSet(); String departmentIfUserInBU = getDepartmentIfUserInBU(document, departments); finalDepartments.add(departmentIfUserInBU); diff --git a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/thrift/ThriftClients.java b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/thrift/ThriftClients.java index 06f60ac338..5d1b7c2abb 100644 --- a/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/thrift/ThriftClients.java +++ b/libraries/lib-datahandler/src/main/java/org/eclipse/sw360/datahandler/thrift/ThriftClients.java @@ -18,7 +18,6 @@ import org.apache.http.impl.conn.DefaultProxyRoutePlanner; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.thrift.TConfiguration; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.THttpClient; @@ -62,8 +61,6 @@ public class ThriftClients { public static final String BACKEND_PROXY_URL; public static final int THRIFT_CONNECTION_TIMEOUT; public static final int THRIFT_READ_TIMEOUT; - public static final int THRIFT_MAX_MESSAGE_SIZE; - public static final int THRIFT_MAX_FRAME_SIZE; //! Service addresses private static final String ATTACHMENT_SERVICE_URL = "/attachments/thrift"; @@ -99,9 +96,6 @@ public class ThriftClients { THRIFT_CONNECTION_TIMEOUT = Integer.valueOf(props.getProperty("backend.timeout.connection", "5000")); THRIFT_READ_TIMEOUT = Integer.valueOf(props.getProperty("backend.timeout.read", "600000")); - THRIFT_MAX_MESSAGE_SIZE = Integer.valueOf(props.getProperty("backend.thrift.max.message.size", String.valueOf(TConfiguration.DEFAULT_MAX_MESSAGE_SIZE))); - THRIFT_MAX_FRAME_SIZE = Integer.valueOf(props.getProperty("backend.thrift.max.frame.size", String.valueOf(TConfiguration.DEFAULT_MAX_FRAME_SIZE))); - log.info("The following configuration will be used for connections to the backend:\n" + "\tURL : " + BACKEND_URL + "\n" + "\tProxy : " + BACKEND_PROXY_URL + "\n" + @@ -117,18 +111,15 @@ public ThriftClients() { private static TProtocol makeProtocol(String url, String service) { THttpClient thriftClient = null; final String destinationAddress = url + service; - final TConfiguration thriftConfigure = TConfiguration.custom().setMaxMessageSize(THRIFT_MAX_MESSAGE_SIZE) - .setMaxFrameSize(THRIFT_MAX_FRAME_SIZE).build(); - try { if (BACKEND_PROXY_URL != null) { URL proxyUrl = new URL(BACKEND_PROXY_URL); HttpHost proxy = new HttpHost(proxyUrl.getHost(), proxyUrl.getPort(), proxyUrl.getProtocol()); DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); CloseableHttpClient httpClient = HttpClients.custom().setRoutePlanner(routePlanner).build(); - thriftClient = new THttpClient(thriftConfigure, destinationAddress, httpClient); + thriftClient = new THttpClient(destinationAddress, httpClient); } else { - thriftClient = new THttpClient(thriftConfigure, destinationAddress); + thriftClient = new THttpClient(destinationAddress); } thriftClient.setConnectTimeout(THRIFT_CONNECTION_TIMEOUT); thriftClient.setReadTimeout(THRIFT_READ_TIMEOUT); @@ -207,4 +198,5 @@ public ChangeLogsService.Iface makeChangeLogsClient() { public HealthService.Iface makeHealthClient() { return new HealthService.Client(makeProtocol(BACKEND_URL, HEALTH_SERVICE_URL)); } + } diff --git a/libraries/lib-datahandler/src/main/resources/sw360.properties b/libraries/lib-datahandler/src/main/resources/sw360.properties index fc4cda098a..a9c31f396c 100644 --- a/libraries/lib-datahandler/src/main/resources/sw360.properties +++ b/libraries/lib-datahandler/src/main/resources/sw360.properties @@ -43,9 +43,5 @@ ## first byte of the response is available. #backend.timeout.read = 600000 -## These two properties used to set max message size and frame size of thrift transport -#backend.thrift.max.message.size=104857600 -#backend.thrift.max.frame.size=16384000 - ## This property is used to enable the component visibility restriction feature. #component.visibility.restriction.enabled=true \ No newline at end of file diff --git a/libraries/lib-datahandler/src/main/thrift/attachments.thrift b/libraries/lib-datahandler/src/main/thrift/attachments.thrift index e42d9b7a97..5e4cdfad9a 100644 --- a/libraries/lib-datahandler/src/main/thrift/attachments.thrift +++ b/libraries/lib-datahandler/src/main/thrift/attachments.thrift @@ -39,8 +39,9 @@ enum AttachmentType { SCREENSHOT = 15, OTHER = 16, README_OSS = 17, - SECURITY_ASSESSMENT = 18, - INITIAL_SCAN_REPORT = 19 + SBOM = 18, + SECURITY_ASSESSMENT = 19, + INITIAL_SCAN_REPORT = 20 } enum CheckStatus { diff --git a/libraries/lib-datahandler/src/main/thrift/components.thrift b/libraries/lib-datahandler/src/main/thrift/components.thrift index a5cbbbfcc9..9985aa6837 100644 --- a/libraries/lib-datahandler/src/main/thrift/components.thrift +++ b/libraries/lib-datahandler/src/main/thrift/components.thrift @@ -27,6 +27,7 @@ typedef sw360.MainlineState MainlineState typedef sw360.ProjectReleaseRelationship ProjectReleaseRelationship typedef sw360.SW360Exception SW360Exception typedef sw360.PaginationData PaginationData +typedef sw360.ImportBomRequestPreparation ImportBomRequestPreparation typedef attachments.Attachment Attachment typedef attachments.FilledAttachment FilledAttachment typedef users.User User @@ -828,10 +829,15 @@ service ComponentService { */ string getCyclicLinkedReleasePath(1: Release release, 2: User user); + // /** + // * parse a bom file and write the information to SW360 + // **/ + ImportBomRequestPreparation prepareImportBom(1: User user, 2:string attachmentContentId); + /** * parse a bom file and write the information to SW360 **/ - RequestSummary importBomFromAttachmentContent(1: User user, 2:string attachmentContentId); + RequestSummary importBomFromAttachmentContent(1: User user, 2:string attachmentContentId, 3:string newReleaseVersion, 4:string releaseId, 5:string rdfFilePath); /** * split data like releases and attachments from source component to target component. @@ -847,4 +853,5 @@ service ComponentService { * Send email to the user once spreadsheet export completed */ void sendExportSpreadsheetSuccessMail(1: string url, 2: string userEmail); + } diff --git a/libraries/lib-datahandler/src/main/thrift/sw360.thrift b/libraries/lib-datahandler/src/main/thrift/sw360.thrift index ad62816f72..7eaaf9f3a6 100644 --- a/libraries/lib-datahandler/src/main/thrift/sw360.thrift +++ b/libraries/lib-datahandler/src/main/thrift/sw360.thrift @@ -186,6 +186,15 @@ struct AddDocumentRequestSummary { 3: optional string message; } +struct ImportBomRequestPreparation { + 1: required RequestStatus requestStatus; + 2: optional bool isComponentDuplicate; + 3: optional bool isReleaseDuplicate; + 4: optional string name; + 5: optional string version; + 6: optional string message; +} + struct CustomProperties { 1: optional string id, 2: optional string revision, diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/changelog/ChangeLogController.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/changelog/ChangeLogController.java index 1651d787d7..fd8ad31469 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/changelog/ChangeLogController.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/changelog/ChangeLogController.java @@ -77,6 +77,7 @@ public ResponseEntity getChangeLogForDocument(Pageable pageable, @PathVariable(" ResourceClassNotFoundException { User sw360User = restControllerHelper.getSw360UserFromAuthentication(); List changelogs = sw360ChangeLogService.getChangeLogsByDocumentId(docId, sw360User); + changelogs.stream().forEach(cl -> cl.setChangeTimestamp(cl.getChangeTimestamp().split(" ")[0])); PaginationResult paginationResult = restControllerHelper.createPaginationResult(request, pageable, changelogs, SW360Constants.TYPE_CHANGELOG); ObjectMapper mapper = new ObjectMapper(); diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/core/JacksonCustomizations.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/core/JacksonCustomizations.java index 24f5a673a4..cc3ecaaecd 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/core/JacksonCustomizations.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/core/JacksonCustomizations.java @@ -191,7 +191,7 @@ static abstract class MultiStatusMixin extends MultiStatus { "modifiedOn", "setModifiedBy", "modifiedBy" - }) + }) static abstract class ProjectMixin extends Project { @Override @@ -439,6 +439,7 @@ static abstract class ComponentMixin extends Component { "setComponentId", "setReleaseDate", "setExternalIds", + "setSpdxId", "externalToolProcessesSize", "setExternalToolProcesses", "setEccInformation", @@ -1003,7 +1004,8 @@ public static abstract class CommentMixin extends Comment { "setMainlineState", "setReleaseRelation", "setCreatedOn", - "setCreatedBy" + "setCreatedBy", + "setSpdxId" }) public static abstract class ProjectReleaseRelationshipMixin extends ProjectReleaseRelationship { } @@ -1100,7 +1102,8 @@ public static abstract class VulnerabilityMixinForCreateUpdate extends Vulnerabi "verificationStateInfoIterator", "setMatchedBy", "setUsedNeedle", - "setReleaseId" + "setReleaseId", + "setSpdxId" }) public static abstract class ReleaseVulnerabilityRelationMixin extends ReleaseVulnerabilityRelation { } @@ -1118,9 +1121,12 @@ public static abstract class VerificationStateInfoMixin extends VerificationStat @JsonInclude(JsonInclude.Include.NON_NULL) @JsonIgnoreProperties({ "setEnableSvm", - "setProjectRelationship" + "setProjectRelationship", + "setSpdxId" }) public static abstract class ProjectProjectRelationshipMixin extends ProjectProjectRelationship { } + + } }