From 53c8d85da8040dd4c484a328dc9b68586bcbdf4a Mon Sep 17 00:00:00 2001 From: Smruti Prakash Sahoo Date: Thu, 20 Apr 2023 10:18:35 +0530 Subject: [PATCH 001/260] feat(clearing): Improved cloud backend clearing Signed-off-by: Smruti Prakash Sahoo --- .../db/ComponentDatabaseHandler.java | 20 +++++++++++++++++++ .../css/sw360/components/_statebox.scss | 4 ++++ .../sw360/portal/common/PortalConstants.java | 1 + .../includes/projects/clearingStatus.jsp | 6 ++++++ .../resources/content/Language.properties | 2 ++ .../resources/content/Language_ja.properties | 2 ++ .../resources/content/Language_vi.properties | 2 ++ .../ReleaseClearingStateSummaryComputer.java | 6 ++++-- .../sw360/datahandler/common/CommonUtils.java | 6 ++++++ .../datahandler/common/ThriftEnumUtils.java | 6 +++++- .../src/main/thrift/attachments.thrift | 3 ++- .../src/main/thrift/components.thrift | 2 ++ .../src/main/thrift/projects.thrift | 3 ++- 13 files changed, 58 insertions(+), 5 deletions(-) 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 2aef327263..840f95e2ac 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 @@ -187,12 +187,27 @@ public ComponentDatabaseHandler(Supplier httpClient, String dbNa private void autosetReleaseClearingState(Release releaseAfter, Release releaseBefore) { Optional oldBestCR = getBestClearingReport(releaseBefore); Optional newBestCR = getBestClearingReport(releaseAfter); + + Optional oldSecondBestCR = getBestInternalUseScanReport(releaseBefore); + Optional newSecondBestCR = getBestInternalUseScanReport(releaseAfter); + long isrCountAfter = evaluateClearingStateForScanAvailable(releaseAfter); if (isrCountAfter > 0) { releaseAfter.setClearingState(ClearingState.SCAN_AVAILABLE); } else { releaseAfter.setClearingState(ClearingState.NEW_CLEARING); } + + if (newSecondBestCR.isPresent()) { + if (newSecondBestCR.get().getCheckStatus() == CheckStatus.ACCEPTED) { + releaseAfter.setClearingState(ClearingState.INTERNAL_USE_SCAN_AVAILABLE); + } + } else { + if (oldSecondBestCR.isPresent()) { + releaseAfter.setClearingState(ClearingState.NEW_CLEARING); + } + } + if (newBestCR.isPresent()) { if (newBestCR.get().getCheckStatus() == CheckStatus.ACCEPTED) { releaseAfter.setClearingState(ClearingState.APPROVED); @@ -203,6 +218,11 @@ private void autosetReleaseClearingState(Release releaseAfter, Release releaseBe if (oldBestCR.isPresent()) { releaseAfter.setClearingState(ClearingState.NEW_CLEARING); } + + if (newSecondBestCR.isPresent() && (newSecondBestCR.get().getCheckStatus() == CheckStatus.ACCEPTED)) { + releaseAfter.setClearingState(ClearingState.INTERNAL_USE_SCAN_AVAILABLE); + } + if (isrCountAfter > 0) { releaseAfter.setClearingState(ClearingState.SCAN_AVAILABLE); } diff --git a/frontend/liferay-theme/src/main/webapp/css/sw360/components/_statebox.scss b/frontend/liferay-theme/src/main/webapp/css/sw360/components/_statebox.scss index 1efc8ffbee..6e2b242da1 100644 --- a/frontend/liferay-theme/src/main/webapp/css/sw360/components/_statebox.scss +++ b/frontend/liferay-theme/src/main/webapp/css/sw360/components/_statebox.scss @@ -19,6 +19,10 @@ background-color: rgba($yellow, 0.7); } + &.clearingStateISUA { + background-color: rgba($purple, 0.7); + } + &.projectStateActive, &.clearingStateClosed { background-color: rgba($green, 0.7); } 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 4cb9c8e950..5cee731fdd 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 @@ -507,6 +507,7 @@ public class PortalConstants { public static final String PROJECT_STATE_ACTIVE__CSS = "projectStateActive"; public static final String PROJECT_STATE_INACTIVE__CSS = "projectStateInactive"; public static final String CLEARING_STATE_OPEN__CSS = "clearingStateOpen"; + public static final String CLEARING_STATE_IUSA__CSS = "clearingStateISUA"; public static final String CLEARING_STATE_INPROGRESS__CSS = "clearingStateInProgress"; public static final String CLEARING_STATE_CLOSED__CSS = "clearingStateClosed"; public static final String CLEARING_STATE_UNKNOWN__CSS = "clearingStateUnknown"; diff --git a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/projects/includes/projects/clearingStatus.jsp b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/projects/includes/projects/clearingStatus.jsp index fa02bf5661..d5b41de212 100644 --- a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/projects/includes/projects/clearingStatus.jsp +++ b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/projects/includes/projects/clearingStatus.jsp @@ -230,6 +230,10 @@ +
  • + + +
  • @@ -698,6 +702,8 @@ AUI().use('liferay-portlet-url', function () { case 'Open': // -> red case 'New': return '<%=PortalConstants.CLEARING_STATE_OPEN__CSS%>'; + case 'Internal use scan available': + return '<%=PortalConstants.CLEARING_STATE_IUSA__CSS%>'; case 'Report available': //->blue return 'bg-info'; case 'Sent to clearing tool': //->orange diff --git a/frontend/sw360-portlet/src/main/resources/content/Language.properties b/frontend/sw360-portlet/src/main/resources/content/Language.properties index adfe47b006..26f84e54dd 100644 --- a/frontend/sw360-portlet/src/main/resources/content/Language.properties +++ b/frontend/sw360-portlet/src/main/resources/content/Language.properties @@ -239,6 +239,7 @@ close=Close closed=Closed closed.clearing.requests=Closed Clearing Requests closed.moderation.requests=Closed Moderation Requests +cloud.backend=Cloud Backend code.snippet=Code Snippet collapse.all=Collapse all comment=Comment @@ -706,6 +707,7 @@ interest=Interest internal=Internal internal.project=Internal Project internal.use=Internal use +internal.use.scan.available=Internal Use Scan Available interval=Interval invalid.agreed.clearing.date=Invalid agreed clearing date! invalid.clearingTeam.email=Invalid clearingTeam email! 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 3b8e67a2d9..5b7b471341 100644 --- a/frontend/sw360-portlet/src/main/resources/content/Language_ja.properties +++ b/frontend/sw360-portlet/src/main/resources/content/Language_ja.properties @@ -239,6 +239,7 @@ close=クローズ closed=クローズ済 closed.clearing.requests=クローズされたクリアリクエスト closed.moderation.requests=クローズされたモデレーションリクエスト +cloud.backend=Cloud Backend code.snippet=コードスニペット collapse.all=全て展開 comment=コメント @@ -705,6 +706,7 @@ interest=興味 internal=内部 internal.project=社内プロジェクト internal.use=内部利用 +internal.use.scan.available=Internal Use Scan Available interval=インターバル invalid.agreed.clearing.date=同意したクリアリング日が不正 invalid.clearingTeam.email=クリアリングチームのメールアドレスが不正 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 f71faa0413..5c8e8e6a65 100644 --- a/frontend/sw360-portlet/src/main/resources/content/Language_vi.properties +++ b/frontend/sw360-portlet/src/main/resources/content/Language_vi.properties @@ -239,6 +239,7 @@ close=Đóng closed=Đã đóng closed.clearing.requests=Yêu cầu thanh toán bù trừ closed.moderation.requests=Yêu cầu kiểm duyệt đã đóng +cloud.backend=Cloud Backend code.snippet=Code Snippet collapse.all=Collapse all comment=Giải thích @@ -708,6 +709,7 @@ interest=Quan tâm internal=Nội bộ internal.project=Dự án nội bộ internal.use=Sử dụng nội bộ +internal.use.scan.available=Internal Use Scan Available interval=Khoảng invalid.agreed.clearing.date=Invalid agreed clearing date! invalid.clearingTeam.email=Invalid clearingTeam email! diff --git a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/businessrules/ReleaseClearingStateSummaryComputer.java b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/businessrules/ReleaseClearingStateSummaryComputer.java index 88812aa7e4..5044ebd7fd 100644 --- a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/businessrules/ReleaseClearingStateSummaryComputer.java +++ b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/businessrules/ReleaseClearingStateSummaryComputer.java @@ -9,7 +9,6 @@ */ package org.eclipse.sw360.datahandler.businessrules; -import org.eclipse.sw360.datahandler.thrift.components.ClearingState; import org.eclipse.sw360.datahandler.thrift.components.ComponentService; import org.eclipse.sw360.datahandler.thrift.components.Release; import org.eclipse.sw360.datahandler.thrift.components.ReleaseClearingStateSummary; @@ -29,7 +28,7 @@ public class ReleaseClearingStateSummaryComputer { public static ReleaseClearingStateSummary computeReleaseClearingStateSummary(List releases, String clearingTeam) { - ReleaseClearingStateSummary summary = new ReleaseClearingStateSummary(0, 0, 0, 0, 0, 0); + ReleaseClearingStateSummary summary = new ReleaseClearingStateSummary(0, 0, 0, 0, 0, 0, 0); if (releases == null) { return summary; @@ -61,6 +60,9 @@ public static ReleaseClearingStateSummary computeReleaseClearingStateSummary(Lis case SCAN_AVAILABLE: summary.scanAvailable++; break; + case INTERNAL_USE_SCAN_AVAILABLE: + summary.internalUseScanAvailable++; + break; default: summary.newRelease++; break; diff --git a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/CommonUtils.java b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/CommonUtils.java index a86f95afd7..33d472f806 100644 --- a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/CommonUtils.java +++ b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/CommonUtils.java @@ -643,6 +643,12 @@ public static Optional getBestClearingReport(Release release) { .max(Comparator.comparing(Attachment::getCheckStatus, CHECK_STATUS_COMPARATOR)); } + public static Optional getBestInternalUseScanReport(Release release) { + return nullToEmptyCollection(release.getAttachments()).stream() + .filter(att -> att.getAttachmentType() == AttachmentType.INTERNAL_USE_SCAN) + .max(Comparator.comparing(Attachment::getCheckStatus, CHECK_STATUS_COMPARATOR)); + } + public static boolean isTemporaryObligation(Obligation oblig) { return oblig.isSetId() && oblig.getId().startsWith(TMP_OBLIGATION_ID_PREFIX); } diff --git a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/ThriftEnumUtils.java b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/ThriftEnumUtils.java index 8f5264af21..a2e4d36c2b 100644 --- a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/ThriftEnumUtils.java +++ b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/ThriftEnumUtils.java @@ -93,7 +93,8 @@ private ThriftEnumUtils() { ProjectType.INTERNAL, "Internal Project" , ProjectType.PRODUCT, "Product" , ProjectType.SERVICE, "Service", - ProjectType.INNER_SOURCE, "Inner Source"); + ProjectType.INNER_SOURCE, "Inner Source", + ProjectType.CLOUD_BACKEND, "Cloud Backend"); private static final ImmutableMap MAP_ATTACHMENT_TYPE_STRING = ImmutableMap.builder() .put(AttachmentType.DOCUMENT, "Document") @@ -117,6 +118,7 @@ private ThriftEnumUtils() { .put(AttachmentType.SECURITY_ASSESSMENT, "Security Assessment") .put(AttachmentType.SBOM, "SBOM") .put(AttachmentType.INITIAL_SCAN_REPORT, "Initial Scan Report") + .put(AttachmentType.INTERNAL_USE_SCAN, "Initial Use Scan") .build(); // @formatter:off @@ -143,6 +145,7 @@ private ThriftEnumUtils() { .put(AttachmentType.SECURITY_ASSESSMENT, "SECA") .put(AttachmentType.SBOM, "SBOM") .put(AttachmentType.INITIAL_SCAN_REPORT, "ISR") + .put(AttachmentType.INTERNAL_USE_SCAN, "IUS") .build(); private static final ImmutableMap MAP_CLEARING_STATUS_STRING = ImmutableMap @@ -153,6 +156,7 @@ private ThriftEnumUtils() { .put(ClearingState.REPORT_AVAILABLE, "Report available") .put(ClearingState.APPROVED, "Report approved") .put(ClearingState.SCAN_AVAILABLE, "Scan available") + .put(ClearingState.INTERNAL_USE_SCAN_AVAILABLE, "Internal use scan available") .build(); private static final ImmutableMap MAP_EXTERNAL_TOOL_STRING = ImmutableMap diff --git a/libraries/datahandler/src/main/thrift/attachments.thrift b/libraries/datahandler/src/main/thrift/attachments.thrift index 7776dabb0b..93cd08f6ae 100644 --- a/libraries/datahandler/src/main/thrift/attachments.thrift +++ b/libraries/datahandler/src/main/thrift/attachments.thrift @@ -41,7 +41,8 @@ enum AttachmentType { README_OSS = 17, SECURITY_ASSESSMENT = 18, INITIAL_SCAN_REPORT = 19, - SBOM = 20 + SBOM = 20, + INTERNAL_USE_SCAN = 21 } enum CheckStatus { diff --git a/libraries/datahandler/src/main/thrift/components.thrift b/libraries/datahandler/src/main/thrift/components.thrift index 6a2bcd3659..1982c04484 100644 --- a/libraries/datahandler/src/main/thrift/components.thrift +++ b/libraries/datahandler/src/main/thrift/components.thrift @@ -125,6 +125,7 @@ enum ClearingState { REPORT_AVAILABLE = 3, APPROVED = 4, SCAN_AVAILABLE = 5, + INTERNAL_USE_SCAN_AVAILABLE = 6 } /** @@ -138,6 +139,7 @@ struct ReleaseClearingStateSummary { 4: required i32 reportAvailable, 5: required i32 approved, 6: required i32 scanAvailable, + 7: required i32 internalUseScanAvailable, } enum ECCStatus { diff --git a/libraries/datahandler/src/main/thrift/projects.thrift b/libraries/datahandler/src/main/thrift/projects.thrift index 5e8ca5d5fb..bd5a5e3a78 100644 --- a/libraries/datahandler/src/main/thrift/projects.thrift +++ b/libraries/datahandler/src/main/thrift/projects.thrift @@ -57,7 +57,8 @@ enum ProjectType { INTERNAL = 1, PRODUCT = 2, SERVICE = 3, - INNER_SOURCE = 4 + INNER_SOURCE = 4, + CLOUD_BACKEND = 5 } enum ProjectRelationship { From 249f48f490be51d004ee56fe0d258fcc018c0707 Mon Sep 17 00:00:00 2001 From: Nguyen Nhu Tuan Date: Fri, 8 Apr 2022 14:56:17 +0700 Subject: [PATCH 002/260] feat(SPDX): Making new tab in component release pages for showing SPDX/SPDX Lite data #1240 Signed-off-by: Nguyen Nhu Tuan --- .../DocumentCreationInformationSummary.java | 37 + .../summary/FileInformationSummary.java | 37 + .../summary/PackageInformationSummary.java | 37 + .../summary/SpdxDocumentSummary.java | 37 + .../db/ComponentDatabaseHandler.java | 84 +- .../datahandler/db/DatabaseHandlerUtil.java | 51 + .../document/SpdxDocumentDatabaseHandler.java | 224 +++ .../spdx/document/SpdxDocumentRepository.java | 40 + .../document/SpdxDocumentSearchHandler.java | 48 + ...dxDocumentCreationInfoDatabaseHandler.java | 191 +++ .../SpdxDocumentCreationInfoRepository.java | 40 + ...SpdxDocumentCreationInfoSearchHandler.java | 48 + .../SpdxPackageInfoDatabaseHandler.java | 245 ++++ .../SpdxPackageInfoRepository.java | 40 + .../SpdxPackageInfoSearchHandler.java | 48 + .../SpdxDocumentCreationInfoModerator.java | 156 +++ .../entitlement/SpdxDocumentModerator.java | 210 +++ .../entitlement/SpdxPackageInfoModerator.java | 207 +++ .../eclipse/sw360/spdx/SpdxBOMImporter.java | 671 ++++++++- .../sw360/spdx/SpdxBOMImporterSink.java | 122 +- .../sw360/spdx/SpdxBOMImporterTest.java | 2 + backend/src/pom.xml | 3 + .../sw360/moderation/ModerationHandler.java | 51 + .../db/ModerationDatabaseHandler.java | 107 ++ .../db/ReleaseModerationRequestGenerator.java | 10 +- ...reationInfoModerationRequestGenerator.java | 48 + ...pdxDocumentModerationRequestGenerator.java | 49 + ...PackageInfoModerationRequestGenerator.java | 53 + backend/src/src-spdxdocument/pom.xml | 38 + .../spdxdocument/SPDXDocumentHandler.java | 92 ++ .../spdxdocument/SPDXDocumentServlet.java | 26 + .../src/src-spdxdocumentcreationinfo/pom.xml | 43 + .../DocumentCreationInformationHandler.java | 90 ++ .../DocumentCreationInformationServlet.java | 26 + backend/src/src-spdxpackageinfo/pom.xml | 43 + .../PackageInformationHandler.java | 103 ++ .../PackageInformationServlet.java | 26 + backend/svc/pom.xml | 3 + backend/svc/svc-spdxdocument/pom.xml | 72 + .../src/main/webapp/WEB-INF/web.xml | 37 + .../src/main/webapp/index.jsp | 21 + .../svc/svc-spdxdocumentcreationinfo/pom.xml | 72 + .../src/main/webapp/WEB-INF/web.xml | 37 + .../src/main/webapp/index.jsp | 21 + backend/svc/svc-spdxpackageinfo/pom.xml | 72 + .../src/main/webapp/WEB-INF/web.xml | 38 + .../src/main/webapp/index.jsp | 21 + .../portal/common/ChangeLogsPortletUtils.java | 60 +- .../sw360/portal/common/PortalConstants.java | 11 + .../sw360/portal/common/SpdxUtils.java | 417 ++++++ .../sw360/portal/portlets/Sw360Portlet.java | 8 +- .../portlets/components/ComponentPortlet.java | 250 +++- .../moderation/ModerationPortlet.java | 138 ++ .../DisplayDocumentCreationInfoChanges.java | 302 ++++ .../tags/DisplayPackageInfoChanges.java | 360 +++++ .../tags/DisplaySPDXDocumentChanges.java | 476 +++++++ .../org/eclipse/sw360/portal/tags/OutTag.java | 10 + .../main/resources/META-INF/customTags.tld | 130 ++ .../html/components/detailRelease.jsp | 1 + .../resources/html/components/edit.jsp | 1 + .../resources/html/components/editRelease.jsp | 79 +- .../includes/releases/detailOverview.jspf | 8 + .../includes/releases/spdx/edit.jspf | 547 ++++++++ .../spdx/includes/editAnnotations.jsp | 92 ++ .../editDocumentCreationInformation.jsp | 225 +++ .../editOtherLicensingInformationDetected.jsp | 103 ++ .../spdx/includes/editPackageInformation.jsp | 528 +++++++ .../editRelationshipsBetweenSPDXElements.jsp | 71 + .../spdx/includes/editSnippetInformation.jsp | 200 +++ .../includes/releases/spdx/view.jsp | 1217 +++++++++++++++++ .../spdx/documentCreationInfo/delete.jsp | 93 ++ .../spdx/documentCreationInfo/merge.jsp | 102 ++ .../moderation/spdx/packageInfo/delete.jsp | 96 ++ .../moderation/spdx/packageInfo/merge.jsp | 105 ++ .../moderation/spdx/spdxDocument/delete.jsp | 92 ++ .../moderation/spdx/spdxDocument/merge.jsp | 101 ++ .../html/utils/includes/importBom.jspf | 2 +- .../utils/includes/importBomForComponent.jspf | 99 +- .../js/components/includes/releases/spdxjs.js | 1175 ++++++++++++++++ .../includes/releases/validateLib.js | 253 ++++ .../META-INF/resources/js/utils/array.js | 34 + .../resources/content/Language.properties | 23 + .../resources/content/Language_ja.properties | 4 + .../resources/content/Language_vi.properties | 6 + .../resources/content/Language_zh.properties | 4 + .../datahandler/common/DatabaseSettings.java | 2 + .../sw360/datahandler/common/Moderator.java | 5 - .../datahandler/common/SW360Constants.java | 5 + .../sw360/datahandler/common/SW360Utils.java | 24 + .../datahandler/common/ThriftEnumUtils.java | 17 +- .../couchdb/DatabaseMixInForChangeLog.java | 139 +- .../couchdb/DatabaseMixInForSPDXDocument.java | 211 +++ .../permissions/PermissionUtils.java | 9 + .../SpdxDocumentCreationInfoPermissions.java | 53 + .../permissions/SpdxDocumentPermissions.java | 53 + .../SpdxPackageInfoPermissions.java | 53 + .../datahandler/thrift/ThriftClients.java | 26 + .../sw360/datahandler/thrift/ThriftUtils.java | 8 + .../datahandler/thrift/ThriftValidate.java | 28 + .../src/main/thrift/changelogs.thrift | 8 +- .../src/main/thrift/components.thrift | 2 + .../src/main/thrift/moderation.thrift | 55 + .../src/main/thrift/spdx/annotations.thrift | 21 + .../spdx/documentcreationinformation.thrift | 76 + .../main/thrift/spdx/fileinformation.thrift | 65 + .../otherlicensinginformationdetected.thrift | 21 + .../thrift/spdx/packageinformation.thrift | 97 ++ .../relationshipsbetweenspdxelements.thrift | 20 + .../thrift/spdx/snippetinformation.thrift | 34 + .../src/main/thrift/spdx/spdxdocument.thrift | 61 + .../datahandler/src/main/thrift/sw360.thrift | 7 +- pom.xml | 13 + .../changelog/ChangeLogController.java | 1 + .../core/JacksonCustomizations.java | 11 +- 114 files changed, 12162 insertions(+), 163 deletions(-) create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/components/summary/DocumentCreationInformationSummary.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/components/summary/FileInformationSummary.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/components/summary/PackageInformationSummary.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/components/summary/SpdxDocumentSummary.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentDatabaseHandler.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentRepository.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentSearchHandler.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoDatabaseHandler.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoRepository.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoSearchHandler.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoDatabaseHandler.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoRepository.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoSearchHandler.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxDocumentCreationInfoModerator.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxDocumentModerator.java create mode 100644 backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxPackageInfoModerator.java create mode 100644 backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxDocumentCreationInfoModerationRequestGenerator.java create mode 100644 backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxDocumentModerationRequestGenerator.java create mode 100644 backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxPackageInfoModerationRequestGenerator.java create mode 100644 backend/src/src-spdxdocument/pom.xml create mode 100644 backend/src/src-spdxdocument/src/main/java/org/eclipse/sw360/spdxdocument/SPDXDocumentHandler.java create mode 100644 backend/src/src-spdxdocument/src/main/java/org/eclipse/sw360/spdxdocument/SPDXDocumentServlet.java create mode 100644 backend/src/src-spdxdocumentcreationinfo/pom.xml create mode 100644 backend/src/src-spdxdocumentcreationinfo/src/main/java/org/eclipse/sw360/spdxdocumentcreationinfo/DocumentCreationInformationHandler.java create mode 100644 backend/src/src-spdxdocumentcreationinfo/src/main/java/org/eclipse/sw360/spdxdocumentcreationinfo/DocumentCreationInformationServlet.java create mode 100644 backend/src/src-spdxpackageinfo/pom.xml create mode 100644 backend/src/src-spdxpackageinfo/src/main/java/org/eclipse/sw360/spdxpackageinfo/PackageInformationHandler.java create mode 100644 backend/src/src-spdxpackageinfo/src/main/java/org/eclipse/sw360/spdxpackageinfo/PackageInformationServlet.java create mode 100644 backend/svc/svc-spdxdocument/pom.xml create mode 100644 backend/svc/svc-spdxdocument/src/main/webapp/WEB-INF/web.xml create mode 100644 backend/svc/svc-spdxdocument/src/main/webapp/index.jsp create mode 100644 backend/svc/svc-spdxdocumentcreationinfo/pom.xml create mode 100644 backend/svc/svc-spdxdocumentcreationinfo/src/main/webapp/WEB-INF/web.xml create mode 100644 backend/svc/svc-spdxdocumentcreationinfo/src/main/webapp/index.jsp create mode 100644 backend/svc/svc-spdxpackageinfo/pom.xml create mode 100644 backend/svc/svc-spdxpackageinfo/src/main/webapp/WEB-INF/web.xml create mode 100644 backend/svc/svc-spdxpackageinfo/src/main/webapp/index.jsp create mode 100644 frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/SpdxUtils.java create mode 100644 frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplayDocumentCreationInfoChanges.java create mode 100644 frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplayPackageInfoChanges.java create mode 100644 frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplaySPDXDocumentChanges.java create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/includes/releases/spdx/edit.jspf create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/includes/releases/spdx/includes/editAnnotations.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/includes/releases/spdx/includes/editDocumentCreationInformation.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/includes/releases/spdx/includes/editOtherLicensingInformationDetected.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/includes/releases/spdx/includes/editPackageInformation.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/includes/releases/spdx/includes/editRelationshipsBetweenSPDXElements.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/includes/releases/spdx/includes/editSnippetInformation.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/includes/releases/spdx/view.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/moderation/spdx/documentCreationInfo/delete.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/moderation/spdx/documentCreationInfo/merge.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/moderation/spdx/packageInfo/delete.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/moderation/spdx/packageInfo/merge.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/moderation/spdx/spdxDocument/delete.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/html/moderation/spdx/spdxDocument/merge.jsp create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/js/components/includes/releases/spdxjs.js create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/js/components/includes/releases/validateLib.js create mode 100644 frontend/sw360-portlet/src/main/resources/META-INF/resources/js/utils/array.js create mode 100644 libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/couchdb/DatabaseMixInForSPDXDocument.java create mode 100644 libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/permissions/SpdxDocumentCreationInfoPermissions.java create mode 100644 libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/permissions/SpdxDocumentPermissions.java create mode 100644 libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/permissions/SpdxPackageInfoPermissions.java create mode 100644 libraries/datahandler/src/main/thrift/spdx/annotations.thrift create mode 100644 libraries/datahandler/src/main/thrift/spdx/documentcreationinformation.thrift create mode 100644 libraries/datahandler/src/main/thrift/spdx/fileinformation.thrift create mode 100644 libraries/datahandler/src/main/thrift/spdx/otherlicensinginformationdetected.thrift create mode 100644 libraries/datahandler/src/main/thrift/spdx/packageinformation.thrift create mode 100644 libraries/datahandler/src/main/thrift/spdx/relationshipsbetweenspdxelements.thrift create mode 100644 libraries/datahandler/src/main/thrift/spdx/snippetinformation.thrift create mode 100644 libraries/datahandler/src/main/thrift/spdx/spdxdocument.thrift diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/DocumentCreationInformationSummary.java b/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/DocumentCreationInformationSummary.java new file mode 100644 index 0000000000..3b2a218718 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/DocumentCreationInformationSummary.java @@ -0,0 +1,37 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.components.summary; + +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; + +import static org.eclipse.sw360.datahandler.thrift.ThriftUtils.copyField; + +public class DocumentCreationInformationSummary extends DocumentSummary { + + @Override + protected DocumentCreationInformation summary(SummaryType type, DocumentCreationInformation document) { + // Copy required details + DocumentCreationInformation copy = new DocumentCreationInformation(); + + switch (type) { + case SUMMARY: + copyField(document, copy, DocumentCreationInformation._Fields.ID); + copyField(document, copy, DocumentCreationInformation._Fields.SPDXID); + copyField(document, copy, DocumentCreationInformation._Fields.NAME); + break; + default: + break; + } + + return copy; + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/FileInformationSummary.java b/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/FileInformationSummary.java new file mode 100644 index 0000000000..adb1c68e71 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/FileInformationSummary.java @@ -0,0 +1,37 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.components.summary; + +import org.eclipse.sw360.datahandler.thrift.spdx.fileinformation.*; + +import static org.eclipse.sw360.datahandler.thrift.ThriftUtils.copyField; + +public class FileInformationSummary extends DocumentSummary { + + @Override + protected FileInformation summary(SummaryType type, FileInformation document) { + // Copy required details + FileInformation copy = new FileInformation(); + + switch (type) { + case SUMMARY: + copyField(document, copy, FileInformation._Fields.ID); + copyField(document, copy, FileInformation._Fields.SPDXID); + copyField(document, copy, FileInformation._Fields.FILE_NAME); + break; + default: + break; + } + + return copy; + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/PackageInformationSummary.java b/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/PackageInformationSummary.java new file mode 100644 index 0000000000..2b343a90c6 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/PackageInformationSummary.java @@ -0,0 +1,37 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.components.summary; + +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.*; + +import static org.eclipse.sw360.datahandler.thrift.ThriftUtils.copyField; + +public class PackageInformationSummary extends DocumentSummary { + + @Override + protected PackageInformation summary(SummaryType type, PackageInformation document) { + // Copy required details + PackageInformation copy = new PackageInformation(); + + switch (type) { + case SUMMARY: + copyField(document, copy, PackageInformation._Fields.ID); + copyField(document, copy, PackageInformation._Fields.SPDXID); + copyField(document, copy, PackageInformation._Fields.NAME); + break; + default: + break; + } + + return copy; + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/SpdxDocumentSummary.java b/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/SpdxDocumentSummary.java new file mode 100644 index 0000000000..3d260df71d --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/components/summary/SpdxDocumentSummary.java @@ -0,0 +1,37 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.components.summary; + +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; + +import static org.eclipse.sw360.datahandler.thrift.ThriftUtils.copyField; + +public class SpdxDocumentSummary extends DocumentSummary { + + @Override + protected SPDXDocument summary(SummaryType type, SPDXDocument document) { + // Copy required details + SPDXDocument copy = new SPDXDocument(); + + switch (type) { + case SUMMARY: + copyField(document, copy, SPDXDocument._Fields.ID); + copyField(document, copy, SPDXDocument._Fields.SPDX_DOCUMENT_CREATION_INFO_ID); + copyField(document, copy, SPDXDocument._Fields.SPDX_PACKAGE_INFO_IDS); + copyField(document, copy, SPDXDocument._Fields.SPDX_FILE_INFO_IDS); + default: + break; + } + + return copy; + } + +} 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 2aef327263..6287da497a 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 @@ -25,6 +25,7 @@ import org.eclipse.sw360.datahandler.common.ThriftEnumUtils; import org.eclipse.sw360.datahandler.couchdb.AttachmentConnector; import org.eclipse.sw360.datahandler.couchdb.AttachmentStreamConnector; +import org.eclipse.sw360.datahandler.db.spdx.document.SpdxDocumentDatabaseHandler; import org.eclipse.sw360.datahandler.entitlement.ComponentModerator; import org.eclipse.sw360.datahandler.entitlement.ProjectModerator; import org.eclipse.sw360.datahandler.entitlement.ReleaseModerator; @@ -65,6 +66,8 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import org.spdx.library.InvalidSPDXAnalysisException; +import java.io.InputStreamReader; import java.net.MalformedURLException; import java.util.*; import java.util.concurrent.TimeUnit; @@ -100,6 +103,10 @@ public class ComponentDatabaseHandler extends AttachmentAwareDatabaseHandler { private static final String ECC_AUTOSET_VALUE = "N"; private static final String DEFAULT_CATEGORY = "Default_Category"; private static final String ECC_FIELDS_VALUE_RESET = ""; + private static final String NO_COMPONENT = "Don't have Component created!"; + private static final String NO_RELEASE = "Don't have Release created!"; + private static final List listComponentName = new ArrayList<>(); + private static final Map mapReleaseName = new HashMap<>(); /** * Connection to the couchDB database @@ -113,6 +120,7 @@ public class ComponentDatabaseHandler extends AttachmentAwareDatabaseHandler { private final AttachmentConnector attachmentConnector; private SvmConnector svmConnector; + private final SpdxDocumentDatabaseHandler spdxDocumentDatabaseHandler; /** * Access to moderation */ @@ -162,6 +170,9 @@ 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); + + // Create the spdx document database handler + this.spdxDocumentDatabaseHandler = new SpdxDocumentDatabaseHandler(httpClient, DatabaseSettings.COUCH_DB_SPDX); } public ComponentDatabaseHandler(Supplier httpClient, String dbName, String changeLogsDbName, String attachmentDbName, ComponentModerator moderator, ReleaseModerator releaseModerator, ProjectModerator projectModerator) throws MalformedURLException { @@ -542,6 +553,20 @@ private boolean isDuplicate(String releaseName, String releaseVersion) { return duplicates.size()>0; } + private void isDuplicateComponent(List componentNames, boolean caseInsenstive) { + for (String name : componentNames) { + if(!isDuplicate(name, caseInsenstive)) + listComponentName.add(name); + } + } + + private void isDuplicateRelease(Map releases) { + for (Map.Entry release : releases.entrySet()) { + if(!isDuplicate(release.getKey(), release.getValue())) + mapReleaseName.put(release.getKey(), release.getValue()); + } + } + private void resetReleaseDependentFields(Component component) { component.setLanguages(new HashSet()); component.setOperatingSystems(new HashSet()); @@ -1728,7 +1753,13 @@ public RequestStatus deleteRelease(String id, User user, boolean forceDelete) th Component componentBefore = componentRepository.get(release.getComponentId()); // Remove release id from component removeReleaseId(id, release.componentId); - Component componentAfter=removeReleaseAndCleanUp(release, user); + // Remove spdx if exist + String spdxId = release.getSpdxId(); + if (CommonUtils.isNotNullEmptyOrWhitespace(spdxId)) { + spdxDocumentDatabaseHandler.deleteSPDXDocument(spdxId, user); + release = releaseRepository.get(id); + } + 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, @@ -2543,24 +2574,41 @@ public ImportBomRequestPreparation prepareImportBom(User user, String attachment ImportBomRequestPreparation importBomRequestPreparation = spdxBOMImporter.prepareImportSpdxBOMAsRelease(sourceFile); 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 { + List componentsName = getComponentsName(importBomRequestPreparation.getComponentsName()); + Map releasesName = getReleasesName(importBomRequestPreparation.getReleasesName()); + isDuplicateRelease(releasesName); + isDuplicateComponent(componentsName,true); + if (listComponentName.size() == 0 && mapReleaseName.size() == 0){ importBomRequestPreparation.setIsComponentDuplicate(true); importBomRequestPreparation.setIsReleaseDuplicate(true); } + else { + String componentName = ""; + String releaseName = ""; + if (listComponentName.isEmpty()){ + componentName = NO_COMPONENT; + } else { + componentName = listComponentName.stream().collect(Collectors.joining(" , ")); + } + if (mapReleaseName.isEmpty()){ + releaseName = NO_RELEASE; + } else { + releaseName = mapReleaseName.keySet().stream().map(key -> key + " " + mapReleaseName.get(key)).collect(Collectors.joining(" , ")); + } + listComponentName.clear(); + mapReleaseName.clear(); + importBomRequestPreparation.setComponentsName(componentName); + importBomRequestPreparation.setReleasesName(releaseName); + importBomRequestPreparation.setIsComponentDuplicate(false); + importBomRequestPreparation.setIsReleaseDuplicate(false); + } + importBomRequestPreparation.setMessage(sourceFile.getAbsolutePath()); } return importBomRequestPreparation; } - } catch (IOException e) { + } catch (IOException | InvalidSPDXAnalysisException e) { throw new SW360Exception(e.getMessage()); } } @@ -2738,4 +2786,18 @@ public void sendExportSpreadsheetSuccessMail(String url, String recepient) throw "component", url); } + public List getComponentsName(String components) { + String[] parts = components.split(","); + return Arrays.asList(parts); + } + + public Map getReleasesName(String releases) { + Map releaseNames= new HashMap<>(); + String[] parts = releases.split(","); + for (int i = 0; i < parts.length; i++) { + String[] releaseName = parts[i].split(" "); + releaseNames.put(releaseName[0], releaseName[1]); + } + return releaseNames; + } } 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 cd3a7c329a..b9ae179cc3 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 @@ -78,6 +78,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; @@ -102,6 +103,19 @@ import org.eclipse.sw360.datahandler.thrift.users.RequestedAction; import org.eclipse.sw360.datahandler.thrift.users.User; import org.eclipse.sw360.datahandler.thrift.vendors.Vendor; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.annotations.Annotations; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.CheckSum; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.Creator; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.ExternalDocumentReferences; +import org.eclipse.sw360.datahandler.thrift.spdx.otherlicensinginformationdetected.OtherLicensingInformationDetected; +import org.eclipse.sw360.datahandler.thrift.spdx.relationshipsbetweenspdxelements.RelationshipsBetweenSPDXElements; +import org.eclipse.sw360.datahandler.thrift.spdx.snippetinformation.SnippetInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.snippetinformation.SnippetRange; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.ExternalReference; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageVerificationCode; import org.eclipse.sw360.datahandler.thrift.licenses.Obligation; import com.fasterxml.jackson.core.JsonProcessingException; @@ -412,6 +426,21 @@ public static void trimStringFields(T obj, List listOfStrFields) { changeLog.setDocumentId(newProjVer.getId()); changeLog.setDocumentType(newProjVer.getType()); changeLog.setDbName(DatabaseSettings.COUCH_DB_DATABASE); + } else if (newDocVersion instanceof SPDXDocument) { + SPDXDocument newProjVer = (SPDXDocument) newDocVersion; + changeLog.setDocumentId(newProjVer.getId()); + changeLog.setDocumentType(newProjVer.getType()); + changeLog.setDbName(DatabaseSettings.COUCH_DB_SPDX); + } else if (newDocVersion instanceof DocumentCreationInformation) { + DocumentCreationInformation newProjVer = (DocumentCreationInformation) newDocVersion; + changeLog.setDocumentId(newProjVer.getId()); + changeLog.setDocumentType(newProjVer.getType()); + changeLog.setDbName(DatabaseSettings.COUCH_DB_SPDX); + } else if (newDocVersion instanceof PackageInformation) { + PackageInformation newProjVer = (PackageInformation) newDocVersion; + changeLog.setDocumentId(newProjVer.getId()); + changeLog.setDocumentType(newProjVer.getType()); + changeLog.setDbName(DatabaseSettings.COUCH_DB_SPDX); } else if (newDocVersion instanceof Obligation) { Obligation newProjVer = (Obligation) newDocVersion; changeLog.setDocumentId(newProjVer.getId()); @@ -598,6 +627,12 @@ private static void changeLogsForNewlyCreatedOrDeleted(T newor fields = Release._Fields.values(); } else if (neworDeletedVersion instanceof ModerationRequest) { fields = ModerationRequest._Fields.values(); + } else if (neworDeletedVersion instanceof SPDXDocument) { + fields = SPDXDocument._Fields.values(); + } else if (neworDeletedVersion instanceof DocumentCreationInformation) { + fields = DocumentCreationInformation._Fields.values(); + } else if (neworDeletedVersion instanceof PackageInformation) { + fields = PackageInformation._Fields.values(); } else if (neworDeletedVersion instanceof Obligation) { fields = Obligation._Fields.values(); } else { @@ -624,6 +659,12 @@ private static void changeLogsForNewlyCreatedOrDeleted(T newor fields = Release._Fields.values(); } else if (newVersion instanceof ModerationRequest) { fields = ModerationRequest._Fields.values(); + } else if (newVersion instanceof SPDXDocument) { + fields = SPDXDocument._Fields.values(); + } else if (newVersion instanceof DocumentCreationInformation) { + fields = DocumentCreationInformation._Fields.values(); + } else if (newVersion instanceof PackageInformation) { + fields = PackageInformation._Fields.values(); } else if (newVersion instanceof Obligation) { fields = Obligation._Fields.values(); } else { @@ -840,6 +881,16 @@ private static ObjectMapper initAndGetObjectMapper() { mapper.addMixInAnnotations(Repository.class, RepositoryMixin.class); mapper.addMixInAnnotations(ProjectProjectRelationship.class, ProjectProjectRelationshipMixin.class); mapper.addMixInAnnotations(ProjectReleaseRelationship.class, ProjectReleaseRelationshipMixin.class); + mapper.addMixInAnnotations(CheckSum.class, CheckSumMixin.class); + mapper.addMixInAnnotations(Annotations.class, AnnotationsMixin.class); + mapper.addMixInAnnotations(ExternalDocumentReferences.class, ExternalDocumentReferencesMixin.class); + mapper.addMixInAnnotations(Creator.class, CreatorMixin.class); + mapper.addMixInAnnotations(OtherLicensingInformationDetected.class, OtherLicensingInformationDetectedMixin.class); + mapper.addMixInAnnotations(PackageVerificationCode.class, PackageVerificationCodeMixin.class); + mapper.addMixInAnnotations(ExternalReference.class, ExternalReferenceMixin.class); + mapper.addMixInAnnotations(RelationshipsBetweenSPDXElements.class, RelationshipsBetweenSPDXElementsMixin.class); + mapper.addMixInAnnotations(SnippetInformation.class, SnippetInformationMixin.class); + mapper.addMixInAnnotations(SnippetRange.class, SnippetRangeMixin.class); mapper.addMixInAnnotations(Obligation.class, ObligationMixin.class); } return mapper; diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentDatabaseHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentDatabaseHandler.java new file mode 100644 index 0000000000..57885c8ad2 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentDatabaseHandler.java @@ -0,0 +1,224 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.document; + +import com.cloudant.client.api.CloudantClient; + +import org.eclipse.sw360.datahandler.cloudantclient.DatabaseConnectorCloudant; +import org.eclipse.sw360.datahandler.common.DatabaseSettings; +import org.eclipse.sw360.datahandler.thrift.*; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.eclipse.sw360.datahandler.thrift.users.RequestedAction; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.*; +import org.eclipse.sw360.datahandler.thrift.components.*; +import org.eclipse.sw360.datahandler.thrift.changelogs.*; +import org.eclipse.sw360.datahandler.db.ReleaseRepository; +import org.eclipse.sw360.datahandler.db.VendorRepository; +import org.eclipse.sw360.datahandler.db.DatabaseHandlerUtil; +import org.eclipse.sw360.datahandler.db.spdx.documentcreationinfo.SpdxDocumentCreationInfoDatabaseHandler; +import org.eclipse.sw360.datahandler.db.spdx.packageinfo.SpdxPackageInfoDatabaseHandler; +import org.eclipse.sw360.datahandler.entitlement.SpdxDocumentModerator; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; +import org.eclipse.sw360.datahandler.common.CommonUtils; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import java.net.MalformedURLException; +import java.util.*; +import java.util.function.Supplier; +import com.google.common.collect.Lists; + +import static org.eclipse.sw360.datahandler.common.SW360Assert.assertNotNull; +import static org.eclipse.sw360.datahandler.common.CommonUtils.*; +import static org.eclipse.sw360.datahandler.permissions.PermissionUtils.makePermission; +import static org.eclipse.sw360.datahandler.thrift.ThriftValidate.prepareSPDXDocument; + +public class SpdxDocumentDatabaseHandler { + + private static final Logger log = LogManager.getLogger(SpdxDocumentDatabaseHandler.class); + + /** + * Connection to the couchDB database + */ + private final DatabaseConnectorCloudant db; + private final DatabaseConnectorCloudant sw360db; + private final DatabaseConnectorCloudant dbChangeLogs; + + private final SpdxDocumentRepository SPDXDocumentRepository; + private final ReleaseRepository releaseRepository; + private final VendorRepository vendorRepository; + private DatabaseHandlerUtil dbHandlerUtil; + private final SpdxDocumentModerator moderator; + + private final SpdxDocumentCreationInfoDatabaseHandler creationInfoDatabaseHandler; + private final SpdxPackageInfoDatabaseHandler packageInfoDatabaseHandler; + + public SpdxDocumentDatabaseHandler(Supplier httpClient, String dbName) throws MalformedURLException { + db = new DatabaseConnectorCloudant(httpClient, dbName); + + // Create the repositories + SPDXDocumentRepository = new SpdxDocumentRepository(db); + + sw360db = new DatabaseConnectorCloudant(httpClient, DatabaseSettings.COUCH_DB_DATABASE); + vendorRepository = new VendorRepository(sw360db); + releaseRepository = new ReleaseRepository(sw360db, vendorRepository); + // Create the moderator + moderator = new SpdxDocumentModerator(); + // Create the changelogs + dbChangeLogs = new DatabaseConnectorCloudant(httpClient, DatabaseSettings.COUCH_DB_CHANGE_LOGS); + this.dbHandlerUtil = new DatabaseHandlerUtil(dbChangeLogs); + this.creationInfoDatabaseHandler = new SpdxDocumentCreationInfoDatabaseHandler(httpClient, dbName); + this.packageInfoDatabaseHandler = new SpdxPackageInfoDatabaseHandler(httpClient, dbName); + } + + public List getSPDXDocumentSummary(User user) { + List spdxs = SPDXDocumentRepository.getSPDXDocumentSummary(); + return spdxs; + } + + public SPDXDocument getSPDXDocumentById(String id, User user) throws SW360Exception { + SPDXDocument spdx = SPDXDocumentRepository.get(id); + assertNotNull(spdx, "Could not find SPDX Document by id: " + id); + // Set permissions + if (user != null) { + makePermission(spdx, user).fillPermissions(); + } + return spdx; + } + + public SPDXDocument getSPDXDocumentForEdit(String id, User user) throws SW360Exception { + List moderationRequestsForDocumentId = moderator.getModerationRequestsForDocumentId(id); + + SPDXDocument spdx = getSPDXDocumentById(id, user); + DocumentState documentState; + + if (moderationRequestsForDocumentId.isEmpty()) { + documentState = CommonUtils.getOriginalDocumentState(); + } else { + final String email = user.getEmail(); + Optional moderationRequestOptional = CommonUtils.getFirstModerationRequestOfUser(moderationRequestsForDocumentId, email); + if (moderationRequestOptional.isPresent() + && isInProgressOrPending(moderationRequestOptional.get())) { + ModerationRequest moderationRequest = moderationRequestOptional.get(); + spdx = moderator.updateSPDXDocumentFromModerationRequest(spdx, moderationRequest.getSPDXDocumentAdditions(), moderationRequest.getSPDXDocumentDeletions()); + documentState = CommonUtils.getModeratedDocumentState(moderationRequest); + } else { + documentState = new DocumentState().setIsOriginalDocument(true).setModerationState(moderationRequestsForDocumentId.get(0).getModerationState()); + } + } + spdx.setPermissions(makePermission(spdx, user).getPermissionMap()); + spdx.setDocumentState(documentState); + return spdx; + } + + public AddDocumentRequestSummary addSPDXDocument(SPDXDocument spdx, User user) throws SW360Exception { + AddDocumentRequestSummary requestSummary= new AddDocumentRequestSummary(); + prepareSPDXDocument(spdx); + String releaseId = spdx.getReleaseId(); + Release release = releaseRepository.get(releaseId); + assertNotNull(release, "Could not find Release to add SPDX Document!"); + if (isNotNullEmptyOrWhitespace(release.getSpdxId())){ + log.error("SPDX Document id is not found release!"); + return requestSummary.setRequestStatus(AddDocumentRequestStatus.DUPLICATE) + .setId(release.getSpdxId()); + } + spdx.setCreatedBy(user.getEmail()); + SPDXDocumentRepository.add(spdx); + String spdxId = spdx.getId(); + release.setSpdxId(spdxId); + releaseRepository.update(release); + dbHandlerUtil.addChangeLogs(spdx, null, user.getEmail(), Operation.CREATE, null, Lists.newArrayList(), null, null); + return requestSummary.setRequestStatus(AddDocumentRequestStatus.SUCCESS) + .setId(spdx.getId()); + } + + public RequestStatus updateSPDXDocument(SPDXDocument spdx, User user) throws SW360Exception { + prepareSPDXDocument(spdx); + SPDXDocument actual = SPDXDocumentRepository.get(spdx.getId()); + assertNotNull(actual, "Could not find SPDX Document to update!"); + if (!makePermission(spdx, user).isActionAllowed(RequestedAction.WRITE)) { + if (isChanged(actual, spdx)) { + return moderator.updateSPDXDocument(spdx, user); + } else { + return RequestStatus.SUCCESS; + } + } + SPDXDocumentRepository.update(spdx); + dbHandlerUtil.addChangeLogs(spdx, actual, user.getEmail(), Operation.UPDATE, null, Lists.newArrayList(), null, null); + return RequestStatus.SUCCESS; + } + + public RequestStatus updateSPDXDocumentFromModerationRequest(SPDXDocument spdxAdditions, SPDXDocument spdxDeletions, User user) throws SW360Exception { + try { + SPDXDocument spdx = getSPDXDocumentById(spdxAdditions.getId(), user); + spdx = moderator.updateSPDXDocumentFromModerationRequest(spdx, spdxAdditions, spdxDeletions); + return updateSPDXDocument(spdx, user); + } catch (SW360Exception e) { + log.error("Could not get original SPDX Document when updating from moderation request."); + return RequestStatus.FAILURE; + } + } + + public RequestStatus deleteSPDXDocument(String id, User user) throws SW360Exception { + SPDXDocument spdx = SPDXDocumentRepository.get(id); + assertNotNull(spdx, "Could not find SPDX Document to delete!"); + if (!makePermission(spdx, user).isActionAllowed(RequestedAction.WRITE)) { + return moderator.deleteSPDXDocument(spdx, user); + } + Set packageInfoIds = spdx.getSpdxPackageInfoIds(); + if (packageInfoIds != null) { + for (String packageInfoId : packageInfoIds) { + packageInfoDatabaseHandler.deletePackageInformation(packageInfoId, user); + } + } + + Set fileInfoIds = spdx.getSpdxFileInfoIds(); + if (fileInfoIds != null) { + return RequestStatus.IN_USE; + } + + String documentCreationId = spdx.getSpdxDocumentCreationInfoId(); + if (documentCreationId != null) { + creationInfoDatabaseHandler.deleteDocumentCreationInformation(documentCreationId, user); + } + + spdx.unsetSpdxPackageInfoIds(); + spdx.unsetSpdxDocumentCreationInfoId(); + + SPDXDocumentRepository.remove(id); + String releaseId = spdx.getReleaseId(); + if (isNotNullEmptyOrWhitespace(releaseId)) { + Release release = releaseRepository.get(releaseId); + assertNotNull(release, "Could not remove SPDX Document ID in Release!"); + Release oldRelease = release.deepCopy(); + release.unsetSpdxId(); + releaseRepository.update(release); + dbHandlerUtil.addChangeLogs(release, oldRelease, user.getEmail(), Operation.UPDATE, null, Lists.newArrayList(), spdx.getId(), Operation.SPDX_DOCUMENT_DELETE); + } + return RequestStatus.SUCCESS; + } + + private boolean isChanged(SPDXDocument actual, SPDXDocument update) { + for (SPDXDocument._Fields field : SPDXDocument._Fields.values()) { + if (update.getFieldValue(field) == null && actual.getFieldValue(field) == null) { + continue; + } else if (update.getFieldValue(field) != null && actual.getFieldValue(field) == null){ + return true; + } else if (update.getFieldValue(field) == null && actual.getFieldValue(field) != null){ + return true; + } else if (!actual.getFieldValue(field).equals(update.getFieldValue(field))) { + return true; + } + } + return false; + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentRepository.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentRepository.java new file mode 100644 index 0000000000..25f024b187 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentRepository.java @@ -0,0 +1,40 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.document; + +import org.eclipse.sw360.components.summary.SpdxDocumentSummary; +import org.eclipse.sw360.components.summary.SummaryType; +import org.eclipse.sw360.datahandler.cloudantclient.DatabaseConnectorCloudant; +import org.eclipse.sw360.datahandler.couchdb.SummaryAwareRepository; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; + +import com.cloudant.client.api.model.DesignDocument.MapReduce; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SpdxDocumentRepository extends SummaryAwareRepository { + + private static final String ALL = "function(doc) { if (doc.type == 'SPDXDocument') emit(null, doc._id) }"; + + public SpdxDocumentRepository(DatabaseConnectorCloudant db) { + super(SPDXDocument.class, db, new SpdxDocumentSummary()); + Map views = new HashMap(); + views.put("all", createMapReduce(ALL, null)); + initStandardDesignDocument(views, db); + } + + public List getSPDXDocumentSummary() { + return makeSummary(SummaryType.SUMMARY, getAllIds()); + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentSearchHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentSearchHandler.java new file mode 100644 index 0000000000..f440bf53a2 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/document/SpdxDocumentSearchHandler.java @@ -0,0 +1,48 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.document; + +import org.eclipse.sw360.datahandler.couchdb.lucene.LuceneAwareDatabaseConnector; +import org.eclipse.sw360.datahandler.couchdb.lucene.LuceneSearchView; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.ektorp.http.HttpClient; + +import com.cloudant.client.api.CloudantClient; + +import java.io.IOException; +import java.util.List; +import java.util.function.Supplier; + +import static org.eclipse.sw360.datahandler.couchdb.lucene.LuceneAwareDatabaseConnector.prepareWildcardQuery; + +public class SpdxDocumentSearchHandler { + + private static final LuceneSearchView luceneSearchView + = new LuceneSearchView("lucene", "SPDXDocument", + "function(doc) {" + + " if(doc.type == 'SPDXDocument') { " + + " var ret = new Document();" + + " ret.add(doc._id); " + + " return ret;" + + " }" + + "}"); + + private final LuceneAwareDatabaseConnector connector; + + public SpdxDocumentSearchHandler(Supplier httpClient, Supplier cClient, String dbName) throws IOException { + connector = new LuceneAwareDatabaseConnector(httpClient, cClient, dbName); + connector.addView(luceneSearchView); + } + + public List search(String searchText) { + return connector.searchView(SPDXDocument.class, luceneSearchView, prepareWildcardQuery(searchText)); + } +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoDatabaseHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoDatabaseHandler.java new file mode 100644 index 0000000000..9da2667d05 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoDatabaseHandler.java @@ -0,0 +1,191 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.documentcreationinfo; + +import com.cloudant.client.api.CloudantClient; + +import org.eclipse.sw360.datahandler.cloudantclient.DatabaseConnectorCloudant; +import org.eclipse.sw360.datahandler.db.spdx.document.SpdxDocumentRepository; +import org.eclipse.sw360.datahandler.thrift.*; +import org.eclipse.sw360.datahandler.thrift.users.RequestedAction; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; +import org.eclipse.sw360.datahandler.thrift.changelogs.*; +import org.eclipse.sw360.datahandler.db.DatabaseHandlerUtil; +import org.eclipse.sw360.datahandler.entitlement.SpdxDocumentCreationInfoModerator; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; +import org.eclipse.sw360.datahandler.common.CommonUtils; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import java.net.MalformedURLException; +import java.util.*; +import java.util.function.Supplier; +import com.google.common.collect.Lists; + +import org.eclipse.sw360.datahandler.common.DatabaseSettings; +import static org.eclipse.sw360.datahandler.common.CommonUtils.*; +import static org.eclipse.sw360.datahandler.common.SW360Assert.assertNotNull; +import static org.eclipse.sw360.datahandler.permissions.PermissionUtils.makePermission; +import static org.eclipse.sw360.datahandler.thrift.ThriftValidate.prepareSpdxDocumentCreationInfo; + +public class SpdxDocumentCreationInfoDatabaseHandler { + + private static final Logger log = LogManager.getLogger(SpdxDocumentCreationInfoDatabaseHandler.class); + + /** + * Connection to the couchDB database + */ + private final DatabaseConnectorCloudant db; + private final DatabaseConnectorCloudant dbChangeLogs; + + private final SpdxDocumentCreationInfoRepository SPDXDocumentCreationInfoRepository; + private final SpdxDocumentRepository SPDXDocumentRepository; + private DatabaseHandlerUtil dbHandlerUtil; + private final SpdxDocumentCreationInfoModerator moderator; + + public SpdxDocumentCreationInfoDatabaseHandler(Supplier httpClient, String dbName) throws MalformedURLException { + db = new DatabaseConnectorCloudant(httpClient, dbName); + + // Create the repositories + SPDXDocumentCreationInfoRepository = new SpdxDocumentCreationInfoRepository(db); + SPDXDocumentRepository = new SpdxDocumentRepository(db); + // Create the moderator + moderator = new SpdxDocumentCreationInfoModerator(); + // Create the changelogs + dbChangeLogs = new DatabaseConnectorCloudant(httpClient, DatabaseSettings.COUCH_DB_CHANGE_LOGS); + this.dbHandlerUtil = new DatabaseHandlerUtil(dbChangeLogs); + } + + public List getDocumentCreationInformationSummary(User user) { + List documentCreationInfos = SPDXDocumentCreationInfoRepository.getDocumentCreationInformationSummary(); + return documentCreationInfos; + } + + public DocumentCreationInformation getDocumentCreationInformationById(String id, User user) throws SW360Exception { + DocumentCreationInformation documentCreationInfo = SPDXDocumentCreationInfoRepository.get(id); + assertNotNull(documentCreationInfo, "Could not find SPDX Document Creation Info by id: " + id); + // Set permissions + if (user != null) { + makePermission(documentCreationInfo, user).fillPermissions(); + } + return documentCreationInfo; + } + + public DocumentCreationInformation getDocumentCreationInfoForEdit(String id, User user) throws SW360Exception { + List moderationRequestsForDocumentId = moderator.getModerationRequestsForDocumentId(id); + + DocumentCreationInformation documentCreationInfo = getDocumentCreationInformationById(id, user); + DocumentState documentState; + + if (moderationRequestsForDocumentId.isEmpty()) { + documentState = CommonUtils.getOriginalDocumentState(); + } else { + final String email = user.getEmail(); + Optional moderationRequestOptional = CommonUtils.getFirstModerationRequestOfUser(moderationRequestsForDocumentId, email); + if (moderationRequestOptional.isPresent() + && isInProgressOrPending(moderationRequestOptional.get())){ + ModerationRequest moderationRequest = moderationRequestOptional.get(); + documentCreationInfo = moderator.updateSpdxDocumentCreationInfoFromModerationRequest(documentCreationInfo, moderationRequest.getDocumentCreationInfoAdditions(), moderationRequest.getDocumentCreationInfoDeletions()); + documentState = CommonUtils.getModeratedDocumentState(moderationRequest); + } else { + documentState = new DocumentState().setIsOriginalDocument(true).setModerationState(moderationRequestsForDocumentId.get(0).getModerationState()); + } + } + documentCreationInfo.setPermissions(makePermission(documentCreationInfo, user).getPermissionMap()); + documentCreationInfo.setDocumentState(documentState); + return documentCreationInfo; + } + + public AddDocumentRequestSummary addDocumentCreationInformation(DocumentCreationInformation documentCreationInfo, User user) throws SW360Exception { + AddDocumentRequestSummary requestSummary= new AddDocumentRequestSummary(); + prepareSpdxDocumentCreationInfo(documentCreationInfo); + String spdxDocumentId = documentCreationInfo.getSpdxDocumentId(); + SPDXDocument spdxDocument = SPDXDocumentRepository.get(spdxDocumentId); + assertNotNull(spdxDocument, "Could not find SPDX Document to add SPDX Document Creation Info!"); + if (isNotNullEmptyOrWhitespace(spdxDocument.getSpdxDocumentCreationInfoId())) { + log.error("SPDX Document Creation existed in SPDX Document!"); + return requestSummary.setRequestStatus(AddDocumentRequestStatus.DUPLICATE) + .setId(spdxDocumentId); + } + documentCreationInfo.setCreatedBy(user.getEmail()); + SPDXDocumentCreationInfoRepository.add(documentCreationInfo); + String documentCreationInfoId = documentCreationInfo.getId(); + spdxDocument.setSpdxDocumentCreationInfoId(documentCreationInfoId); + SPDXDocumentRepository.update(spdxDocument); + dbHandlerUtil.addChangeLogs(documentCreationInfo, null, user.getEmail(), Operation.CREATE, null, Lists.newArrayList(), null, null); + return requestSummary.setRequestStatus(AddDocumentRequestStatus.SUCCESS) + .setId(documentCreationInfoId); + } + + public RequestStatus updateDocumentCreationInformation(DocumentCreationInformation documentCreationInfo, User user) throws SW360Exception { + DocumentCreationInformation actual = SPDXDocumentCreationInfoRepository.get(documentCreationInfo.getId()); + assertNotNull(actual, "Could not find SPDX Document Creation Information to update!"); + prepareSpdxDocumentCreationInfo(documentCreationInfo); + if (!makePermission(documentCreationInfo, user).isActionAllowed(RequestedAction.WRITE)) { + if (isChanged(actual, documentCreationInfo)) { + return moderator.updateSpdxDocumentCreationInfo(documentCreationInfo, user); + } else { + return RequestStatus.SUCCESS; + } + } + SPDXDocumentCreationInfoRepository.update(documentCreationInfo); + dbHandlerUtil.addChangeLogs(documentCreationInfo, actual, user.getEmail(), Operation.UPDATE, null, Lists.newArrayList(), null, null); + return RequestStatus.SUCCESS; + } + + public RequestStatus updateDocumentCreationInfomationFromModerationRequest(DocumentCreationInformation documentCreationInfoAdditions, DocumentCreationInformation documentCreationInfoDeletions, User user) throws SW360Exception { + try { + DocumentCreationInformation documentCreationInfo = getDocumentCreationInformationById(documentCreationInfoAdditions.getId(), user); + documentCreationInfo = moderator.updateSpdxDocumentCreationInfoFromModerationRequest(documentCreationInfo, documentCreationInfoAdditions, documentCreationInfoDeletions); + return updateDocumentCreationInformation(documentCreationInfo, user); + } catch (SW360Exception e) { + log.error("Could not get original SPDX Document creation info when updating from moderation request."); + return RequestStatus.FAILURE; + } + } + + public RequestStatus deleteDocumentCreationInformation(String id, User user) throws SW360Exception { + DocumentCreationInformation documentCreationInfo = SPDXDocumentCreationInfoRepository.get(id); + assertNotNull(documentCreationInfo, "Could not find SPDX Document Creation Information to delete!"); + if (!makePermission(documentCreationInfo, user).isActionAllowed(RequestedAction.WRITE)) { + return moderator.deleteSpdxDocumentCreationInfo(documentCreationInfo, user); + } + SPDXDocumentCreationInfoRepository.remove(documentCreationInfo); + String spdxDocumentId = documentCreationInfo.getSpdxDocumentId(); + if (isNotNullEmptyOrWhitespace(spdxDocumentId)) { + SPDXDocument spdxDocument = SPDXDocumentRepository.get(spdxDocumentId); + assertNotNull(spdxDocument, "Could not remove SPDX Document Creation Info ID in SPDX Document!"); + SPDXDocument oldSpdxDocument = spdxDocument.deepCopy(); + spdxDocument.unsetSpdxDocumentCreationInfoId(); + SPDXDocumentRepository.update(spdxDocument); + dbHandlerUtil.addChangeLogs(spdxDocument, oldSpdxDocument, user.getEmail(), Operation.UPDATE, null, Lists.newArrayList(), documentCreationInfo.getId(), Operation.SPDX_DOCUMENT_CREATION_INFO_DELETE); + } + return RequestStatus.SUCCESS; + } + + private boolean isChanged(DocumentCreationInformation actual, DocumentCreationInformation update) { + + for (DocumentCreationInformation._Fields field : DocumentCreationInformation._Fields.values()) { + if(update.getFieldValue(field) == null) { + continue; + } else if (actual.getFieldValue(field) == null) { + return true; + } else if (!actual.getFieldValue(field).equals(update.getFieldValue(field))) { + return true; + } + } + + return false; + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoRepository.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoRepository.java new file mode 100644 index 0000000000..8978eda05f --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoRepository.java @@ -0,0 +1,40 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.documentcreationinfo; + +import org.eclipse.sw360.components.summary.DocumentCreationInformationSummary; +import org.eclipse.sw360.components.summary.SummaryType; +import org.eclipse.sw360.datahandler.cloudantclient.DatabaseConnectorCloudant; +import org.eclipse.sw360.datahandler.couchdb.SummaryAwareRepository; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; + +import com.cloudant.client.api.model.DesignDocument.MapReduce; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SpdxDocumentCreationInfoRepository extends SummaryAwareRepository { + + private static final String ALL = "function(doc) { if (doc.type == 'documentCreationInformation') emit(null, doc._id) }"; + + public SpdxDocumentCreationInfoRepository(DatabaseConnectorCloudant db) { + super(DocumentCreationInformation.class, db, new DocumentCreationInformationSummary()); + Map views = new HashMap(); + views.put("all", createMapReduce(ALL, null)); + initStandardDesignDocument(views, db); + } + + public List getDocumentCreationInformationSummary() { + return makeSummary(SummaryType.SUMMARY, getAllIds()); + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoSearchHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoSearchHandler.java new file mode 100644 index 0000000000..d863e38f6f --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/documentcreationinfo/SpdxDocumentCreationInfoSearchHandler.java @@ -0,0 +1,48 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.documentcreationinfo; + +import org.eclipse.sw360.datahandler.couchdb.lucene.LuceneAwareDatabaseConnector; +import org.eclipse.sw360.datahandler.couchdb.lucene.LuceneSearchView; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation; +import org.ektorp.http.HttpClient; + +import com.cloudant.client.api.CloudantClient; + +import java.io.IOException; +import java.util.List; +import java.util.function.Supplier; + +import static org.eclipse.sw360.datahandler.couchdb.lucene.LuceneAwareDatabaseConnector.prepareWildcardQuery; + +public class SpdxDocumentCreationInfoSearchHandler { + + private static final LuceneSearchView luceneSearchView + = new LuceneSearchView("lucene", "documentCreationInformation", + "function(doc) {" + + " if(doc.type == 'documentCreationInformation') { " + + " var ret = new Document();" + + " ret.add(doc._id); " + + " return ret;" + + " }" + + "}"); + + private final LuceneAwareDatabaseConnector connector; + + public SpdxDocumentCreationInfoSearchHandler(Supplier httpClient, Supplier cClient, String dbName) throws IOException { + connector = new LuceneAwareDatabaseConnector(httpClient, cClient, dbName); + connector.addView(luceneSearchView); + } + + public List search(String searchText) { + return connector.searchView(DocumentCreationInformation.class, luceneSearchView, prepareWildcardQuery(searchText)); + } +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoDatabaseHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoDatabaseHandler.java new file mode 100644 index 0000000000..4ee66bea41 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoDatabaseHandler.java @@ -0,0 +1,245 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.packageinfo; + +import com.cloudant.client.api.CloudantClient; + +import org.eclipse.sw360.datahandler.cloudantclient.DatabaseConnectorCloudant; +import org.eclipse.sw360.datahandler.db.spdx.document.SpdxDocumentRepository; +import org.eclipse.sw360.datahandler.thrift.*; +import org.eclipse.sw360.datahandler.thrift.users.RequestedAction; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.*; +import org.eclipse.sw360.datahandler.thrift.changelogs.*; +import org.eclipse.sw360.datahandler.db.DatabaseHandlerUtil; +import org.eclipse.sw360.datahandler.entitlement.SpdxPackageInfoModerator; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; +import org.eclipse.sw360.datahandler.common.CommonUtils; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import java.net.MalformedURLException; +import java.util.*; +import java.util.function.Supplier; +import com.google.common.collect.Lists; + +import org.eclipse.sw360.datahandler.common.DatabaseSettings; +import static org.eclipse.sw360.datahandler.common.CommonUtils.*; +import static org.eclipse.sw360.datahandler.common.SW360Assert.assertNotNull; +import static org.eclipse.sw360.datahandler.permissions.PermissionUtils.makePermission; +import static org.eclipse.sw360.datahandler.thrift.ThriftValidate.prepareSpdxPackageInfo; + +public class SpdxPackageInfoDatabaseHandler { + + private static final Logger log = LogManager.getLogger(SpdxPackageInfoDatabaseHandler.class); + private final DatabaseConnectorCloudant dbChangeLogs; + + /** + * Connection to the couchDB database + */ + private final DatabaseConnectorCloudant db; + + private final SpdxPackageInfoRepository PackageInfoRepository; + private final SpdxDocumentRepository SPDXDocumentRepository; + private DatabaseHandlerUtil dbHandlerUtil; + private final SpdxPackageInfoModerator moderator; + + public SpdxPackageInfoDatabaseHandler(Supplier httpClient, String dbName) throws MalformedURLException { + db = new DatabaseConnectorCloudant(httpClient, dbName); + + // Create the repositories + PackageInfoRepository = new SpdxPackageInfoRepository(db); + SPDXDocumentRepository = new SpdxDocumentRepository(db); + + // Create the moderator + moderator = new SpdxPackageInfoModerator(); + // Create the changelogs + dbChangeLogs = new DatabaseConnectorCloudant(httpClient, DatabaseSettings.COUCH_DB_CHANGE_LOGS); + this.dbHandlerUtil = new DatabaseHandlerUtil(dbChangeLogs); + } + + public List getPackageInformationSummary(User user) { + List packageInfos = PackageInfoRepository.getPackageInformationSummary(); + return packageInfos; + } + + public PackageInformation getPackageInformationById(String id, User user) throws SW360Exception { + PackageInformation packageInfo = PackageInfoRepository.get(id); + assertNotNull(packageInfo, "Could not find SPDX Package Info by id: " + id); + // Set permissions + if (user != null) { + makePermission(packageInfo, user).fillPermissions(); + } + return packageInfo; + } + + public PackageInformation getPackageInformationForEdit(String id, User user) throws SW360Exception { + List moderationRequestsForDocumentId = moderator.getModerationRequestsForDocumentId(id); + + PackageInformation packageInfo = getPackageInformationById(id, user); + DocumentState documentState; + + if (moderationRequestsForDocumentId.isEmpty()) { + documentState = CommonUtils.getOriginalDocumentState(); + } else { + final String email = user.getEmail(); + Optional moderationRequestOptional = CommonUtils.getFirstModerationRequestOfUser(moderationRequestsForDocumentId, email); + if (moderationRequestOptional.isPresent() + && isInProgressOrPending(moderationRequestOptional.get())) { + ModerationRequest moderationRequest = moderationRequestOptional.get(); + packageInfo = moderator.updateSpdxPackageInfoFromModerationRequest(packageInfo, moderationRequest.getPackageInfoAdditions(), moderationRequest.getPackageInfoDeletions()); + documentState = CommonUtils.getModeratedDocumentState(moderationRequest); + } else { + documentState = new DocumentState().setIsOriginalDocument(true).setModerationState(moderationRequestsForDocumentId.get(0).getModerationState()); + } + } + packageInfo.setPermissions(makePermission(packageInfo, user).getPermissionMap()); + packageInfo.setDocumentState(documentState); + return packageInfo; + } + + public AddDocumentRequestSummary addPackageInformation(PackageInformation packageInfo, User user) throws SW360Exception { + AddDocumentRequestSummary requestSummary = new AddDocumentRequestSummary(); + prepareSpdxPackageInfo(packageInfo); + packageInfo.setCreatedBy(user.getEmail()); + PackageInfoRepository.add(packageInfo); + String packageInfoId = packageInfo.getId(); + String spdxDocumentId = packageInfo.getSpdxDocumentId(); + SPDXDocument spdxDocument = SPDXDocumentRepository.get(spdxDocumentId); + assertNotNull(spdxDocument, "Could not find SPDX Document by id: " + spdxDocumentId); + Set spdxPackageInfoIds = new HashSet<>(); + if (spdxDocument.getSpdxPackageInfoIds() != null) { + spdxPackageInfoIds = spdxDocument.getSpdxPackageInfoIds(); + } + spdxPackageInfoIds.add(packageInfoId); + spdxDocument.setSpdxPackageInfoIds(spdxPackageInfoIds); + SPDXDocumentRepository.update(spdxDocument); + dbHandlerUtil.addChangeLogs(packageInfo, null, user.getEmail(), Operation.CREATE, null, Lists.newArrayList(), null, null); + return requestSummary.setRequestStatus(AddDocumentRequestStatus.SUCCESS).setId(packageInfoId); + } + + public AddDocumentRequestSummary addPackageInformations(Set packageInfos, User user) throws SW360Exception { + AddDocumentRequestSummary requestSummary = new AddDocumentRequestSummary(); + String spdxDocumentId = packageInfos.iterator().next().getSpdxDocumentId(); + SPDXDocument spdxDocument = SPDXDocumentRepository.get(spdxDocumentId); + assertNotNull(spdxDocument, "Could not find SPDX Document by id: " + spdxDocumentId); + Set packageInfoIds = new HashSet<>(); + if (spdxDocument.getSpdxPackageInfoIds() != null) { + packageInfoIds = spdxDocument.getSpdxPackageInfoIds(); + } + for (PackageInformation packageInfo : packageInfos) { + prepareSpdxPackageInfo(packageInfo); + packageInfo.setCreatedBy(user.getEmail()); + PackageInfoRepository.add(packageInfo); + packageInfoIds.add(packageInfo.getId()); + dbHandlerUtil.addChangeLogs(packageInfo, null, user.getEmail(), Operation.CREATE, null, Lists.newArrayList(), null, null); + } + spdxDocument.setSpdxPackageInfoIds(packageInfoIds); + SPDXDocumentRepository.update(spdxDocument); + return requestSummary.setRequestStatus(AddDocumentRequestStatus.SUCCESS).setId(spdxDocumentId); + } + + public RequestStatus updatePackageInformation(PackageInformation packageInfo, User user) throws SW360Exception { + prepareSpdxPackageInfo(packageInfo); + PackageInformation actual = PackageInfoRepository.get(packageInfo.getId()); + assertNotNull(actual, "Could not find SPDX Package Information to update!"); + if (!makePermission(packageInfo, user).isActionAllowed(RequestedAction.WRITE)) { + if (isChanged(actual, packageInfo)) { + return moderator.updateSpdxPackageInfo(packageInfo, user); + } else { + return RequestStatus.SUCCESS; + } + } + PackageInfoRepository.update(packageInfo); + dbHandlerUtil.addChangeLogs(packageInfo, actual, user.getEmail(), Operation.UPDATE, null, Lists.newArrayList(), null, null); + return RequestStatus.SUCCESS; + } + + public RequestSummary updatePackageInformations(Set packageInfos, User user) throws SW360Exception { + int countPackagesSendToModerator = 0; + for (PackageInformation packageInfo : packageInfos) { + PackageInformation actual = PackageInfoRepository.get(packageInfo.getId()); + assertNotNull(actual, "Could not find SPDX Package Information to update!"); + prepareSpdxPackageInfo(packageInfo); + if (!makePermission(packageInfos, user).isActionAllowed(RequestedAction.WRITE)) { + if (moderator.updateSpdxPackageInfo(packageInfo, user) == RequestStatus.SENT_TO_MODERATOR) { + countPackagesSendToModerator++; + } + } else { + PackageInfoRepository.update(packageInfo); + dbHandlerUtil.addChangeLogs(packageInfo, actual, user.getEmail(), Operation.UPDATE, null, Lists.newArrayList(), null, null); + } + } + RequestSummary requestSummary = new RequestSummary(); + if (countPackagesSendToModerator == packageInfos.size()) { + requestSummary.setRequestStatus(RequestStatus.SENT_TO_MODERATOR); + } else { + String message = "Send to moderator request " + countPackagesSendToModerator; + requestSummary.setMessage(message) + .setTotalAffectedElements(countPackagesSendToModerator) + .setTotalElements(packageInfos.size()) + .setRequestStatus(RequestStatus.SUCCESS); + } + return requestSummary; + } + + public RequestStatus updatePackageInfomationFromModerationRequest(PackageInformation packageInfoAdditions, PackageInformation packageInfoDeletions, User user) throws SW360Exception { + try { + PackageInformation packageInformation = getPackageInformationById(packageInfoAdditions.getId(), user); + packageInformation = moderator.updateSpdxPackageInfoFromModerationRequest(packageInformation, packageInfoAdditions, packageInfoDeletions); + return updatePackageInformation(packageInformation, user); + } catch (SW360Exception e) { + log.error("Could not get original SPDX Package info when updating from moderation request."); + return RequestStatus.FAILURE; + } + } + + public RequestStatus deletePackageInformation(String id, User user) throws SW360Exception { + PackageInformation packageInfo = PackageInfoRepository.get(id); + assertNotNull(packageInfo, "Could not find SPDX Package Information to delete!"); + if (!makePermission(packageInfo, user).isActionAllowed(RequestedAction.WRITE)) { + return moderator.deleteSpdxPackageInfo(packageInfo, user); + } + PackageInfoRepository.remove(packageInfo); + String spdxDocumentId = packageInfo.getSpdxDocumentId(); + SPDXDocument spdxDocument = SPDXDocumentRepository.get(spdxDocumentId); + assertNotNull(spdxDocument, "Could not find SPDX Document to remove Package Info!"); + SPDXDocument oldSpdxDocument = spdxDocument.deepCopy(); + Set packageInfoIds = spdxDocument.getSpdxPackageInfoIds(); + if (packageInfoIds != null) { + packageInfoIds.remove(id); + spdxDocument.setSpdxPackageInfoIds(packageInfoIds); + SPDXDocumentRepository.update(spdxDocument); + dbHandlerUtil.addChangeLogs(spdxDocument, oldSpdxDocument, user.getEmail(), Operation.UPDATE, null, Lists.newArrayList(), packageInfo.getId(), Operation.SPDX_PACKAGE_INFO_DELETE); + } else { + log.warn("Could not remove Package Id from SPDX Documnet"); + } + + return RequestStatus.SUCCESS; + } + + private boolean isChanged(PackageInformation actual, PackageInformation update) { + + for (PackageInformation._Fields field : PackageInformation._Fields.values()) { + if (update.getFieldValue(field) == null) { + continue; + } else if (actual.getFieldValue(field) == null) { + return true; + } else if (!actual.getFieldValue(field).equals(update.getFieldValue(field))) { + return true; + } + } + + return false; + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoRepository.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoRepository.java new file mode 100644 index 0000000000..06554cd9c1 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoRepository.java @@ -0,0 +1,40 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.packageinfo; + +import org.eclipse.sw360.components.summary.PackageInformationSummary; +import org.eclipse.sw360.components.summary.SummaryType; +import org.eclipse.sw360.datahandler.cloudantclient.DatabaseConnectorCloudant; +import org.eclipse.sw360.datahandler.couchdb.SummaryAwareRepository; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.*; + +import com.cloudant.client.api.model.DesignDocument.MapReduce; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SpdxPackageInfoRepository extends SummaryAwareRepository { + + private static final String ALL = "function(doc) { if (doc.type == 'packageInformation') emit(null, doc._id) }"; + + public SpdxPackageInfoRepository(DatabaseConnectorCloudant db) { + super(PackageInformation.class, db, new PackageInformationSummary()); + Map views = new HashMap(); + views.put("all", createMapReduce(ALL, null)); + initStandardDesignDocument(views, db); + } + + public List getPackageInformationSummary() { + return makeSummary(SummaryType.SUMMARY, getAllIds()); + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoSearchHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoSearchHandler.java new file mode 100644 index 0000000000..70b5b2d61f --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/spdx/packageinfo/SpdxPackageInfoSearchHandler.java @@ -0,0 +1,48 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.db.spdx.packageinfo; + +import org.eclipse.sw360.datahandler.couchdb.lucene.LuceneAwareDatabaseConnector; +import org.eclipse.sw360.datahandler.couchdb.lucene.LuceneSearchView; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.*; +import org.ektorp.http.HttpClient; + +import com.cloudant.client.api.CloudantClient; + +import java.io.IOException; +import java.util.List; +import java.util.function.Supplier; + +import static org.eclipse.sw360.datahandler.couchdb.lucene.LuceneAwareDatabaseConnector.prepareWildcardQuery; + +public class SpdxPackageInfoSearchHandler { + + private static final LuceneSearchView luceneSearchView + = new LuceneSearchView("lucene", "packageInformation", + "function(doc) {" + + " if(doc.type == 'packageInformation') { " + + " var ret = new Document();" + + " ret.add(doc._id); " + + " return ret;" + + " }" + + "}"); + + private final LuceneAwareDatabaseConnector connector; + + public SpdxPackageInfoSearchHandler(Supplier httpClient, Supplier cClient, String dbName) throws IOException { + connector = new LuceneAwareDatabaseConnector(httpClient, cClient, dbName); + connector.addView(luceneSearchView); + } + + public List search(String searchText) { + return connector.searchView(PackageInformation.class, luceneSearchView, prepareWildcardQuery(searchText)); + } +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxDocumentCreationInfoModerator.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxDocumentCreationInfoModerator.java new file mode 100644 index 0000000000..7490589c8a --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxDocumentCreationInfoModerator.java @@ -0,0 +1,156 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.entitlement; + +import org.eclipse.sw360.datahandler.common.Moderator; +import org.eclipse.sw360.datahandler.thrift.RequestStatus; +import org.eclipse.sw360.datahandler.thrift.ThriftClients; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.Creator; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.ExternalDocumentReferences; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationService; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.apache.logging.log4j.Logger; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.apache.logging.log4j.LogManager; +import org.apache.thrift.TException; + +public class SpdxDocumentCreationInfoModerator + extends Moderator { + + private static final Logger log = LogManager.getLogger(SpdxDocumentCreationInfoModerator.class); + + public SpdxDocumentCreationInfoModerator(ThriftClients thriftClients) { + super(thriftClients); + } + + public SpdxDocumentCreationInfoModerator() { + super(new ThriftClients()); + } + + public RequestStatus updateSpdxDocumentCreationInfo(DocumentCreationInformation documentCreationInfo, User user) { + + try { + ModerationService.Iface client = thriftClients.makeModerationClient(); + client.createSpdxDocumentCreationInfoRequest(documentCreationInfo, user); + return RequestStatus.SENT_TO_MODERATOR; + } catch (TException e) { + log.error("Could not moderate SPDX Document Creation Info " + documentCreationInfo.getId() + " for User " + + user.getEmail(), e); + return RequestStatus.FAILURE; + } + } + + public RequestStatus deleteSpdxDocumentCreationInfo(DocumentCreationInformation documentCreationInfo, User user) { + try { + ModerationService.Iface client = thriftClients.makeModerationClient(); + client.createSpdxDocumentCreationInfoDeleteRequest(documentCreationInfo, user); + return RequestStatus.SENT_TO_MODERATOR; + } catch (TException e) { + log.error("Could not moderate delete SPDX document creation information" + documentCreationInfo.getId() + " for User " + + user.getEmail(), e); + return RequestStatus.FAILURE; + } + } + + public DocumentCreationInformation updateSpdxDocumentCreationInfoFromModerationRequest( + DocumentCreationInformation documentCreationInfo, DocumentCreationInformation documentCreationInfoAdditions, + DocumentCreationInformation documentCreationInfoDeletions) { + for (DocumentCreationInformation._Fields field : DocumentCreationInformation._Fields.values()) { + if (documentCreationInfoAdditions.getFieldValue(field) == null + && documentCreationInfoDeletions.getFieldValue(field) == null) { + continue; + } + switch (field) { + case ID: + case REVISION: + case TYPE: + break; + case EXTERNAL_DOCUMENT_REFS: + documentCreationInfo = updateExternalDocumentRefs(documentCreationInfo, documentCreationInfoAdditions, documentCreationInfoDeletions); + break; + case CREATOR: + documentCreationInfo = updateCreator(documentCreationInfo, documentCreationInfoAdditions, documentCreationInfoDeletions); + break; + default: + documentCreationInfo = updateBasicField(field, DocumentCreationInformation.metaDataMap.get(field), + documentCreationInfo, documentCreationInfoAdditions, documentCreationInfoDeletions); + } + + } + return documentCreationInfo; + } + + private DocumentCreationInformation updateExternalDocumentRefs(DocumentCreationInformation documentCreationInfo, + DocumentCreationInformation documentCreationInfoAdditions, + DocumentCreationInformation documentCreationInfoDeletions) { + Set actuals = documentCreationInfo.getExternalDocumentRefs(); + Iterator additionsIterator = documentCreationInfoAdditions.getExternalDocumentRefsIterator(); + Iterator deletionsIterator = documentCreationInfoDeletions.getExternalDocumentRefsIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return documentCreationInfo; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + ExternalDocumentReferences additions = additionsIterator.next(); + ExternalDocumentReferences actual = new ExternalDocumentReferences(); + for (ExternalDocumentReferences._Fields field : ExternalDocumentReferences._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while (deletionsIterator.hasNext()) { + ExternalDocumentReferences deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + documentCreationInfo.setExternalDocumentRefs(actuals); + return documentCreationInfo; + } + + private DocumentCreationInformation updateCreator(DocumentCreationInformation documentCreationInfo, + DocumentCreationInformation documentCreationInfoAdditions, + DocumentCreationInformation documentCreationInfoDeletions) { + Set actuals = documentCreationInfo.getCreator(); + Iterator additionsIterator = documentCreationInfoAdditions.getCreatorIterator(); + Iterator deletionsIterator = documentCreationInfoDeletions.getCreatorIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return documentCreationInfo; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + Creator additions = additionsIterator.next(); + Creator actual = new Creator(); + for (Creator._Fields field : Creator._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while (deletionsIterator.hasNext()) { + Creator deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + documentCreationInfo.setCreator(actuals); + return documentCreationInfo; + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxDocumentModerator.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxDocumentModerator.java new file mode 100644 index 0000000000..23f6a1a009 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxDocumentModerator.java @@ -0,0 +1,210 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.entitlement; + +import org.eclipse.sw360.datahandler.common.Moderator; +import org.eclipse.sw360.datahandler.thrift.RequestStatus; +import org.eclipse.sw360.datahandler.thrift.ThriftClients; +import org.eclipse.sw360.datahandler.thrift.spdx.annotations.Annotations; +import org.eclipse.sw360.datahandler.thrift.spdx.otherlicensinginformationdetected.OtherLicensingInformationDetected; +import org.eclipse.sw360.datahandler.thrift.spdx.relationshipsbetweenspdxelements.RelationshipsBetweenSPDXElements; +import org.eclipse.sw360.datahandler.thrift.spdx.snippetinformation.SnippetInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationService; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.apache.logging.log4j.Logger; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.apache.logging.log4j.LogManager; +import org.apache.thrift.TException; + +public class SpdxDocumentModerator extends Moderator { + + private static final Logger log = LogManager.getLogger(SpdxDocumentModerator.class); + + public SpdxDocumentModerator(ThriftClients thriftClients) { + super(thriftClients); + } + + public SpdxDocumentModerator() { + super(new ThriftClients()); + } + + public RequestStatus updateSPDXDocument(SPDXDocument spdx, User user) { + + try { + ModerationService.Iface client = thriftClients.makeModerationClient(); + client.createSPDXDocumentRequest(spdx, user); + return RequestStatus.SENT_TO_MODERATOR; + } catch (TException e) { + log.error("Could not moderate SPDX Document " + spdx.getId() + " for User " + user.getEmail(), e); + return RequestStatus.FAILURE; + } + } + + public RequestStatus deleteSPDXDocument(SPDXDocument spdx, User user) { + try { + ModerationService.Iface client = thriftClients.makeModerationClient(); + client.createSPDXDocumentDeleteRequest(spdx, user); + return RequestStatus.SENT_TO_MODERATOR; + } catch (TException e) { + log.error("Could not moderate delete SPDX document " + spdx.getId() + " for User " + user.getEmail(), e); + return RequestStatus.FAILURE; + } + } + + public SPDXDocument updateSPDXDocumentFromModerationRequest(SPDXDocument spdx, SPDXDocument spdxAdditions, SPDXDocument spdxDeletions) { + for (SPDXDocument._Fields field : SPDXDocument._Fields.values()) { + if (spdxAdditions.getFieldValue(field) == null && spdxDeletions.getFieldValue(field) == null) { + continue; + } + switch (field) { + case ID: + case REVISION: + case TYPE: + break; + case OTHER_LICENSING_INFORMATION_DETECTEDS: + spdx = updateOtherLicensingInformationDetecteds(spdx, spdxAdditions, spdxDeletions); + break; + case RELATIONSHIPS: + spdx = updateRelationships(spdx, spdxAdditions, spdxDeletions); + break; + case ANNOTATIONS: + spdx = updateAnnotaions(spdx, spdxAdditions, spdxDeletions); + break; + case SNIPPETS: + spdx = updateSnippets(spdx, spdxAdditions, spdxDeletions); + break; + default: + spdx = updateBasicField(field, SPDXDocument.metaDataMap.get(field), spdx, spdxAdditions, spdxDeletions); + } + + } + return spdx; + } + + private SPDXDocument updateOtherLicensingInformationDetecteds(SPDXDocument spdx, SPDXDocument spdxAdditions, SPDXDocument spdxDeletions) { + Set actuals = spdx.getOtherLicensingInformationDetecteds(); + Iterator additionsIterator = spdxAdditions.getOtherLicensingInformationDetectedsIterator(); + Iterator deletionsIterator = spdxDeletions.getOtherLicensingInformationDetectedsIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return spdx; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + OtherLicensingInformationDetected additions = additionsIterator.next(); + OtherLicensingInformationDetected actual = new OtherLicensingInformationDetected(); + for (OtherLicensingInformationDetected._Fields field : OtherLicensingInformationDetected._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while(deletionsIterator.hasNext()) { + OtherLicensingInformationDetected deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + + spdx.setOtherLicensingInformationDetecteds(actuals); + return spdx; + } + + private SPDXDocument updateRelationships(SPDXDocument spdx, SPDXDocument spdxAdditions, SPDXDocument spdxDeletions) { + Set actuals = spdx.getRelationships(); + Iterator additionsIterator = spdxAdditions.getRelationshipsIterator(); + Iterator deletionsIterator = spdxDeletions.getRelationshipsIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return spdx; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + RelationshipsBetweenSPDXElements additions = additionsIterator.next(); + RelationshipsBetweenSPDXElements actual = new RelationshipsBetweenSPDXElements(); + for (RelationshipsBetweenSPDXElements._Fields field : RelationshipsBetweenSPDXElements._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while (deletionsIterator.hasNext()) { + RelationshipsBetweenSPDXElements deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + spdx.setRelationships(actuals); + return spdx; + } + + private SPDXDocument updateAnnotaions(SPDXDocument spdx, SPDXDocument spdxAdditions, SPDXDocument spdxDeletions) { + Set actuals = spdx.getAnnotations(); + Iterator additionsIterator = spdxAdditions.getAnnotationsIterator(); + Iterator deletionsIterator = spdxDeletions.getAnnotationsIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return spdx; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + Annotations additions = additionsIterator.next(); + Annotations actual = new Annotations(); + for (Annotations._Fields field : Annotations._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while (deletionsIterator.hasNext()) { + Annotations deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + spdx.setAnnotations(actuals); + return spdx; + } + + private SPDXDocument updateSnippets(SPDXDocument spdx, SPDXDocument spdxAdditions, SPDXDocument spdxDeletions) { + Set actuals = spdx.getSnippets(); + Iterator additionsIterator = spdxAdditions.getSnippetsIterator(); + Iterator deletionsIterator = spdxDeletions.getSnippetsIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return spdx; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + SnippetInformation additions = additionsIterator.next(); + SnippetInformation actual = new SnippetInformation(); + for (SnippetInformation._Fields field : SnippetInformation._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while (deletionsIterator.hasNext()) { + SnippetInformation deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + spdx.setSnippets(actuals); + return spdx; + } + +} diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxPackageInfoModerator.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxPackageInfoModerator.java new file mode 100644 index 0000000000..a7536f4967 --- /dev/null +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/entitlement/SpdxPackageInfoModerator.java @@ -0,0 +1,207 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.datahandler.entitlement; + +import org.eclipse.sw360.datahandler.common.Moderator; +import org.eclipse.sw360.datahandler.thrift.RequestStatus; +import org.eclipse.sw360.datahandler.thrift.ThriftClients; +import org.eclipse.sw360.datahandler.thrift.spdx.annotations.Annotations; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.CheckSum; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.ExternalReference; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageVerificationCode; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationService; +import org.eclipse.sw360.datahandler.thrift.users.User; + +import org.apache.logging.log4j.Logger; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.apache.logging.log4j.LogManager; +import org.apache.thrift.TException; + +public class SpdxPackageInfoModerator extends Moderator { + + private static final Logger log = LogManager.getLogger(SpdxPackageInfoModerator.class); + + + public SpdxPackageInfoModerator(ThriftClients thriftClients) { + super(thriftClients); + } + + public SpdxPackageInfoModerator() { + super(new ThriftClients()); + } + + public RequestStatus updateSpdxPackageInfo(PackageInformation packageInfo, User user) { + + try { + ModerationService.Iface client = thriftClients.makeModerationClient(); + client.createSpdxPackageInfoRequest(packageInfo, user); + return RequestStatus.SENT_TO_MODERATOR; + } catch (TException e) { + log.error("Could not moderate SPDX Package Info " + packageInfo.getId() + " for User " + user.getEmail(), e); + return RequestStatus.FAILURE; + } + } + + public RequestStatus deleteSpdxPackageInfo(PackageInformation packageInfo, User user) { + try { + ModerationService.Iface client = thriftClients.makeModerationClient(); + client.createSpdxPackageInfoDeleteRequest(packageInfo, user); + return RequestStatus.SENT_TO_MODERATOR; + } catch (TException e) { + log.error("Could not moderate SPDX Package Info " + packageInfo.getId() + " for User " + user.getEmail(), e); + return RequestStatus.FAILURE; + } + } + + public PackageInformation updateSpdxPackageInfoFromModerationRequest(PackageInformation packageInfo, + PackageInformation packageInfoAdditions, + PackageInformation packageInfoDeletions) { + for (PackageInformation._Fields field : PackageInformation._Fields.values()) { + if (packageInfoAdditions.getFieldValue(field) == null && packageInfoDeletions.getFieldValue(field) == null) { + continue; + } + switch (field) { + case ID: + case REVISION: + case TYPE: + break; + case CHECKSUMS: + packageInfo = updateCheckSums(packageInfo, packageInfoAdditions, packageInfoDeletions); + break; + case EXTERNAL_REFS: + packageInfo = updateExternalReference(packageInfo, packageInfoAdditions, packageInfoDeletions); + break; + case ANNOTATIONS: + packageInfo = updateAnnotaions(packageInfo, packageInfoAdditions, packageInfoDeletions); + break; + case PACKAGE_VERIFICATION_CODE: + packageInfo = updatePackageVerificationCode(packageInfo, packageInfoAdditions, packageInfoDeletions); + break; + default: + packageInfo = updateBasicField(field, PackageInformation.metaDataMap.get(field), packageInfo, packageInfoAdditions, packageInfoDeletions); + } + + } + return packageInfo; + } + + private PackageInformation updateAnnotaions(PackageInformation packageInfo, PackageInformation packageInfoAdditions, PackageInformation packageInfoDeletions) { + Set actuals = packageInfo.getAnnotations(); + Iterator additionsIterator = packageInfoAdditions.getAnnotationsIterator(); + Iterator deletionsIterator = packageInfoDeletions.getAnnotationsIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return packageInfo; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + Annotations additions = additionsIterator.next(); + Annotations actual = new Annotations(); + for (Annotations._Fields field : Annotations._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while (deletionsIterator.hasNext()) { + Annotations deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + packageInfo.setAnnotations(actuals); + return packageInfo; + } + + private PackageInformation updateCheckSums(PackageInformation packageInfo, PackageInformation packageInfoAdditions, PackageInformation packageInfoDeletions) { + Set actuals = packageInfo.getChecksums(); + Iterator additionsIterator = packageInfoAdditions.getChecksumsIterator(); + Iterator deletionsIterator = packageInfoDeletions.getChecksumsIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return packageInfo; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + CheckSum additions = additionsIterator.next(); + CheckSum actual = new CheckSum(); + for (CheckSum._Fields field : CheckSum._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while (deletionsIterator.hasNext()) { + CheckSum deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + packageInfo.setChecksums(actuals); + return packageInfo; + } + + private PackageInformation updateExternalReference(PackageInformation packageInfo, PackageInformation packageInfoAdditions, PackageInformation packageInfoDeletions) { + Set actuals = packageInfo.getExternalRefs(); + Iterator additionsIterator = packageInfoAdditions.getExternalRefsIterator(); + Iterator deletionsIterator = packageInfoDeletions.getExternalRefsIterator(); + if (additionsIterator == null && deletionsIterator == null) { + return packageInfo; + } + if (actuals == null) { + actuals = new HashSet<>(); + } + while (additionsIterator.hasNext()) { + ExternalReference additions = additionsIterator.next(); + ExternalReference actual = new ExternalReference(); + for (ExternalReference._Fields field : ExternalReference._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + actuals.add(actual); + } + while (deletionsIterator.hasNext()) { + ExternalReference deletions = deletionsIterator.next(); + actuals.remove(deletions); + } + packageInfo.setExternalRefs(actuals); + return packageInfo; + } + + private PackageInformation updatePackageVerificationCode(PackageInformation packageInfo, PackageInformation packageInfoAdditions, PackageInformation packageInfoDeletions) { + PackageVerificationCode actual = packageInfo.getPackageVerificationCode(); + PackageVerificationCode additions = packageInfoAdditions.getPackageVerificationCode(); + PackageVerificationCode deletions = packageInfoDeletions.getPackageVerificationCode(); + + if (additions == null && deletions == null) { + return packageInfo; + } + if (actual == null) { + actual = new PackageVerificationCode(); + } + + for (PackageVerificationCode._Fields field : PackageVerificationCode._Fields.values()) { + if (additions.isSet(field)) { + actual.setFieldValue(field, additions.getFieldValue(field)); + } + } + + packageInfo.setPackageVerificationCode(actual); + return packageInfo; + } + +} 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 c448b28840..025bfa252f 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 @@ -22,20 +22,39 @@ import org.eclipse.sw360.datahandler.thrift.components.ComponentType; import org.eclipse.sw360.datahandler.thrift.components.Release; import org.eclipse.sw360.datahandler.thrift.projects.Project; +import org.eclipse.sw360.datahandler.thrift.spdx.annotations.Annotations; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; +import org.eclipse.sw360.datahandler.thrift.spdx.otherlicensinginformationdetected.OtherLicensingInformationDetected; +import org.eclipse.sw360.datahandler.thrift.spdx.relationshipsbetweenspdxelements.RelationshipsBetweenSPDXElements; +import org.eclipse.sw360.datahandler.thrift.spdx.snippetinformation.*; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.*; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.*; +import org.spdx.library.model.enumerations.Purpose; import org.spdx.library.model.enumerations.RelationshipType; +import org.spdx.library.model.license.ExtractedLicenseInfo; +import org.spdx.library.model.license.SpdxNoAssertionLicense; +import org.spdx.library.model.pointer.ByteOffsetPointer; +import org.spdx.library.model.pointer.LineCharPointer; +import org.spdx.library.model.pointer.SinglePointer; +import org.spdx.library.model.pointer.StartEndPointer; import org.spdx.library.model.*; import org.spdx.library.InvalidSPDXAnalysisException; import org.spdx.tools.InvalidFileNameException; import org.spdx.tools.SpdxToolsHelper; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.eclipse.sw360.datahandler.common.CommonUtils.isNotNullEmptyOrWhitespace; import static org.eclipse.sw360.datahandler.common.CommonUtils.isNullEmptyOrWhitespace; public class SpdxBOMImporter { @@ -46,7 +65,7 @@ public SpdxBOMImporter(SpdxBOMImporterSink sink) { this.sink = sink; } - public ImportBomRequestPreparation prepareImportSpdxBOMAsRelease(File targetFile) { + public ImportBomRequestPreparation prepareImportSpdxBOMAsRelease(File targetFile) throws InvalidSPDXAnalysisException { final ImportBomRequestPreparation requestPreparation = new ImportBomRequestPreparation(); final SpdxDocument spdxDocument = openAsSpdx(targetFile); if (spdxDocument == null) { @@ -54,6 +73,18 @@ public ImportBomRequestPreparation prepareImportSpdxBOMAsRelease(File targetFile requestPreparation.setMessage("error-read-file"); return requestPreparation; } + String componentsName = ""; + String releasesName = ""; + String version = ""; + List listPackages = getPackages(spdxDocument); + for (SpdxPackage spdxPackage : listPackages) { + componentsName += spdxPackage.getName() + ","; + if (!spdxPackage.getVersionInfo().toString().equals("Optional.empty")) + releasesName += spdxPackage.getName() + " " + spdxPackage.getVersionInfo() + ","; + version += spdxPackage.getVersionInfo() + ","; + } + componentsName = componentsName.replace("Optional[", "").replace("]", ""); + releasesName = releasesName.replace("Optional[", "").replace("]", ""); try { final List describedPackages = spdxDocument.getDocumentDescribes().stream().collect(Collectors.toList()); final List packages = describedPackages.stream() @@ -70,9 +101,9 @@ public ImportBomRequestPreparation prepareImportSpdxBOMAsRelease(File targetFile } final SpdxElement spdxElement = packages.get(0); if (spdxElement instanceof SpdxPackage) { - final SpdxPackage spdxPackage = (SpdxPackage) spdxElement; - requestPreparation.setName(getValue(spdxPackage.getName())); - requestPreparation.setVersion(getValue(spdxPackage.getVersionInfo())); + requestPreparation.setComponentsName(componentsName); + requestPreparation.setReleasesName(releasesName); + requestPreparation.setVersion(version); requestPreparation.setRequestStatus(RequestStatus.SUCCESS); } else { requestPreparation.setMessage("Failed to get spdx package from the provided BOM file."); @@ -80,7 +111,7 @@ public ImportBomRequestPreparation prepareImportSpdxBOMAsRelease(File targetFile } } catch (InvalidSPDXAnalysisException e) { requestPreparation.setRequestStatus(RequestStatus.FAILURE); - e.printStackTrace(); + log.error("Error when prepare Import Spdx BOM",e); } return requestPreparation; } @@ -95,7 +126,7 @@ private SpdxDocument openAsSpdx(File file){ log.info("Read file: " + file.getName()); return SpdxToolsHelper.deserializeDocument(file); } catch (InvalidSPDXAnalysisException | IOException | InvalidFileNameException e) { - log.error("Error read file " + file.getName() + " to SpdxDocument:" + e.getMessage() ); + log.error("Error read file " + file.getName() + " to SpdxDocument:" + e.getMessage()); return null; } } @@ -147,7 +178,7 @@ private RequestSummary importSpdxBOM(InputStream inputStream, AttachmentContent if (SW360Constants.TYPE_PROJECT.equals(type)) { response = importAsProject(spdxElement, attachmentContent); } else if (SW360Constants.TYPE_RELEASE.equals(type)) { - response = importAsRelease(spdxElement, attachmentContent); + response = importAsRelease(spdxElement, attachmentContent, spdxDocument); } else { throw new SW360Exception("Unsupported type=[" + type + "], can not import BOM"); } @@ -186,12 +217,484 @@ private SpdxBOMImporterSink.Response importAsComponent(SpdxPackage spdxPackage) private Release createReleaseFromSpdxPackage(SpdxPackage spdxPackage) throws InvalidSPDXAnalysisException { final Release release = new Release(); final String name = getValue(spdxPackage.getName()); + final Map externalIds = new HashMap<>(); final String version = getValue(spdxPackage.getVersionInfo()); + release.setExternalIds(externalIds); release.setName(name); release.setVersion(version); return release; } + private SPDXDocument createSPDXDocumentFromSpdxDocument(String releaseId, SpdxDocument spdxDocument) throws SW360Exception, MalformedURLException { + final SPDXDocument doc = getSpdxDocumentFromRelease(releaseId); + doc.setReleaseId(releaseId); + try { + + List spdxSnippets = (List) SpdxModelFactory.getElements(spdxDocument.getModelStore(), spdxDocument.getDocumentUri(), null, SpdxSnippet.class).collect(Collectors.toList()); + if (spdxSnippets.size() != 0) { + final Set snippetInfos = createSnippetsFromSpdxSnippets(spdxSnippets); + doc.setSnippets(snippetInfos); + } + + final List spdxRelationships = spdxDocument.getRelationships().stream().collect(Collectors.toList()); + final List spdxAnnotations = List.copyOf(spdxDocument.getAnnotations()); + final List extractedLicenseInfos = List.copyOf(spdxDocument.getExtractedLicenseInfos()); + + final Set relationships = createRelationshipsFromSpdxRelationships(spdxRelationships, spdxDocument.getId()); + final Set annotations = createAnnotationsFromSpdxAnnotations(spdxAnnotations); + final Set otherLicenses = createOtherLicensesFromSpdxExtractedLicenses(extractedLicenseInfos); + final Set moderators = new HashSet<>(); + doc.setModerators(moderators); + doc.setRelationships(relationships) + .setAnnotations(annotations) + .setOtherLicensingInformationDetecteds(otherLicenses); + } catch (InvalidSPDXAnalysisException e) { + log.error(e); + } + + return doc; + } + + private Set createAnnotationsFromSpdxAnnotations(List spdxAnnotations) throws InvalidSPDXAnalysisException { + Set annotations = new HashSet<>(); + int index = 0; + for (Annotation spdxAnn : spdxAnnotations) { + String annotator = spdxAnn.getAnnotator(); + String date = spdxAnn.getAnnotationDate(); + String type = spdxAnn.getAnnotationType().name(); + String comment = spdxAnn.getComment(); + + Annotations ann = new Annotations(); + ann.setAnnotator(verifyOrSetDefault(annotator)) + .setAnnotationDate(verifyOrSetDefault(date)) + .setAnnotationType(verifyOrSetDefault(type)) + .setAnnotationComment(verifyOrSetDefault(comment)) + .setIndex(index); + + annotations.add(ann); + index++; + } + return annotations; + } + + private Set createSnippetsFromSpdxSnippets(List spdxSnippets) { + Set snippets = new HashSet<>(); + int index = 0; + try { + for (SpdxSnippet spdxSnippet : spdxSnippets) { + String id = spdxSnippet.getId(); + String snippetFromFile = spdxSnippet.getSnippetFromFile().getId(); + Set ranges = createSnippetRangesFromSpdxSnippet(spdxSnippet); + String licenseConcluded = spdxSnippet.getLicenseConcluded().toString(); + Set licenseInfoInFile = spdxSnippet.getLicenseInfoFromFiles().stream() + .map(license -> verifyOrSetDefault(license.getId())) + .collect(Collectors.toSet()); + String licenseComment = getValue(spdxSnippet.getLicenseComments()); + String copyrightText = spdxSnippet.getCopyrightText(); + String comment = getValue(spdxSnippet.getComment()); + String name = getValue(spdxSnippet.getName()); + String attributionText = String.join("|", spdxSnippet.getAttributionText()); + + SnippetInformation snippet = new SnippetInformation(); + snippet.setSPDXID(verifyOrSetDefault(id)) + .setSnippetFromFile(verifyOrSetDefault(snippetFromFile)) + .setSnippetRanges(ranges) + .setLicenseConcluded(verifyOrSetDefault(licenseConcluded)) + .setLicenseInfoInSnippets(licenseInfoInFile) + .setLicenseComments(verifyOrSetDefault(licenseComment)) + .setCopyrightText(verifyOrSetDefault(copyrightText)) + .setComment(verifyOrSetDefault(comment)) + .setName(verifyOrSetDefault(name)) + .setSnippetAttributionText(verifyOrSetDefault(attributionText)) + .setIndex(index); + + snippets.add(snippet); + index++; + } + } catch (InvalidSPDXAnalysisException e) { + log.error(e); + } + return snippets; + } + + private Set createSnippetRangesFromSpdxSnippet(SpdxSnippet spdxSnippet) throws InvalidSPDXAnalysisException { + StartEndPointer spdxByteRange = spdxSnippet.getByteRange(); + String[] byteRanges = rangeToStrs(spdxByteRange); + SnippetRange snippetByteRange = new SnippetRange(); + snippetByteRange.setRangeType("BYTE") + .setStartPointer(byteRanges[0]) + .setEndPointer(byteRanges[1]) + .setReference(spdxByteRange.getStartPointer().getReference().getId()) + .setIndex(0); + + Optional spdxLineRange = spdxSnippet.getLineRange(); + if (spdxLineRange.isPresent()) { + String[] lineRanges = rangeToStrs(spdxLineRange.get()); + SnippetRange snippetLineRange = new SnippetRange(); + snippetLineRange.setRangeType("LINE") + .setStartPointer(lineRanges[0]) + .setEndPointer(lineRanges[1]) + .setReference(spdxLineRange.get().getStartPointer().getReference().getId()) + .setIndex(1); + return new HashSet<>(Arrays.asList(snippetByteRange, snippetLineRange)); + } + return new HashSet<>(Arrays.asList(snippetByteRange)); + } + + // 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 Set createRelationshipsFromSpdxRelationships(List spdxRelationships, String spdxElementId) throws InvalidSPDXAnalysisException { + Set relationships = new HashSet<>(); + int index = 0; + + for (Relationship spdxRelationship : spdxRelationships) { + Optional relatedSpdxElement = spdxRelationship.getRelatedSpdxElement(); + if (relatedSpdxElement.isPresent() && !(relatedSpdxElement.get() instanceof SpdxFile)) { + String type = spdxRelationship.getRelationshipType().name(); + String relatedSpdxElementId = relatedSpdxElement.get().getId(); + String comment = getValue(spdxRelationship.getComment()); + + RelationshipsBetweenSPDXElements relationship = new RelationshipsBetweenSPDXElements(); + relationship.setSpdxElementId(verifyOrSetDefault(spdxElementId)) + .setRelationshipType(verifyOrSetDefault(type)) + .setRelatedSpdxElement(verifyOrSetDefault(relatedSpdxElementId)) + .setRelationshipComment(verifyOrSetDefault(comment)) + .setIndex(index); + + relationships.add(relationship); + index++; + } + } + + return relationships; + } + + private Set createOtherLicensesFromSpdxExtractedLicenses(List spdxExtractedLicenses) throws InvalidSPDXAnalysisException { + Set otherLicenses = new HashSet<>(); + int index = 0; + + for (ExtractedLicenseInfo spdxExtractedLicense : spdxExtractedLicenses) { + String licenseId = spdxExtractedLicense.getLicenseId(); + String extractedText = spdxExtractedLicense.getExtractedText(); + String name = spdxExtractedLicense.getName(); + Set crossRef = new HashSet<>(Arrays.asList(verifyOrSetDefault(spdxExtractedLicense.getCrossRef().toArray(new String[spdxExtractedLicense.getCrossRef().size()])))); + String comment = spdxExtractedLicense.getComment(); + + OtherLicensingInformationDetected otherLicense = new OtherLicensingInformationDetected(); + otherLicense.setLicenseId(verifyOrSetDefault(licenseId)) + .setExtractedText(verifyOrSetDefault(extractedText)) + .setLicenseName(verifyOrSetDefault(name)) + .setLicenseCrossRefs(crossRef) + .setLicenseComment(verifyOrSetDefault(comment)) + .setIndex(index); + + otherLicenses.add(otherLicense); + index++; + } + + return otherLicenses; + } + + private DocumentCreationInformation createDocumentCreationInfoFromSpdxDocument(String spdxDocId, SpdxDocument spdxDocument) throws SW360Exception, MalformedURLException { + final DocumentCreationInformation info = getDocCreationInfoFromSpdxDocument(spdxDocId); + info.setSpdxDocumentId(spdxDocId); + + try { + final String spdxVersion = spdxDocument.getSpecVersion(); + final String dataLicense = spdxDocument.getDataLicense().toString(); + final String spdxId = spdxDocument.getId(); + final String name = getValue(spdxDocument.getName()); + final String documentNamespace = spdxDocument.getDocumentUri(); + final Set refs = createExternalDocumentRefsFromSpdxDocument(spdxDocument); + final String licenseListVersion = getValue(spdxDocument.getCreationInfo().getLicenseListVersion()); + final Set creators = createCreatorFromSpdxDocument(spdxDocument); + final String createdDate = spdxDocument.getCreationInfo().getCreated(); + final String creatorComment = getValue(spdxDocument.getCreationInfo().getComment()); + final String documentComment = getValue(spdxDocument.getComment()); + final Set moderators = new HashSet<>(); + info.setSpdxVersion(verifyOrSetDefault(spdxVersion)) + .setDataLicense(verifyOrSetDefault(dataLicense)) + .setSPDXID(verifyOrSetDefault(spdxId)) + .setName(verifyOrSetDefault(name)) + .setDocumentNamespace(verifyOrSetDefault(documentNamespace)) + .setExternalDocumentRefs(refs) + .setLicenseListVersion(verifyOrSetDefault(licenseListVersion)) + .setCreator(creators) + .setCreated(verifyOrSetDefault(createdDate)) + .setCreatorComment(verifyOrSetDefault(creatorComment)) + .setDocumentComment(verifyOrSetDefault(documentComment)) + .setModerators(moderators); + } catch (InvalidSPDXAnalysisException e) { + log.error(e); + } + + return info; + } + + private Set createExternalDocumentRefsFromSpdxDocument(SpdxDocument spdxDocument) { + Set refs = new HashSet<>(); + int index = 0; + + try { + List externalDocumentRefs = List.copyOf(spdxDocument.getExternalDocumentRefs()); + + for (ExternalDocumentRef externalDocumentRef : externalDocumentRefs) { + Optional spdxChecksum = externalDocumentRef.getChecksum(); + if (spdxChecksum.isPresent()) { + String externalDocumentId = externalDocumentRef.getId(); + String spdxDocumentNamespace = externalDocumentRef.getSpdxDocumentNamespace(); + CheckSum checksum = new CheckSum(); + checksum.setAlgorithm(spdxChecksum.get().getAlgorithm().name()) + .setChecksumValue(spdxChecksum.get().getValue()); + + ExternalDocumentReferences ref = new ExternalDocumentReferences(); + ref.setExternalDocumentId(verifyOrSetDefault(externalDocumentId)) + .setChecksum(checksum) + .setSpdxDocument(verifyOrSetDefault(spdxDocumentNamespace)) + .setIndex(index); + + refs.add(ref); + index++; + } + } + } catch (InvalidSPDXAnalysisException e) { + log.error(e); + } + + return refs; + } + + private Set createCreatorFromSpdxDocument(SpdxDocument spdxDocument) { + Set creators = new HashSet<>(); + int index = 0; + + try { + List spdxCreators = List.copyOf(spdxDocument.getCreationInfo().getCreators()); + + for (String spdxCreator : spdxCreators) { + String[] data = spdxCreator.split(":"); + if (data.length < 2) { + log.error("Failed to get SPDX creator from " + spdxCreator + "!"); + continue; + } + String type = data[0].trim(); + String value = spdxCreator.substring(data[0].length() + 1).trim(); + + Creator creator = new Creator(); + creator.setType(verifyOrSetDefault(type)); + creator.setValue(verifyOrSetDefault(value)); + creator.setIndex(index); + + creators.add(creator); + index++; + } + } catch (InvalidSPDXAnalysisException e) { + log.error(e); + } + + return creators; + } + + private PackageInformation createPackageInfoFromSpdxPackage(String spdxDocId, SpdxPackage spdxPackage) throws SW360Exception, InvalidSPDXAnalysisException { + if (spdxPackage.getVersionInfo().toString().equals("Optional.empty")) + return null; + Optional packageName = spdxPackage.getName(); + if (!packageName.isPresent()) { + return null; + } + + PackageVerificationCode PVC = createPVCFromSpdxPackage(spdxPackage); + Set checksums = createCheckSumsFromSpdxChecksums(spdxPackage); + String licenseDeclared = createLicenseDeclaredFromSpdxLicenseDeclared(spdxPackage); + Set externalRefs = createExternalReferenceFromSpdxPackage(spdxPackage); + + PackageInformation pInfo = getPackageInformationFromSpdxDocument(spdxDocId, packageName.get()); + pInfo.setSpdxDocumentId(spdxDocId); + + try { + final String name = getValue(spdxPackage.getName()); + final String spdxId = spdxPackage.getId(); + final String versionInfo = getValue(spdxPackage.getVersionInfo()); + final String packageFileName = getValue(spdxPackage.getPackageFileName()); + final String supplier = getValue(spdxPackage.getSupplier()); + final String originator = getValue(spdxPackage.getOriginator()); + final String downloadLocation = getValue(spdxPackage.getDownloadLocation()); + final boolean fileAnalyzed = spdxPackage.isFilesAnalyzed(); + final String homepage = getValue(spdxPackage.getHomepage()); + final String sourceInfo = getValue(spdxPackage.getSourceInfo()); + final String primaryPackagePurpose = getValuePrimaryPurpose(spdxPackage.getPrimaryPurpose()); + final String releaseDate = getValue(spdxPackage.getReleaseDate()); + final String builtDate = getValue(spdxPackage.getBuiltDate()); + final String validUntilDate = getValue(spdxPackage.getValidUntilDate()); + + + String licenseConcluded = ""; + if (spdxPackage.getLicenseConcluded() != null) { + licenseConcluded = spdxPackage.getLicenseConcluded().toString(); + } + final Set licenseInfosFromFiles = spdxPackage.getLicenseInfoFromFiles().stream() + .map(license -> license.toString()) + .collect(Collectors.toSet()); + final String licenseComment = getValue(spdxPackage.getLicenseComments()); + final String copyrightText = spdxPackage.getCopyrightText(); + final String summary = getValue(spdxPackage.getSummary()); + final String description = getValue(spdxPackage.getDescription()); + final String comment = getValue(spdxPackage.getComment()); + final Set attributionText = new HashSet<>(Arrays.asList(verifyOrSetDefault(spdxPackage.getAttributionText().toArray(new String [spdxPackage.getAttributionText().size()])))); + final Set annotations = createAnnotationsFromSpdxAnnotations(List.copyOf(spdxPackage.getAnnotations())); + final Set moderators = new HashSet<>(); + pInfo.setName(verifyOrSetDefault(name)) + .setSPDXID(verifyOrSetDefault(spdxId)) + .setVersionInfo(verifyOrSetDefault(versionInfo)) + .setPackageFileName(verifyOrSetDefault(packageFileName)) + .setSupplier(verifyOrSetDefault(supplier)) + .setOriginator(verifyOrSetDefault(originator)) + .setDownloadLocation(verifyOrSetDefault(downloadLocation)) + .setFilesAnalyzed(fileAnalyzed) + .setPackageVerificationCode(PVC) + .setChecksums(checksums) + .setHomepage(verifyOrSetDefault(homepage)) + .setSourceInfo(verifyOrSetDefault(sourceInfo)) + .setPrimaryPackagePurpose(verifyOrSetDefault(primaryPackagePurpose)) + .setReleaseDate(verifyOrSetDefault(releaseDate)) + .setBuiltDate(verifyOrSetDefault(builtDate)) + .setValidUntilDate(verifyOrSetDefault(validUntilDate)) + .setLicenseConcluded(verifyOrSetDefault(licenseConcluded)) + .setLicenseInfoFromFiles(licenseInfosFromFiles) + .setLicenseDeclared(verifyOrSetDefault(licenseDeclared)) + .setLicenseComments(verifyOrSetDefault(licenseComment)) + .setCopyrightText(verifyOrSetDefault(copyrightText)) + .setSummary(verifyOrSetDefault(summary)) + .setDescription(verifyOrSetDefault(description)) + .setPackageComment(verifyOrSetDefault(comment)) + .setExternalRefs(externalRefs) + .setAttributionText(attributionText) + .setAnnotations(annotations) + .setModerators(moderators); + } catch (InvalidSPDXAnalysisException e) { + log.error("Create Package Info From SpdxPackage error " + e); + } + + return pInfo; + } + + private String getValuePrimaryPurpose(Optional primaryPurpose) { + if (primaryPurpose.isPresent()) { + return primaryPurpose.get().toString(); + } else { + return ""; + } + } + + private PackageVerificationCode createPVCFromSpdxPackage(SpdxPackage spdxPackage) { + try { + PackageVerificationCode PVC = new PackageVerificationCode(); + Optional spdxPVC = spdxPackage.getPackageVerificationCode(); + String value = ""; + Set excludedFileNames = new HashSet<>(); + if (!spdxPVC.isEmpty()) { + value = spdxPVC.get().getValue(); + excludedFileNames = new HashSet(Arrays.asList(verifyOrSetDefault(spdxPVC.get().getExcludedFileNames().toString()))); + } + PVC.setExcludedFiles(excludedFileNames) + .setValue(verifyOrSetDefault(value)); + return PVC; + } catch (InvalidSPDXAnalysisException | NullPointerException e) { + log.error("Error get PVC " + e); + return null; + } + } + + private Set createExternalReferenceFromSpdxPackage(SpdxPackage spdxPackage) { + Set refs = new HashSet<>(); + int index = 0; + + try { + List spdxExternalRefs = List.copyOf(spdxPackage.getExternalRefs()); + for (ExternalRef spdxRef : spdxExternalRefs) { + String category = spdxRef.getReferenceCategory().name(); + String locator = spdxRef.getReferenceLocator(); + String type = spdxRef.getReferenceType().getIndividualURI(); + String comment = getValue(spdxRef.getComment()); + + ExternalReference ref = new ExternalReference(); + ref.setReferenceCategory(verifyOrSetDefault(category)) + .setReferenceLocator(verifyOrSetDefault(locator)) + .setReferenceType(verifyOrSetDefault(type)) + .setComment(verifyOrSetDefault(comment)) + .setIndex(index); + + refs.add(ref); + index++; + } + } catch (InvalidSPDXAnalysisException e) { + log.error(e); + } + return refs; + } + + private Set createCheckSumsFromSpdxChecksums(SpdxPackage spdxPackage) { + Set checksums = new HashSet<>(); + int index = 0; + try { + List spdxChecksums = List.copyOf(spdxPackage.getChecksums()); + for (Checksum spdxChecksum : spdxChecksums) { + String algorithm = spdxChecksum.getAlgorithm().name(); + String value = spdxChecksum.getValue(); + CheckSum checksum = new CheckSum(); + checksum.setAlgorithm(verifyOrSetDefault(algorithm)) + .setChecksumValue(verifyOrSetDefault(value)) + .setIndex(index); + checksums.add(checksum); + index++; + } + } catch (InvalidSPDXAnalysisException | NullPointerException e) { + checksums = Collections.emptySet(); + } + return checksums; + } + + private String createLicenseDeclaredFromSpdxLicenseDeclared(SpdxPackage spdxPackage) { + try { + if (!spdxPackage.getLicenseDeclared().equals(new SpdxNoAssertionLicense(spdxPackage.getModelStore(), spdxPackage.getDocumentUri()))) { + return spdxPackage.getLicenseDeclared().toString(); + } + return null; + } catch (InvalidSPDXAnalysisException e) { + log.error("Can not get licenseDeclared " + e); + } + return null; + } + private Attachment makeAttachmentFromContent(AttachmentContent attachmentContent) { Attachment attachment = new Attachment(); attachment.setAttachmentContentId(attachmentContent.getId()); @@ -204,11 +707,11 @@ private Attachment makeAttachmentFromContent(AttachmentContent attachmentContent } private Optional importAsRelease(SpdxElement relatedSpdxElement) throws SW360Exception, InvalidSPDXAnalysisException { - return importAsRelease(relatedSpdxElement, null); + return importAsRelease(relatedSpdxElement, null, null); } - private Optional importAsRelease(SpdxElement relatedSpdxElement, AttachmentContent attachmentContent - ) throws SW360Exception, InvalidSPDXAnalysisException { + private Optional importAsRelease(SpdxElement relatedSpdxElement, AttachmentContent attachmentContent, SpdxDocument spdxDocument + ) throws SW360Exception, InvalidSPDXAnalysisException { if (relatedSpdxElement instanceof SpdxPackage) { final SpdxPackage spdxPackage = (SpdxPackage) relatedSpdxElement; final Release release; @@ -232,6 +735,22 @@ private Optional importAsRelease(SpdxElement relat final SpdxBOMImporterSink.Response response = sink.addRelease(release); + if(spdxDocument != null) { + List spdxPackageList = getPackages(spdxDocument); + List spdxPackages =new ArrayList<>(); + for (SpdxPackage spdxPackageCheck : spdxPackageList) { + if (!spdxPackageCheck.getName().equals(spdxPackage.getName())) + spdxPackages.add(spdxPackageCheck); + } + importAsReleaseFromSpdxDocument(spdxPackages,attachmentContent,spdxDocument); + if (SW360Constants.SPDX_DOCUMENT_ENABLED) { + try { + importSpdxDocument(response.getId(), spdxDocument, spdxPackage); + } catch (MalformedURLException e) { + log.error(e); + } + } + } response.addChild(component); return Optional.of(response); } else { @@ -240,6 +759,130 @@ private Optional importAsRelease(SpdxElement relat } } + private List getPackages(SpdxDocument spdxDocument) throws InvalidSPDXAnalysisException { + List allPackages = new ArrayList<>(); + try(@SuppressWarnings("unchecked") + Stream allPackagesStream = (Stream) SpdxModelFactory.getElements(spdxDocument.getModelStore(), spdxDocument.getDocumentUri(), + spdxDocument.getCopyManager(), SpdxPackage.class)) { + allPackages = allPackagesStream.collect(Collectors.toList()); + } + return allPackages; + } + + private void importAsReleaseFromSpdxDocument(List packages, AttachmentContent attachmentContent,SpdxDocument spdxDocument) throws SW360Exception, InvalidSPDXAnalysisException { + for (SpdxPackage spdxElement: packages){ + final Release release = createReleaseFromSpdxPackage(spdxElement); + String name = spdxElement.getName().toString().replace("Optional[", "").replace("]",""); + Component component = sink.searchComponent(name); + if (spdxElement.getVersionInfo().toString().equals("Optional.empty")){ + if (component == null) release.setComponentId(importAsComponent(spdxElement).getId()); + else release.setComponentId(component.getId()); + continue; + } else { + if (component == null) release.setComponentId(importAsComponent(spdxElement).getId()); + else release.setComponentId(component.getId()); + if (sink.searchRelease(release.getName()) == null) { + final Relationship[] relationships = spdxElement.getRelationships().toArray(new Relationship[0]); + List releases = importAsReleases(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); + if (SW360Constants.SPDX_DOCUMENT_ENABLED) { + try { + importSpdxDocument(response.getId(), spdxDocument, spdxElement); + } catch (MalformedURLException e) { + log.error(e); + } + } + } + } + } + } + + private void importSpdxDocument(String releaseId, SpdxDocument spdxDocument, SpdxPackage spdxPackage) throws SW360Exception, MalformedURLException, InvalidSPDXAnalysisException { + final SPDXDocument spdxDoc = createSPDXDocumentFromSpdxDocument(releaseId, spdxDocument); + final SpdxBOMImporterSink.Response spdxDocRes = sink.addOrUpdateSpdxDocument(spdxDoc); + final String spdxDocId = spdxDocRes.getId(); + + final DocumentCreationInformation docCreationInfo = createDocumentCreationInfoFromSpdxDocument(spdxDocId, spdxDocument); + sink.addOrUpdateDocumentCreationInformation(docCreationInfo); + List allPackages = new ArrayList<>(); + try(@SuppressWarnings("unchecked") + Stream allPackagesStream = (Stream) SpdxModelFactory.getElements(spdxDocument.getModelStore(), spdxDocument.getDocumentUri(), + spdxDocument.getCopyManager(), SpdxPackage.class)) { + allPackages = allPackagesStream.collect(Collectors.toList()); + } + List spdxPackages =new ArrayList<>(); + for (SpdxPackage spdxPackageCheck : allPackages) { + if (spdxPackageCheck.getName().equals(spdxPackage.getName())) + spdxPackages.add(spdxPackageCheck); + } + int index = 1; + for (SpdxPackage packageElement : spdxPackages) { + log.info("Import package: " + packageElement.toString()); + PackageInformation packageInfo = createPackageInfoFromSpdxPackage(spdxDocId, packageElement); + if (packageInfo == null) { + continue; + } + List packageRelationship = List.copyOf(packageElement.getRelationships()); + if (!packageRelationship.isEmpty()) { + Set packageReleaseRelationship = createRelationshipsFromSpdxRelationships(packageRelationship, packageElement.getId()); + packageInfo.setRelationships(packageReleaseRelationship); + } else { + packageInfo.setRelationships(Collections.emptySet()); + } + if (packageElement.getName().equals(spdxPackage.getName())) { + packageInfo.setIndex(0); + } else { + packageInfo.setIndex(index); + index ++; + } + sink.addOrUpdatePackageInformation(packageInfo); + } + } + + private SPDXDocument getSpdxDocumentFromRelease(String releaseId) throws SW360Exception { + SPDXDocument spdxDoc; + final Release release = sink.getRelease(releaseId); + if (release.isSetSpdxId()) { + spdxDoc = sink.getSPDXDocument(release.getSpdxId()); + } else { + spdxDoc = new SPDXDocument(); + } + return spdxDoc; + } + + private DocumentCreationInformation getDocCreationInfoFromSpdxDocument(String spdxDocId) throws SW360Exception { + DocumentCreationInformation info; + final SPDXDocument spdxDoc = sink.getSPDXDocument(spdxDocId); + if (spdxDoc.isSetSpdxDocumentCreationInfoId()) { + info = sink.getDocumentCreationInfo(spdxDoc.getSpdxDocumentCreationInfoId()); + } else { + info = new DocumentCreationInformation(); + } + return info; + } + + private PackageInformation getPackageInformationFromSpdxDocument(String spdxDocId, String packageName) throws SW360Exception { + PackageInformation info; + final SPDXDocument spdxDoc = sink.getSPDXDocument(spdxDocId); + if (spdxDoc.getSpdxPackageInfoIdsSize() > 0) { + for (String packageId : spdxDoc.getSpdxPackageInfoIds()) { + if (sink.getPackageInfo(packageId).getName().equals(packageName)) { + info = sink.getPackageInfo(packageId); + return info; + } + } + return new PackageInformation(); + } else { + return new PackageInformation(); + } + } + private Map makeReleaseIdToRelationship(List releases) { return releases.stream() .collect(Collectors.toMap(SpdxBOMImporterSink.Response::getId, SpdxBOMImporterSink.Response::getReleaseRelationship)); @@ -313,6 +956,14 @@ private Optional importAsProject(SpdxElement spdxE } } + private String verifyOrSetDefault(String value) { + return (isNotNullEmptyOrWhitespace(value)) ? value : ""; + } + + private String[] verifyOrSetDefault(String[] values) { + return (values != null && values.length > 0) ? values : new String[0]; + } + private String getValue(Optional value) { if (value.isPresent()) { return value.get(); 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..3f9a36de0c 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 @@ -9,6 +9,7 @@ */ package org.eclipse.sw360.spdx; +import org.eclipse.sw360.datahandler.common.DatabaseSettings; import org.eclipse.sw360.datahandler.common.CommonUtils; import org.eclipse.sw360.datahandler.db.ComponentDatabaseHandler; import org.eclipse.sw360.datahandler.db.ProjectDatabaseHandler; @@ -16,12 +17,21 @@ import org.eclipse.sw360.datahandler.thrift.attachments.Attachment; import org.eclipse.sw360.datahandler.thrift.components.Component; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; + +import org.eclipse.sw360.datahandler.db.spdx.document.SpdxDocumentDatabaseHandler; +import org.eclipse.sw360.datahandler.db.spdx.documentcreationinfo.SpdxDocumentCreationInfoDatabaseHandler; +import org.eclipse.sw360.datahandler.db.spdx.packageinfo.SpdxPackageInfoDatabaseHandler; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.sw360.datahandler.thrift.components.Release; 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; @@ -30,11 +40,17 @@ public class SpdxBOMImporterSink { private final ProjectDatabaseHandler projectDatabaseHandler; private final ComponentDatabaseHandler componentDatabaseHandler; + private final SpdxDocumentDatabaseHandler spdxDocumentDatabaseHandler; + private final SpdxDocumentCreationInfoDatabaseHandler creationInfoDatabaseHandler; + private final SpdxPackageInfoDatabaseHandler packageInfoDatabaseHandler; 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.spdxDocumentDatabaseHandler = new SpdxDocumentDatabaseHandler(DatabaseSettings.getConfiguredClient(), DatabaseSettings.COUCH_DB_SPDX); + this.creationInfoDatabaseHandler = new SpdxDocumentCreationInfoDatabaseHandler(DatabaseSettings.getConfiguredClient(), DatabaseSettings.COUCH_DB_SPDX); + this.packageInfoDatabaseHandler = new SpdxPackageInfoDatabaseHandler(DatabaseSettings.getConfiguredClient(), DatabaseSettings.COUCH_DB_SPDX); this.user = user; } @@ -62,12 +78,68 @@ public Response addRelease(Release release) throws SW360Exception { user); final String releaseId = addDocumentRequestSummary.getId(); - if(releaseId == null || releaseId.isEmpty()) { + if (releaseId == null || releaseId.isEmpty()) { throw new SW360Exception("Id of added release should not be empty. " + addDocumentRequestSummary.toString()); } return new Response(releaseId, AddDocumentRequestStatus.SUCCESS.equals(addDocumentRequestSummary.getRequestStatus())); } + public Response addOrUpdateSpdxDocument(SPDXDocument spdxDocument) throws SW360Exception { + log.debug("create or update SPDXDocument"); + RequestStatus requestStatus; + String spdxDocId; + if (spdxDocument.isSetId()) { + requestStatus = spdxDocumentDatabaseHandler.updateSPDXDocument(spdxDocument, user); + spdxDocId = spdxDocument.getId(); + } else { + AddDocumentRequestSummary addDocumentRequestSummary = spdxDocumentDatabaseHandler.addSPDXDocument(spdxDocument, user); + requestStatus = RequestStatus.findByValue(addDocumentRequestSummary.getRequestStatus().getValue()); + spdxDocId = addDocumentRequestSummary.getId(); + } + + if (spdxDocId == null || spdxDocId.isEmpty()) { + throw new SW360Exception("Id of spdx document should not be empty. " + requestStatus.toString()); + } + return new Response(spdxDocId, RequestStatus.SUCCESS.equals(requestStatus)); + } + + public Response addOrUpdateDocumentCreationInformation(DocumentCreationInformation documentCreationInfo) throws SW360Exception { + log.debug("create or update DocumentCreationInformation { name='" + documentCreationInfo.getName() + "' }"); + RequestStatus requestStatus; + String docCreationInfoId; + if (documentCreationInfo.isSetId()) { + requestStatus = creationInfoDatabaseHandler.updateDocumentCreationInformation(documentCreationInfo, user); + docCreationInfoId = documentCreationInfo.getId(); + } else { + AddDocumentRequestSummary addDocumentRequestSummary = creationInfoDatabaseHandler.addDocumentCreationInformation(documentCreationInfo, user); + requestStatus = RequestStatus.findByValue(addDocumentRequestSummary.getRequestStatus().getValue()); + docCreationInfoId = addDocumentRequestSummary.getId(); + } + + if (docCreationInfoId == null || docCreationInfoId.isEmpty()) { + throw new SW360Exception("Id of added document creation information should not be empty. " + requestStatus.toString()); + } + return new Response(docCreationInfoId, RequestStatus.SUCCESS.equals(requestStatus)); + } + + public Response addOrUpdatePackageInformation(PackageInformation packageInfo) throws SW360Exception { + log.debug("create or update PackageInfomation { name='" + packageInfo.getName() + "' }"); + RequestStatus requestStatus; + String packageInfoId; + if (packageInfo.isSetId()) { + requestStatus = packageInfoDatabaseHandler.updatePackageInformation(packageInfo, user); + packageInfoId = packageInfo.getId(); + } else { + AddDocumentRequestSummary addDocumentRequestSummary = packageInfoDatabaseHandler.addPackageInformation(packageInfo, user); + requestStatus = RequestStatus.findByValue(addDocumentRequestSummary.getRequestStatus().getValue()); + packageInfoId = addDocumentRequestSummary.getId(); + } + if (packageInfoId == null || packageInfoId.isEmpty()) { + throw new SW360Exception("Id of added package information should not be empty. " + requestStatus.toString()); + } + return new Response(packageInfoId, RequestStatus.SUCCESS.equals(requestStatus)); + } + public Response addProject(Project project) throws SW360Exception { log.debug("create Project { name='" + project.getName() + "', version='" + project.getVersion() + "' }"); @@ -76,7 +148,7 @@ public Response addProject(Project project) throws SW360Exception { } final Set attachments = project.getAttachments(); - if(attachments != null && attachments.size() > 0) { + if (attachments != null && attachments.size() > 0) { project.setAttachments(attachments.stream() .map(a -> a.setCreatedBy(user.getEmail())) .collect(Collectors.toSet())); @@ -85,12 +157,54 @@ public Response addProject(Project project) throws SW360Exception { user); final String projectId = addDocumentRequestSummary.getId(); - if(projectId == null || projectId.isEmpty()) { + if (projectId == null || projectId.isEmpty()) { throw new SW360Exception("Id of added project should not be empty. " + addDocumentRequestSummary.toString()); } return new Response(projectId, AddDocumentRequestStatus.SUCCESS.equals(addDocumentRequestSummary.getRequestStatus())); } + public Release getRelease(String id) throws SW360Exception { + return componentDatabaseHandler.getRelease(id, user); + } + + public Component searchComponent(String name)throws SW360Exception { + List components = componentDatabaseHandler.searchComponentByNameForExport(name.toLowerCase(), false); + if (components.isEmpty()) + return null; + else { + for (Component component : components) { + if (component.getName().equals(name)) + return component; + } + } + return null; + } + + public Release searchRelease(String name)throws SW360Exception { + List releases = componentDatabaseHandler.searchReleaseByNamePrefix(name); + if (releases.isEmpty()) + return null; + else { + for (Release release : releases) { + if (release.getName().equals(name)) + return release; + } + } + return null; + } + + public SPDXDocument getSPDXDocument(String id) throws SW360Exception { + return spdxDocumentDatabaseHandler.getSPDXDocumentById(id, user); + } + + public DocumentCreationInformation getDocumentCreationInfo(String id) throws SW360Exception { + return creationInfoDatabaseHandler.getDocumentCreationInformationById(id, user); + } + + public PackageInformation getPackageInfo(String id) throws SW360Exception { + return packageInfoDatabaseHandler.getPackageInformationById(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 6690c0667d..24eefb1d6f 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 @@ -57,6 +57,8 @@ public void before() throws Exception { Component component = i.getArgument(0); return new SpdxBOMImporterSink.Response(component.getName()); }); + when(spdxBOMImporterSink.searchComponent(anyString())).thenReturn(new Component()); + when(spdxBOMImporterSink.searchRelease(anyString())).thenReturn(new Release()); attachmentContent = new AttachmentContent(); attachmentContent.setFilename("attchmentContentFilename.rdf"); diff --git a/backend/src/pom.xml b/backend/src/pom.xml index 58f5207c1d..b616515909 100644 --- a/backend/src/pom.xml +++ b/backend/src/pom.xml @@ -43,6 +43,9 @@ src-wsimport src-changelogs src-health + src-spdxdocument + src-spdxdocumentcreationinfo + src-spdxpackageinfo diff --git a/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/ModerationHandler.java b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/ModerationHandler.java index d69879420a..5e855df4cd 100644 --- a/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/ModerationHandler.java +++ b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/ModerationHandler.java @@ -27,6 +27,9 @@ import org.eclipse.sw360.datahandler.thrift.projects.ClearingRequest; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.users.User; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; import org.eclipse.sw360.moderation.db.ModerationDatabaseHandler; import java.io.IOException; @@ -125,6 +128,54 @@ public void createProjectDeleteRequest(Project project, User user) throws TExcep handler.createRequest(project, user, true); } + @Override + public RequestStatus createSPDXDocumentRequest(SPDXDocument spdx, User user) throws TException { + assertUser(user); + assertNotNull(spdx); + + return handler.createRequest(spdx, user, false); + } + + @Override + public void createSPDXDocumentDeleteRequest(SPDXDocument spdx, User user) throws TException { + assertUser(user); + assertNotNull(spdx); + + handler.createRequest(spdx, user, true); + } + + @Override + public RequestStatus createSpdxDocumentCreationInfoRequest(DocumentCreationInformation documentCreationInfo, User user) throws TException { + assertUser(user); + assertNotNull(documentCreationInfo); + + return handler.createRequest(documentCreationInfo, user, false); + } + + @Override + public void createSpdxDocumentCreationInfoDeleteRequest(DocumentCreationInformation documentCreationInfo, User user) throws TException { + assertUser(user); + assertNotNull(documentCreationInfo); + + handler.createRequest(documentCreationInfo, user, true); + } + + @Override + public RequestStatus createSpdxPackageInfoRequest(PackageInformation packageInfo, User user) throws TException { + assertUser(user); + assertNotNull(packageInfo); + + return handler.createRequest(packageInfo, user, false); + } + + @Override + public void createSpdxPackageInfoDeleteRequest(PackageInformation packageInfo, User user) throws TException { + assertUser(user); + assertNotNull(packageInfo); + + handler.createRequest(packageInfo, user, true); + } + @Override public List getModerationRequestByDocumentId(String documentId) throws TException { assertId(documentId); 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 ba42ae5098..a8e22de2af 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 @@ -24,6 +24,9 @@ import org.eclipse.sw360.datahandler.db.ComponentDatabaseHandler; import org.eclipse.sw360.datahandler.db.DatabaseHandlerUtil; import org.eclipse.sw360.datahandler.db.ProjectDatabaseHandler; +import org.eclipse.sw360.datahandler.db.spdx.document.SpdxDocumentDatabaseHandler; +import org.eclipse.sw360.datahandler.db.spdx.documentcreationinfo.SpdxDocumentCreationInfoDatabaseHandler; +import org.eclipse.sw360.datahandler.db.spdx.packageinfo.SpdxPackageInfoDatabaseHandler; import org.eclipse.sw360.datahandler.permissions.PermissionUtils; import org.eclipse.sw360.datahandler.thrift.ClearingRequestEmailTemplate; import org.eclipse.sw360.datahandler.thrift.ClearingRequestState; @@ -43,6 +46,9 @@ import org.eclipse.sw360.datahandler.thrift.projects.ClearingRequest; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.projects.ProjectClearingState; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; import org.eclipse.sw360.datahandler.thrift.users.RequestedAction; import org.eclipse.sw360.datahandler.thrift.users.User; import org.eclipse.sw360.datahandler.thrift.users.UserGroup; @@ -90,6 +96,9 @@ public class ModerationDatabaseHandler { private final LicenseDatabaseHandler licenseDatabaseHandler; private final ProjectDatabaseHandler projectDatabaseHandler; private final ComponentDatabaseHandler componentDatabaseHandler; + private final SpdxDocumentDatabaseHandler spdxDocumentDatabaseHandler; + private final SpdxDocumentCreationInfoDatabaseHandler spdxDocumentCreationInfoDatabaseHandler; + private final SpdxPackageInfoDatabaseHandler spdxPackageInfoDatabaseHandler; private final DatabaseConnectorCloudant db; private DatabaseHandlerUtil dbHandlerUtil; @@ -105,6 +114,9 @@ public ModerationDatabaseHandler(Supplier httpClient, String dbN licenseDatabaseHandler = new LicenseDatabaseHandler(httpClient, dbName); projectDatabaseHandler = new ProjectDatabaseHandler(httpClient, dbName, attachmentDbName); componentDatabaseHandler = new ComponentDatabaseHandler(httpClient, dbName, attachmentDbName); + spdxDocumentDatabaseHandler = new SpdxDocumentDatabaseHandler(httpClient, DatabaseSettings.COUCH_DB_SPDX); + spdxDocumentCreationInfoDatabaseHandler = new SpdxDocumentCreationInfoDatabaseHandler(httpClient, DatabaseSettings.COUCH_DB_SPDX); + spdxPackageInfoDatabaseHandler = new SpdxPackageInfoDatabaseHandler(httpClient, DatabaseSettings.COUCH_DB_SPDX); DatabaseConnectorCloudant dbChangeLogs = new DatabaseConnectorCloudant(httpClient, DatabaseSettings.COUCH_DB_CHANGE_LOGS); this.dbHandlerUtil = new DatabaseHandlerUtil(dbChangeLogs); } @@ -613,6 +625,101 @@ public void createRequest(User user) { addOrUpdate(request, user); } + private Set getSPDXDocumentModerators(String department, SPDXDocument dbSpdx) { + // Define moderators + Set moderators = new HashSet<>(); + CommonUtils.add(moderators, dbSpdx.getCreatedBy()); + CommonUtils.addAll(moderators, dbSpdx.getModerators()); + CommonUtils.addAll(moderators, getUsersAtLeast(UserGroup.ECC_ADMIN, department, false, true)); + CommonUtils.addAll(moderators, getUsersAtLeast(UserGroup.ADMIN)); + return moderators; + } + + private Set getSPDXDocumentCreationtModerators(String department, DocumentCreationInformation dbDocumentCreationInfo) { + // Define moderators + Set moderators = new HashSet<>(); + CommonUtils.add(moderators, dbDocumentCreationInfo.getCreatedBy()); + CommonUtils.addAll(moderators, dbDocumentCreationInfo.getModerators()); + CommonUtils.addAll(moderators, getUsersAtLeast(UserGroup.ECC_ADMIN, department, false, true)); + CommonUtils.addAll(moderators, getUsersAtLeast(UserGroup.ADMIN)); + return moderators; + } + + private Set getPackageInformationModerators(String department, PackageInformation packageInformation) { + // Define moderators + Set moderators = new HashSet<>(); + CommonUtils.add(moderators, packageInformation.getCreatedBy()); + CommonUtils.addAll(moderators, packageInformation.getModerators()); + CommonUtils.addAll(moderators, getUsersAtLeast(UserGroup.ECC_ADMIN, department, false, true)); + CommonUtils.addAll(moderators, getUsersAtLeast(UserGroup.ADMIN)); + return moderators; + } + + public RequestStatus createRequest(SPDXDocument spdx, User user, Boolean isDeleteRequest) { + SPDXDocument dbSpdx; + try { + dbSpdx = spdxDocumentDatabaseHandler.getSPDXDocumentById(spdx.getId(), user); + } catch (SW360Exception e) { + log.error("Could not get original SPDX Document from database. Could not generate moderation request.", e); + return RequestStatus.FAILURE; + } + // Define moderators + Set moderators = getSPDXDocumentModerators(user.getDepartment(), dbSpdx); + ModerationRequest request = createStubRequest(user, isDeleteRequest, spdx.getId(), moderators); + + // Set meta-data + request.setDocumentType(DocumentType.SPDX_DOCUMENT); + request.setDocumentName(SW360Utils.printName(spdx)); + + // Fill the request + ModerationRequestGenerator generator = new SpdxDocumentModerationRequestGenerator(); + request = generator.setAdditionsAndDeletions(request, spdx, dbSpdx); + addOrUpdate(request, user); + return RequestStatus.SENT_TO_MODERATOR; + } + + public RequestStatus createRequest(DocumentCreationInformation documentCreationInfo, User user, Boolean isDeleteRequest) { + DocumentCreationInformation dbDocumentCreationInfo; + try { + dbDocumentCreationInfo = spdxDocumentCreationInfoDatabaseHandler.getDocumentCreationInformationById(documentCreationInfo.getId(), user); + } catch (SW360Exception e) { + log.error("Could not get original SPDX Document Creation Info from database. Could not generate moderation request.", e); + return RequestStatus.FAILURE; + } + // Define moderators + Set moderators = getSPDXDocumentCreationtModerators(user.getDepartment(), dbDocumentCreationInfo); + ModerationRequest request = createStubRequest(user, isDeleteRequest, documentCreationInfo.getId(), moderators); + // Set meta-data + request.setDocumentType(DocumentType.SPDX_DOCUMENT_CREATION_INFO); + request.setDocumentName(SW360Utils.printName(documentCreationInfo)); + // Fill the request + ModerationRequestGenerator generator = new SpdxDocumentCreationInfoModerationRequestGenerator(); + request = generator.setAdditionsAndDeletions(request, documentCreationInfo, dbDocumentCreationInfo); + addOrUpdate(request, user); + return RequestStatus.SENT_TO_MODERATOR; + } + + public RequestStatus createRequest(PackageInformation packageInfo, User user, Boolean isDeleteRequest) { + PackageInformation dbPackageInfo; + try { + dbPackageInfo = spdxPackageInfoDatabaseHandler.getPackageInformationById(packageInfo.getId(), user); + } catch (SW360Exception e) { + log.error("Could not get original SPDX Package Info from database. Could not generate moderation request.", e); + return RequestStatus.FAILURE; + } + // Define moderators + Set moderators = getPackageInformationModerators(user.getDepartment(), dbPackageInfo); + ModerationRequest request = createStubRequest(user, isDeleteRequest, packageInfo.getId(), moderators); + // Set meta-data + request.setDocumentType(DocumentType.SPDX_PACKAGE_INFO); + request.setDocumentName(SW360Utils.printName(packageInfo)); + // Fill the request + ModerationRequestGenerator generator = new SpdxPackageInfoModerationRequestGenerator(); + request = generator.setAdditionsAndDeletions(request, packageInfo, dbPackageInfo); + addOrUpdate(request, user); + return RequestStatus.SENT_TO_MODERATOR; + } + 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/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxDocumentCreationInfoModerationRequestGenerator.java b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxDocumentCreationInfoModerationRequestGenerator.java new file mode 100644 index 0000000000..1f5b764ed3 --- /dev/null +++ b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxDocumentCreationInfoModerationRequestGenerator.java @@ -0,0 +1,48 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.moderation.db; + +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; + +public class SpdxDocumentCreationInfoModerationRequestGenerator extends ModerationRequestGenerator { + @Override + public ModerationRequest setAdditionsAndDeletions(ModerationRequest request, DocumentCreationInformation updateDocumentCreationInfo, DocumentCreationInformation actualDocumentCreationInfo){ + updateDocument = updateDocumentCreationInfo; + actualDocument = actualDocumentCreationInfo; + + documentAdditions = new DocumentCreationInformation(); + documentDeletions = new DocumentCreationInformation(); + //required fields: + documentAdditions.setId(updateDocument.getId()); + documentDeletions.setId(actualDocument.getId()); + for (DocumentCreationInformation._Fields field : DocumentCreationInformation._Fields.values()) { + + if (actualDocument.getFieldValue(field) == null) { + documentAdditions.setFieldValue(field, updateDocument.getFieldValue(field)); + } else if (updateDocument.getFieldValue(field) == null) { + documentDeletions.setFieldValue(field, actualDocument.getFieldValue(field)); + } else if (!actualDocument.getFieldValue(field).equals(updateDocument.getFieldValue(field))) { + switch (field) { + case PERMISSIONS: + case DOCUMENT_STATE: + case CREATED_BY: + break; + default: + dealWithBaseTypes(field, DocumentCreationInformation.metaDataMap.get(field)); + } + } + } + request.setDocumentCreationInfoAdditions(documentAdditions); + request.setDocumentCreationInfoDeletions(documentDeletions); + return request; + } +} diff --git a/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxDocumentModerationRequestGenerator.java b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxDocumentModerationRequestGenerator.java new file mode 100644 index 0000000000..61d97c590d --- /dev/null +++ b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxDocumentModerationRequestGenerator.java @@ -0,0 +1,49 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.moderation.db; + +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.*; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; + +public class SpdxDocumentModerationRequestGenerator extends ModerationRequestGenerator { + @Override + public ModerationRequest setAdditionsAndDeletions(ModerationRequest request, SPDXDocument updateSpdx, SPDXDocument actualSpdx){ + updateDocument = updateSpdx; + actualDocument = actualSpdx; + + documentAdditions = new SPDXDocument(); + documentDeletions = new SPDXDocument(); + //required fields: + documentAdditions.setId(updateSpdx.getId()); + documentDeletions.setId(actualSpdx.getId()); + + for (SPDXDocument._Fields field : SPDXDocument._Fields.values()) { + + if (actualSpdx.getFieldValue(field) == null) { + documentAdditions.setFieldValue(field, updateSpdx.getFieldValue(field)); + } else if (updateSpdx.getFieldValue(field) == null) { + documentDeletions.setFieldValue(field, actualSpdx.getFieldValue(field)); + } else if (!actualSpdx.getFieldValue(field).equals(updateSpdx.getFieldValue(field))) { + switch (field) { + case PERMISSIONS: + case DOCUMENT_STATE: + case CREATED_BY: + break; + default: + dealWithBaseTypes(field, SPDXDocument.metaDataMap.get(field)); + } + } + } + request.setSPDXDocumentAdditions(documentAdditions); + request.setSPDXDocumentDeletions(documentDeletions); + return request; + } +} diff --git a/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxPackageInfoModerationRequestGenerator.java b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxPackageInfoModerationRequestGenerator.java new file mode 100644 index 0000000000..b7834bba9a --- /dev/null +++ b/backend/src/src-moderation/src/main/java/org/eclipse/sw360/moderation/db/SpdxPackageInfoModerationRequestGenerator.java @@ -0,0 +1,53 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.moderation.db; + +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; +import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; +import org.apache.thrift.protocol.TType; + +public class SpdxPackageInfoModerationRequestGenerator extends ModerationRequestGenerator { + @Override + public ModerationRequest setAdditionsAndDeletions(ModerationRequest request, PackageInformation updatePackageInfo, PackageInformation actualPackageInfo){ + updateDocument = updatePackageInfo; + actualDocument = actualPackageInfo; + + documentAdditions = new PackageInformation(); + documentDeletions = new PackageInformation(); + //required fields: + documentAdditions.setId(updateDocument.getId()); + documentDeletions.setId(actualDocument.getId()); + + for (PackageInformation._Fields field : PackageInformation._Fields.values()) { + if (PackageInformation.metaDataMap.get(field).valueMetaData.type == TType.BOOL && + actualDocument.getFieldValue(field) != updateDocument.getFieldValue(field)) { + documentAdditions.setFieldValue(field, updateDocument.getFieldValue(field)); + documentDeletions.setFieldValue(field, actualDocument.getFieldValue(field)); + } else if (actualDocument.getFieldValue(field) == null) { + documentAdditions.setFieldValue(field, updateDocument.getFieldValue(field)); + } else if (updateDocument.getFieldValue(field) == null) { + documentDeletions.setFieldValue(field, actualDocument.getFieldValue(field)); + } else if (!actualDocument.getFieldValue(field).equals(updateDocument.getFieldValue(field))) { + switch (field) { + case PERMISSIONS: + case DOCUMENT_STATE: + case CREATED_BY: + break; + default: + dealWithBaseTypes(field, PackageInformation.metaDataMap.get(field)); + } + } + } + request.setPackageInfoAdditions(documentAdditions); + request.setPackageInfoDeletions(documentDeletions); + return request; + } +} diff --git a/backend/src/src-spdxdocument/pom.xml b/backend/src/src-spdxdocument/pom.xml new file mode 100644 index 0000000000..a44a2789eb --- /dev/null +++ b/backend/src/src-spdxdocument/pom.xml @@ -0,0 +1,38 @@ + + + + 4.0.0 + + + org.eclipse.sw360 + backend-src + ${revision} + + + src-spdxdocument + jar + src-spdxdocument + + + + org.apache.logging.log4j + log4j-1.2-api + + + org.apache.commons + commons-lang3 + + + diff --git a/backend/src/src-spdxdocument/src/main/java/org/eclipse/sw360/spdxdocument/SPDXDocumentHandler.java b/backend/src/src-spdxdocument/src/main/java/org/eclipse/sw360/spdxdocument/SPDXDocumentHandler.java new file mode 100644 index 0000000000..9b0512c714 --- /dev/null +++ b/backend/src/src-spdxdocument/src/main/java/org/eclipse/sw360/spdxdocument/SPDXDocumentHandler.java @@ -0,0 +1,92 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.spdxdocument; + +import org.eclipse.sw360.datahandler.common.DatabaseSettings; +import org.eclipse.sw360.datahandler.db.spdx.document.*; +import org.eclipse.sw360.datahandler.thrift.RequestStatus; +import org.eclipse.sw360.datahandler.thrift.AddDocumentRequestSummary; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.*; +import org.eclipse.sw360.datahandler.thrift.users.User; + +import com.cloudant.client.api.CloudantClient; + +import org.apache.thrift.TException; + +import java.net.MalformedURLException; +import java.util.List; +import java.util.function.Supplier; + +import static org.eclipse.sw360.datahandler.common.SW360Assert.*; + +public class SPDXDocumentHandler implements SPDXDocumentService.Iface { + + SpdxDocumentDatabaseHandler handler; + + SPDXDocumentHandler() throws MalformedURLException { + handler = new SpdxDocumentDatabaseHandler(DatabaseSettings.getConfiguredClient(), DatabaseSettings.COUCH_DB_SPDX); + } + + SPDXDocumentHandler(Supplier httpClient, String dbName) throws MalformedURLException { + handler = new SpdxDocumentDatabaseHandler(httpClient, dbName); + } + + @Override + public List getSPDXDocumentSummary(User user) throws TException { + assertUser(user); + return handler.getSPDXDocumentSummary(user); + } + + @Override + public SPDXDocument getSPDXDocumentById(String id, User user) throws TException { + assertNotEmpty(id); + assertUser(user); + return handler.getSPDXDocumentById(id, user); + } + + @Override + public SPDXDocument getSPDXDocumentForEdit(String id, User user) throws TException { + assertNotEmpty(id); + assertUser(user); + return handler.getSPDXDocumentForEdit(id, user); + } + + @Override + public AddDocumentRequestSummary addSPDXDocument(SPDXDocument spdx, User user) throws TException { + assertNotNull(spdx); + assertUser(user); + return handler.addSPDXDocument(spdx, user); + } + + @Override + public RequestStatus updateSPDXDocument(SPDXDocument spdx, User user) throws TException { + assertNotNull(spdx); + assertUser(user); + return handler.updateSPDXDocument(spdx, user); + } + + @Override + public RequestStatus updateSPDXDocumentFromModerationRequest(SPDXDocument spdxAdditions, SPDXDocument spdxDeletions, User user) throws TException { + assertUser(user); + assertNotNull(spdxAdditions); + assertNotNull(spdxDeletions); + return handler.updateSPDXDocumentFromModerationRequest(spdxAdditions, spdxDeletions, user); + } + + @Override + public RequestStatus deleteSPDXDocument(String id, User user) throws TException { + assertId(id); + assertUser(user); + + return handler.deleteSPDXDocument(id, user); + } + +} diff --git a/backend/src/src-spdxdocument/src/main/java/org/eclipse/sw360/spdxdocument/SPDXDocumentServlet.java b/backend/src/src-spdxdocument/src/main/java/org/eclipse/sw360/spdxdocument/SPDXDocumentServlet.java new file mode 100644 index 0000000000..5d47b0d199 --- /dev/null +++ b/backend/src/src-spdxdocument/src/main/java/org/eclipse/sw360/spdxdocument/SPDXDocumentServlet.java @@ -0,0 +1,26 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.spdxdocument; + +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocumentService; +import org.apache.thrift.protocol.TCompactProtocol; +import org.eclipse.sw360.projects.Sw360ThriftServlet; + +import java.net.MalformedURLException; + +public class SPDXDocumentServlet extends Sw360ThriftServlet { + + public SPDXDocumentServlet() throws MalformedURLException { + // Create a service processor using the provided handler + super(new SPDXDocumentService.Processor<>(new SPDXDocumentHandler()), new TCompactProtocol.Factory()); + } + +} diff --git a/backend/src/src-spdxdocumentcreationinfo/pom.xml b/backend/src/src-spdxdocumentcreationinfo/pom.xml new file mode 100644 index 0000000000..145d3c4166 --- /dev/null +++ b/backend/src/src-spdxdocumentcreationinfo/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + + + org.eclipse.sw360 + backend-src + ${revision} + + + src-spdxdocumentcreationinfo + jar + src-spdxdocumentcreationinfo + + + + org.apache.logging.log4j + log4j-1.2-api + + + org.apache.commons + commons-lang3 + + + org.eclipse.sw360 + src-spdxdocument + ${project.version} + + + diff --git a/backend/src/src-spdxdocumentcreationinfo/src/main/java/org/eclipse/sw360/spdxdocumentcreationinfo/DocumentCreationInformationHandler.java b/backend/src/src-spdxdocumentcreationinfo/src/main/java/org/eclipse/sw360/spdxdocumentcreationinfo/DocumentCreationInformationHandler.java new file mode 100644 index 0000000000..a094bb1247 --- /dev/null +++ b/backend/src/src-spdxdocumentcreationinfo/src/main/java/org/eclipse/sw360/spdxdocumentcreationinfo/DocumentCreationInformationHandler.java @@ -0,0 +1,90 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.spdxdocumentcreationinfo; + +import org.eclipse.sw360.datahandler.common.DatabaseSettings; +import org.eclipse.sw360.datahandler.db.spdx.documentcreationinfo.*; +import org.eclipse.sw360.datahandler.thrift.RequestStatus; +import org.eclipse.sw360.datahandler.thrift.AddDocumentRequestSummary; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; +import org.eclipse.sw360.datahandler.thrift.users.User; + +import com.cloudant.client.api.CloudantClient; + +import org.apache.thrift.TException; + +import java.net.MalformedURLException; +import java.util.List; +import java.util.function.Supplier; + +import static org.eclipse.sw360.datahandler.common.SW360Assert.*; + +public class DocumentCreationInformationHandler implements DocumentCreationInformationService.Iface { + + SpdxDocumentCreationInfoDatabaseHandler handler; + + DocumentCreationInformationHandler() throws MalformedURLException { + handler = new SpdxDocumentCreationInfoDatabaseHandler(DatabaseSettings.getConfiguredClient(), DatabaseSettings.COUCH_DB_SPDX); + } + + DocumentCreationInformationHandler(Supplier httpClient, String dbName) throws MalformedURLException { + handler = new SpdxDocumentCreationInfoDatabaseHandler(httpClient, dbName); + } + + @Override + public List getDocumentCreationInformationSummary(User user) throws TException { + assertUser(user); + return handler.getDocumentCreationInformationSummary(user); + } + + @Override + public DocumentCreationInformation getDocumentCreationInformationById(String id, User user) throws TException { + assertNotEmpty(id); + assertUser(user); + return handler.getDocumentCreationInformationById(id, user); + } + + @Override + public DocumentCreationInformation getDocumentCreationInfoForEdit(String id, User user) throws TException { + assertNotEmpty(id); + assertUser(user); + return handler.getDocumentCreationInfoForEdit(id, user); + } + + @Override + public AddDocumentRequestSummary addDocumentCreationInformation(DocumentCreationInformation documentCreationInformation, User user) throws TException { + assertNotNull(documentCreationInformation); + assertUser(user); + return handler.addDocumentCreationInformation(documentCreationInformation, user); + } + + @Override + public RequestStatus updateDocumentCreationInformation(DocumentCreationInformation documentCreationInformation, User user) throws TException { + assertNotNull(documentCreationInformation); + assertUser(user); + return handler.updateDocumentCreationInformation(documentCreationInformation, user); + } + + @Override + public RequestStatus updateDocumentCreationInfomationFromModerationRequest(DocumentCreationInformation documentCreationInfoAdditions, DocumentCreationInformation documentCreationInfoDeletions, User user) throws TException { + assertUser(user); + return handler.updateDocumentCreationInfomationFromModerationRequest(documentCreationInfoAdditions, documentCreationInfoDeletions, user); + } + + @Override + public RequestStatus deleteDocumentCreationInformation(String id, User user) throws TException { + assertId(id); + assertUser(user); + + return handler.deleteDocumentCreationInformation(id, user); + } + +} diff --git a/backend/src/src-spdxdocumentcreationinfo/src/main/java/org/eclipse/sw360/spdxdocumentcreationinfo/DocumentCreationInformationServlet.java b/backend/src/src-spdxdocumentcreationinfo/src/main/java/org/eclipse/sw360/spdxdocumentcreationinfo/DocumentCreationInformationServlet.java new file mode 100644 index 0000000000..bd3865f634 --- /dev/null +++ b/backend/src/src-spdxdocumentcreationinfo/src/main/java/org/eclipse/sw360/spdxdocumentcreationinfo/DocumentCreationInformationServlet.java @@ -0,0 +1,26 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.spdxdocumentcreationinfo; + +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformationService; +import org.apache.thrift.protocol.TCompactProtocol; +import org.eclipse.sw360.projects.Sw360ThriftServlet; + +import java.net.MalformedURLException; + +public class DocumentCreationInformationServlet extends Sw360ThriftServlet { + + public DocumentCreationInformationServlet() throws MalformedURLException { + // Create a service processor using the provided handler + super(new DocumentCreationInformationService.Processor<>(new DocumentCreationInformationHandler()), new TCompactProtocol.Factory()); + } + +} diff --git a/backend/src/src-spdxpackageinfo/pom.xml b/backend/src/src-spdxpackageinfo/pom.xml new file mode 100644 index 0000000000..54630aeef5 --- /dev/null +++ b/backend/src/src-spdxpackageinfo/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + + + org.eclipse.sw360 + backend-src + ${revision} + + + src-spdxpackageinfo + jar + src-spdxpackageinfo + + + + org.apache.logging.log4j + log4j-1.2-api + + + org.apache.commons + commons-lang3 + + + org.eclipse.sw360 + src-spdxdocument + ${project.version} + + + diff --git a/backend/src/src-spdxpackageinfo/src/main/java/org/eclipse/sw360/spdxpackageinfo/PackageInformationHandler.java b/backend/src/src-spdxpackageinfo/src/main/java/org/eclipse/sw360/spdxpackageinfo/PackageInformationHandler.java new file mode 100644 index 0000000000..ce8d71ea4a --- /dev/null +++ b/backend/src/src-spdxpackageinfo/src/main/java/org/eclipse/sw360/spdxpackageinfo/PackageInformationHandler.java @@ -0,0 +1,103 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.spdxpackageinfo; + +import org.eclipse.sw360.datahandler.common.DatabaseSettings; +import org.eclipse.sw360.datahandler.db.spdx.packageinfo.*; +import org.eclipse.sw360.datahandler.thrift.RequestStatus; +import org.eclipse.sw360.datahandler.thrift.RequestSummary; +import org.eclipse.sw360.datahandler.thrift.AddDocumentRequestSummary; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.*; +import org.eclipse.sw360.datahandler.thrift.users.User; + +import com.cloudant.client.api.CloudantClient; + +import org.apache.thrift.TException; + +import java.net.MalformedURLException; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + +import static org.eclipse.sw360.datahandler.common.SW360Assert.*; + +public class PackageInformationHandler implements PackageInformationService.Iface { + + SpdxPackageInfoDatabaseHandler handler; + + PackageInformationHandler() throws MalformedURLException { + handler = new SpdxPackageInfoDatabaseHandler(DatabaseSettings.getConfiguredClient(), DatabaseSettings.COUCH_DB_SPDX); + } + + PackageInformationHandler(Supplier httpClient, String dbName) throws MalformedURLException { + handler = new SpdxPackageInfoDatabaseHandler(httpClient, dbName); + } + + @Override + public List getPackageInformationSummary(User user) throws TException { + assertUser(user); + return handler.getPackageInformationSummary(user); + } + + @Override + public PackageInformation getPackageInformationById(String id, User user) throws TException { + assertNotEmpty(id); + assertUser(user); + return handler.getPackageInformationById(id, user); + } + + @Override + public PackageInformation getPackageInformationForEdit(String id, User user) throws TException { + assertNotEmpty(id); + assertUser(user); + return handler.getPackageInformationForEdit(id, user); + } + + @Override + public AddDocumentRequestSummary addPackageInformation(PackageInformation packageInformation, User user) throws TException { + assertNotNull(packageInformation); + assertUser(user); + return handler.addPackageInformation(packageInformation, user); + } + + @Override + public AddDocumentRequestSummary addPackageInformations(Set packageInformations, User user) throws TException { + return handler.addPackageInformations(packageInformations, user); + } + + @Override + public RequestStatus updatePackageInformation(PackageInformation packageInformation, User user) throws TException { + assertNotNull(packageInformation); + assertUser(user); + return handler.updatePackageInformation(packageInformation, user); + } + + @Override + public RequestSummary updatePackageInformations(Set packageInformations, User user) throws TException { + assertUser(user); + return handler.updatePackageInformations(packageInformations, user); + } + + @Override + public RequestStatus updatePackageInfomationFromModerationRequest(PackageInformation packageInfoAdditions, PackageInformation packageInfoDeletions, User user) throws TException { + assertUser(user); + return handler.updatePackageInfomationFromModerationRequest(packageInfoAdditions, packageInfoDeletions, user); + } + + @Override + public RequestStatus deletePackageInformation(String id, User user) throws TException { + assertId(id); + assertUser(user); + + return handler.deletePackageInformation(id, user); + } + +} diff --git a/backend/src/src-spdxpackageinfo/src/main/java/org/eclipse/sw360/spdxpackageinfo/PackageInformationServlet.java b/backend/src/src-spdxpackageinfo/src/main/java/org/eclipse/sw360/spdxpackageinfo/PackageInformationServlet.java new file mode 100644 index 0000000000..7c8256c443 --- /dev/null +++ b/backend/src/src-spdxpackageinfo/src/main/java/org/eclipse/sw360/spdxpackageinfo/PackageInformationServlet.java @@ -0,0 +1,26 @@ +/* + * Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project. + * Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.spdxpackageinfo; + +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformationService; +import org.apache.thrift.protocol.TCompactProtocol; +import org.eclipse.sw360.projects.Sw360ThriftServlet; + +import java.net.MalformedURLException; + +public class PackageInformationServlet extends Sw360ThriftServlet { + + public PackageInformationServlet() throws MalformedURLException { + // Create a service processor using the provided handler + super(new PackageInformationService.Processor<>(new PackageInformationHandler()), new TCompactProtocol.Factory()); + } + +} diff --git a/backend/svc/pom.xml b/backend/svc/pom.xml index 467a7f1f2e..a0c9640687 100644 --- a/backend/svc/pom.xml +++ b/backend/svc/pom.xml @@ -42,6 +42,9 @@ svc-wsimport svc-changelogs svc-health + svc-spdxdocument + svc-spdxdocumentcreationinfo + svc-spdxpackageinfo diff --git a/backend/svc/svc-spdxdocument/pom.xml b/backend/svc/svc-spdxdocument/pom.xml new file mode 100644 index 0000000000..f1e8a1f9d4 --- /dev/null +++ b/backend/svc/svc-spdxdocument/pom.xml @@ -0,0 +1,72 @@ + + + + 4.0.0 + + + org.eclipse.sw360 + backend-svc + ${revision} + + + svc-spdxdocument + war + svc-spdxdocument + + + ${backend.deploy.dir} + + + + spdxdocument + + + + maven-dependency-plugin + + + add-build-configuration-resources + generate-resources + + unpack + + + + + org.eclipse.sw360 + src-${project.build.finalName} + ${project.version} + jar + true + ${project.build.outputDirectory} + **/*.java,**/*.class + + + + + + + + + + + + org.eclipse.sw360 + src-${project.build.finalName} + ${project.version} + jar + + + diff --git a/backend/svc/svc-spdxdocument/src/main/webapp/WEB-INF/web.xml b/backend/svc/svc-spdxdocument/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..4f34f4aa10 --- /dev/null +++ b/backend/svc/svc-spdxdocument/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,37 @@ + + + + SPDX Document Service + + index.jsp + + + + org.eclipse.sw360.SW360ServiceContextListener + + + + SPDXDocumentService + org.eclipse.sw360.spdxdocument.SPDXDocumentServlet + 1 + + + + SPDXDocumentService + /thrift + + + diff --git a/backend/svc/svc-spdxdocument/src/main/webapp/index.jsp b/backend/svc/svc-spdxdocument/src/main/webapp/index.jsp new file mode 100644 index 0000000000..729fcde010 --- /dev/null +++ b/backend/svc/svc-spdxdocument/src/main/webapp/index.jsp @@ -0,0 +1,21 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Welcome to the SW360 SPDX Document Service + + +

    Welcome to the SW360 SPDX Document Service!

    + + diff --git a/backend/svc/svc-spdxdocumentcreationinfo/pom.xml b/backend/svc/svc-spdxdocumentcreationinfo/pom.xml new file mode 100644 index 0000000000..d2bc99fc7f --- /dev/null +++ b/backend/svc/svc-spdxdocumentcreationinfo/pom.xml @@ -0,0 +1,72 @@ + + + + 4.0.0 + + + org.eclipse.sw360 + backend-svc + ${revision} + + + svc-spdxdocumentcreationinfo + war + svc-spdxdocumentcreationinfo + + + ${backend.deploy.dir} + + + + spdxdocumentcreationinfo + + + + maven-dependency-plugin + + + add-build-configuration-resources + generate-resources + + unpack + + + + + org.eclipse.sw360 + src-${project.build.finalName} + ${project.version} + jar + true + ${project.build.outputDirectory} + **/*.java,**/*.class + + + + + + + + + + + + org.eclipse.sw360 + src-${project.build.finalName} + ${project.version} + jar + + + diff --git a/backend/svc/svc-spdxdocumentcreationinfo/src/main/webapp/WEB-INF/web.xml b/backend/svc/svc-spdxdocumentcreationinfo/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..9a29a4ec99 --- /dev/null +++ b/backend/svc/svc-spdxdocumentcreationinfo/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,37 @@ + + + + SPDX Document Creation Information Service + + index.jsp + + + + org.eclipse.sw360.SW360ServiceContextListener + + + + DocumentCreationInformationService + org.eclipse.sw360.spdxdocumentcreationinfo.DocumentCreationInformationServlet + 1 + + + + DocumentCreationInformationService + /thrift + + + diff --git a/backend/svc/svc-spdxdocumentcreationinfo/src/main/webapp/index.jsp b/backend/svc/svc-spdxdocumentcreationinfo/src/main/webapp/index.jsp new file mode 100644 index 0000000000..12d306ffae --- /dev/null +++ b/backend/svc/svc-spdxdocumentcreationinfo/src/main/webapp/index.jsp @@ -0,0 +1,21 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Welcome to the SW360 SPDX Document Creation Information Service + + +

    Welcome to the SW360 SPDX Document Creation Information Service!

    + + diff --git a/backend/svc/svc-spdxpackageinfo/pom.xml b/backend/svc/svc-spdxpackageinfo/pom.xml new file mode 100644 index 0000000000..ac4d20b937 --- /dev/null +++ b/backend/svc/svc-spdxpackageinfo/pom.xml @@ -0,0 +1,72 @@ + + + + 4.0.0 + + + org.eclipse.sw360 + backend-svc + ${revision} + + + svc-spdxpackageinfo + war + svc-spdxpackageinfo + + + ${backend.deploy.dir} + + + + spdxpackageinfo + + + + maven-dependency-plugin + + + add-build-configuration-resources + generate-resources + + unpack + + + + + org.eclipse.sw360 + src-${project.build.finalName} + ${project.version} + jar + true + ${project.build.outputDirectory} + **/*.java,**/*.class + + + + + + + + + + + + org.eclipse.sw360 + src-${project.build.finalName} + ${project.version} + jar + + + diff --git a/backend/svc/svc-spdxpackageinfo/src/main/webapp/WEB-INF/web.xml b/backend/svc/svc-spdxpackageinfo/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..3d54caa482 --- /dev/null +++ b/backend/svc/svc-spdxpackageinfo/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,38 @@ + + + + SPDX Package Information Service + + index.jsp + + + + org.eclipse.sw360.SW360ServiceContextListener + + + + PackageInformationService + org.eclipse.sw360.spdxpackageinfo.PackageInformationServlet + 1 + + + + PackageInformationService + /thrift + + + diff --git a/backend/svc/svc-spdxpackageinfo/src/main/webapp/index.jsp b/backend/svc/svc-spdxpackageinfo/src/main/webapp/index.jsp new file mode 100644 index 0000000000..313504d7e8 --- /dev/null +++ b/backend/svc/svc-spdxpackageinfo/src/main/webapp/index.jsp @@ -0,0 +1,21 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Welcome to the SW360 SPDX Package Information Service + + +

    Welcome to the SW360 SPDX Package Information Service!

    + + 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 20b6e769b3..5d9ebdf3d8 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,10 @@ 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.components.Release; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocumentService; import org.eclipse.sw360.datahandler.thrift.changelogs.ChangedFields; import org.eclipse.sw360.datahandler.thrift.changelogs.ReferenceDocData; import org.eclipse.sw360.datahandler.thrift.users.User; @@ -125,8 +130,12 @@ private JSONObject serveChangeLogsList(ResourceRequest request, ResourceResponse } } - List changeLogsList = getFilteredChangeLogList(request, changeLogsClient); + List changeLogsList = getFilteredChangeLogList(request, changeLogsClient, null); + if (isReleaseChangesLog(changeLogsList)) { + changeLogsList = getChangesLogsForSPDX(request, changeLogsList, changeLogsClient); + } + changeLogsList.stream().forEach(cl -> cl.setChangeTimestamp(cl.getChangeTimestamp().split(" ")[0])); JSONArray jsonProjects = getChangeLogData(changeLogsList, paginationParameters, request); JSONObject jsonResult = createJSONObject(); jsonResult.put(DATATABLE_RECORDS_TOTAL, changeLogsList.size()); @@ -136,6 +145,49 @@ private JSONObject serveChangeLogsList(ResourceRequest request, ResourceResponse return jsonResult; } + private boolean isReleaseChangesLog(List changeLogsList) { + for (ChangeLogs changeLogs : changeLogsList) { + if (changeLogs.documentType.equals("release")){ + return true; + } + } + return false; + } + + private List getChangesLogsForSPDX(ResourceRequest request, List SPDXChangeLogsList, ChangeLogsService.Iface changeLogsClient) { + ComponentService.Iface componentClient = thriftClients.makeComponentClient(); + SPDXDocumentService.Iface SPDXClient = thriftClients.makeSPDXClient(); + User user = UserCacheHolder.getUserFromRequest(request); + String releaseId = request.getParameter(PortalConstants.DOCUMENT_ID); + try { + Release release = componentClient.getReleaseById(releaseId, user); + String spdxId = release.getSpdxId(); + if (!isNullOrEmpty(spdxId)) { + SPDXDocument spdxDocument = SPDXClient.getSPDXDocumentById(spdxId, user); + String spdxDocumentCreationInfoId = spdxDocument.getSpdxDocumentCreationInfoId(); + Set packageInfoIds = spdxDocument.getSpdxPackageInfoIds(); + List spdxChangeLogsList = getFilteredChangeLogList(request, changeLogsClient, spdxId); + SPDXChangeLogsList.addAll(spdxChangeLogsList); + if (!isNullOrEmpty(spdxDocumentCreationInfoId)) { + List spdxDocumentChangeLogsList = getFilteredChangeLogList(request, changeLogsClient, spdxDocumentCreationInfoId); + SPDXChangeLogsList.addAll(spdxDocumentChangeLogsList); + } + if (packageInfoIds != null) { + List packagesChangeLogsList = Lists.newArrayList(); + for (String packageInfoId : packageInfoIds) { + List packageChangeLogsList = getFilteredChangeLogList(request, changeLogsClient, packageInfoId); + packagesChangeLogsList.addAll(packageChangeLogsList); + } + SPDXChangeLogsList.addAll(packagesChangeLogsList); + } + Collections.sort(SPDXChangeLogsList, Comparator.comparing(ChangeLogs::getChangeTimestamp).reversed()); + } + } catch (TException e) { + log.error("Error while getting change logs for SPDX" + e); + } + return SPDXChangeLogsList; + } + private LiferayPortletURL getModerationPortletUrl(PortletRequest request) { Optional layout = LayoutLocalServiceUtil.getLayouts(QueryUtil.ALL_POS, QueryUtil.ALL_POS).stream() .filter(l -> ("/moderation").equals(l.getFriendlyURL())).findFirst(); @@ -150,9 +202,11 @@ private LiferayPortletURL getModerationPortletUrl(PortletRequest request) { } private List getFilteredChangeLogList(ResourceRequest request, - ChangeLogsService.Iface changeLogsClient) { + ChangeLogsService.Iface changeLogsClient, String docId) { final User user = UserCacheHolder.getUserFromRequest(request); - String docId = request.getParameter(PortalConstants.DOCUMENT_ID); + if (docId == null) { + docId = request.getParameter(PortalConstants.DOCUMENT_ID); + } try { return changeLogsClient.getChangeLogsByDocumentId(user, docId); } catch (TException exp) { 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 4cb9c8e950..e243a217dc 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 @@ -92,6 +92,7 @@ public class PortalConstants { public static final String SELECTED_TAB = "selectedTab"; public static final String IS_USER_ALLOWED_TO_MERGE = "isUserAllowedToMerge"; public static final String DOCUMENT_TYPE = "documentType"; + public static final String IS_SPDX_DOCUMENT = "isSpdxDocument"; public static final String VIEW_SIZE = "viewSize"; public static final String TOTAL_ROWS = "totalRows"; public static final String RESULT = "result"; @@ -728,6 +729,15 @@ public class PortalConstants { public static final boolean IS_SVM_ENABLED; + //! Specialized keys for SPDX + public static final String SPDX_DOCUMENT = "spdxDocument"; + public static final String SPDX_DOCUMENT_CREATION_INFO = "spdxDocumentCreationInfo"; + public static final String SPDX_PACKAGE_INFO = "spdxPackageInfo"; + public static final String ACTUAL_SPDX_DOCUMENT = "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); @@ -769,6 +779,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,REQUIREMENT_DESCRIPTION_FOR,SPECIFICATION_FOR,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/common/SpdxUtils.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/SpdxUtils.java new file mode 100644 index 0000000000..52657daa18 --- /dev/null +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/common/SpdxUtils.java @@ -0,0 +1,417 @@ +/* + * 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.eclipse.sw360.portal.common; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.liferay.portal.kernel.json.JSONArray; +import com.liferay.portal.kernel.json.JSONException; +import com.liferay.portal.kernel.json.JSONFactoryUtil; +import com.liferay.portal.kernel.json.JSONObject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.thrift.TException; +import org.eclipse.sw360.datahandler.thrift.ThriftClients; +import org.eclipse.sw360.datahandler.thrift.spdx.annotations.Annotations; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; +import org.eclipse.sw360.datahandler.thrift.spdx.otherlicensinginformationdetected.OtherLicensingInformationDetected; +import org.eclipse.sw360.datahandler.thrift.spdx.relationshipsbetweenspdxelements.RelationshipsBetweenSPDXElements; +import org.eclipse.sw360.datahandler.thrift.spdx.snippetinformation.SnippetInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.snippetinformation.SnippetRange; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocumentService; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.ExternalReference; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformationService; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageVerificationCode; +import org.eclipse.sw360.datahandler.thrift.users.User; + +import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; +import java.util.HashSet; +import java.util.Set; + +import static com.google.common.base.Strings.isNullOrEmpty; + +public abstract class SpdxUtils { + + private SpdxUtils() { + // Utility class with only static functions + } + + private static final Logger log = LogManager.getLogger(SpdxUtils.class); + private static final ObjectMapper mapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + private static SPDXDocument parseSPDXDocumentFromRequest(String jsonData) { + SPDXDocument spdx = new SPDXDocument(); + if (jsonData == null) { + return null; + } + try { + JSONObject json = JSONFactoryUtil.createJSONObject(jsonData); + Set snippets = parseSnippets(json); + json.remove("snippets"); + Set relationships = parseRelationships(json); + json.remove("relationships"); + Set annotations = parseAnnotations(json); + json.remove("annotations"); + Set licensingInfo = parseLicensingInfo(json); + json.remove("otherLicensingInformationDetecteds"); + json.remove("documentState"); + json.remove("permissions"); + try { + spdx = mapper.readValue(json.toJSONString(), SPDXDocument.class); + } catch (JsonProcessingException e) { + log.error("Error when read value json",e); + } + spdx.setSnippets(snippets); + spdx.setRelationships(relationships); + spdx.setAnnotations(annotations); + spdx.setOtherLicensingInformationDetecteds(licensingInfo); + } catch (JSONException e) { + log.error("Error when parse SPDXDocument",e); + } + return spdx; + } + + private static DocumentCreationInformation parseDocumentCreationInfoFromRequest(String jsonData) { + DocumentCreationInformation documentCreationInfo = new DocumentCreationInformation(); + if (jsonData == null) { + return null; + } + try { + JSONObject json = JSONFactoryUtil.createJSONObject(jsonData); + Set externalDocumentRefs = parseExternalDocumentReferences(json); + json.remove("externalDocumentRefs"); + Set creator = parseCreator(json); + json.remove("creator"); + json.remove("documentState"); + json.remove("permissions"); + try { + documentCreationInfo = mapper.readValue(json.toJSONString(), DocumentCreationInformation.class); + } catch (JsonProcessingException e) { + log.error("Error when read value json",e); + } + documentCreationInfo.setExternalDocumentRefs(externalDocumentRefs); + documentCreationInfo.setCreator(creator); + } catch (JSONException e) { + log.error("Error when parse documentCreationInfo",e); + } + return documentCreationInfo; + } + + private static PackageInformation parsePackageInfoFromRequest(String jsonData) { + PackageInformation packageInfo = new PackageInformation(); + if (jsonData == null) { + return null; + } + try { + JSONObject json = JSONFactoryUtil.createJSONObject(jsonData); + PackageVerificationCode packageVerificationCode = parsePackageVerificationCode(json); + json.remove("packageVerificationCode"); + Set checksums = parseChecksum(json); + json.remove("checksums"); + Set externalRefs = parseExternalReference(json); + json.remove("externalReferences"); + Set annotations = parseAnnotations(json); + json.remove("annotations"); + json.remove("documentState"); + json.remove("permissions"); + try { + packageInfo = mapper.readValue(json.toJSONString(), PackageInformation.class); + } catch (JsonProcessingException e) { + log.error("Error when read value json",e); + } + packageInfo.setPackageVerificationCode(packageVerificationCode); + packageInfo.setChecksums(checksums); + packageInfo.setExternalRefs(externalRefs); + packageInfo.setAnnotations(annotations); + } catch (JSONException e) { + log.error("Error when parse packageInfo",e); + } + return packageInfo; + } + + private static Set parsePackageInfosFromRequest(String jsonData) { + Set packageInfos = new HashSet<>(); + if (jsonData == null) { + return null; + } + try { + JSONArray arrayPackages = JSONFactoryUtil.createJSONArray(jsonData); + if (arrayPackages == null) { + return packageInfos; + } + for (int i = 0; i < arrayPackages.length(); i++) { + PackageInformation packageInfo = parsePackageInfoFromRequest(arrayPackages.getJSONObject(i).toJSONString()); + if (packageInfo != null) { + packageInfos.add(packageInfo); + } + } + } catch (JSONException e) { + log.error("Error when parse packageInfo",e); + } + return packageInfos; + } + + public static void updateSPDX(ActionRequest request, ActionResponse response, User user, String releaseId, Set moderators, boolean addNew) throws TException { + String spdxDocumentData; + String documentCreationInfoData; + String packageInfoData; + String spdxDocumentId = ""; + if (addNew) { + spdxDocumentData = (String) request.getAttribute(SPDXDocument._Fields.TYPE.toString()); + documentCreationInfoData = (String) request.getAttribute(SPDXDocument._Fields.SPDX_DOCUMENT_CREATION_INFO_ID.toString()); + packageInfoData = (String) request.getAttribute(SPDXDocument._Fields.SPDX_PACKAGE_INFO_IDS.toString()); + } else { + spdxDocumentData = request.getParameter(SPDXDocument._Fields.TYPE.toString()); + documentCreationInfoData = request.getParameter(SPDXDocument._Fields.SPDX_DOCUMENT_CREATION_INFO_ID.toString()); + packageInfoData = request.getParameter(SPDXDocument._Fields.SPDX_PACKAGE_INFO_IDS.toString()); + } + if (!isNullOrEmpty(spdxDocumentData)) { + SPDXDocument spdx = parseSPDXDocumentFromRequest(spdxDocumentData); + spdx.setModerators(moderators); + SPDXDocumentService.Iface spdxClient = new ThriftClients().makeSPDXClient(); + if (spdx != null) { + if (isNullOrEmpty(spdx.getReleaseId()) && !isNullOrEmpty(releaseId)) { + spdx.setReleaseId(releaseId); + } + if (isNullOrEmpty(spdx.getId())) { + spdx.unsetId(); + spdx.unsetRevision(); + spdxDocumentId = spdxClient.addSPDXDocument(spdx, user).getId(); + } else { + spdxClient.updateSPDXDocument(spdx, user); + spdxDocumentId = spdx.getId(); + } + } + } + if (!isNullOrEmpty(documentCreationInfoData)) { + DocumentCreationInformation document = parseDocumentCreationInfoFromRequest(documentCreationInfoData); + document.setModerators(moderators); + if (document != null) { + DocumentCreationInformationService.Iface documentClient = new ThriftClients().makeSPDXDocumentInfoClient(); + if (isNullOrEmpty(document.getSpdxDocumentId())) { + document.setSpdxDocumentId(spdxDocumentId); + } + if (isNullOrEmpty(document.getId())) { + document.unsetId(); + document.unsetRevision(); + documentClient.addDocumentCreationInformation(document, user); + } else { + documentClient.updateDocumentCreationInformation(document, user); + } + } + } + if (!isNullOrEmpty(packageInfoData)) { + Set packageInfos = parsePackageInfosFromRequest(packageInfoData); + SPDXDocumentService.Iface SPDXClient = new ThriftClients().makeSPDXClient(); + SPDXDocument spdxDocument = SPDXClient.getSPDXDocumentById(spdxDocumentId, user); + idDeletePackageInfo(packageInfos, spdxDocument, user); + if (packageInfos != null) { + PackageInformationService.Iface packageClient = new ThriftClients().makeSPDXPackageInfoClient(); + for (PackageInformation packageInfo : packageInfos) { + packageInfo.setModerators(moderators); + if (isNullOrEmpty(packageInfo.getSpdxDocumentId())) { + packageInfo.setSpdxDocumentId(spdxDocumentId); + } + if (isNullOrEmpty(packageInfo.getId())) { + packageInfo.unsetId(); + packageInfo.unsetRevision(); + packageClient.addPackageInformation(packageInfo, user); + } else { + packageClient.updatePackageInformation(packageInfo, user); + } + } + } + } + } + + private static void idDeletePackageInfo(Set packageInfos, SPDXDocument spdxDocument, User user) { + Set spdxDocumentId = spdxDocument.getSpdxPackageInfoIds(); + Set listIdPackageInfos = new HashSet<>(); + packageInfos.forEach(pInfo -> listIdPackageInfos.add(pInfo.getId())); + for (String s : spdxDocumentId) { + if (!listIdPackageInfos.contains(s)) { + PackageInformationService.Iface packageClient = new ThriftClients().makeSPDXPackageInfoClient(); + try { + packageClient.deletePackageInformation(s, user); + } catch (Exception e) { + log.error("Could not delete SDPX Package Info {}", e.getMessage()); + } + } + } + } + + private static Set parseSnippets(JSONObject json) { + Set snippets = new HashSet<>(); + JSONArray arraySnippets = json.getJSONArray("snippets"); + if (arraySnippets == null) { + return snippets; + } + for (int i = 0; i < arraySnippets.length(); i++) { + try { + JSONObject objectSnippet = arraySnippets.getJSONObject(i); + JSONArray arraySnippet = objectSnippet.getJSONArray("snippetRanges"); + objectSnippet.remove("snippetRanges"); + SnippetInformation snippet = mapper.readValue(objectSnippet.toJSONString(), SnippetInformation.class); + Set snippetRanges = new HashSet<>(); + for (int j = 0; j < arraySnippet.length(); j++) { + snippetRanges.add(mapper.readValue(arraySnippet.getString(j), SnippetRange.class)); + } + snippet.setSnippetRanges(snippetRanges); + snippets.add(snippet); + } catch (JsonProcessingException e) { + log.error("Error when parse snippets",e); + } + } + return snippets; + } + + private static Set parseRelationships(JSONObject json) { + Set relationships = new HashSet<>(); + JSONArray arrayRelationships = json.getJSONArray("relationships"); + if (arrayRelationships == null) { + return relationships; + } + for (int i = 0; i < arrayRelationships.length(); i++) { + try { + relationships + .add(mapper.readValue(arrayRelationships.getString(i), RelationshipsBetweenSPDXElements.class)); + } catch (JsonProcessingException e) { + log.error("Error when parse relationship",e); + } + } + return relationships; + } + + private static Set parseAnnotations(JSONObject json) { + Set annotations = new HashSet<>(); + JSONArray arrayAnnotations = json.getJSONArray("annotations"); + if (arrayAnnotations == null) { + return annotations; + } + for (int i = 0; i < arrayAnnotations.length(); i++) { + try { + annotations.add(mapper.readValue(arrayAnnotations.getString(i), Annotations.class)); + } catch (JsonProcessingException e) { + log.error("Error when parse annotations",e); + } + } + return annotations; + } + + private static Set parseLicensingInfo(JSONObject json) { + Set licensingInfo = new HashSet<>(); + JSONArray arrayLicensingInfo = json.getJSONArray("otherLicensingInformationDetecteds"); + if (arrayLicensingInfo == null) { + return licensingInfo; + } + for (int i = 0; i < arrayLicensingInfo.length(); i++) { + try { + licensingInfo.add( + mapper.readValue(arrayLicensingInfo.getString(i), OtherLicensingInformationDetected.class)); + } catch (JsonProcessingException e) { + log.error("Error when parse licensingInfo",e); + } + } + return licensingInfo; + } + + private static Set parseExternalDocumentReferences(JSONObject json) { + Set externalDocumentRefs = new HashSet<>(); + JSONArray arrayExternalDocumentRefs = json.getJSONArray("externalDocumentRefs"); + if (arrayExternalDocumentRefs == null) { + return externalDocumentRefs; + } + for (int i = 0; i < arrayExternalDocumentRefs.length(); i++) { + try { + JSONObject objectExternalDocumentRef = arrayExternalDocumentRefs.getJSONObject(i); + JSONObject objectChecksum = objectExternalDocumentRef.getJSONObject("checksum"); + objectExternalDocumentRef.remove("checksum"); + ExternalDocumentReferences externalDocumentRef = mapper.readValue(objectExternalDocumentRef.toJSONString(), ExternalDocumentReferences.class); + CheckSum checksum = mapper.readValue(objectChecksum.toJSONString(), CheckSum.class); + externalDocumentRef.setChecksum(checksum); + externalDocumentRefs.add(externalDocumentRef); + } catch (JsonProcessingException e) { + log.error("Error when parse ExternalDocumentReferences",e); + } + } + return externalDocumentRefs; + } + + private static Set parseCreator(JSONObject json) { + Set creator = new HashSet<>(); + JSONArray arrayCreator = json.getJSONArray("creator"); + if (arrayCreator == null) { + return creator; + } + for (int i = 0; i < arrayCreator.length(); i++) { + try { + creator.add(mapper.readValue(arrayCreator.getString(i), Creator.class)); + } catch (JsonProcessingException e) { + log.error("Error when parse Creator",e); + } + } + return creator; + } + + private static PackageVerificationCode parsePackageVerificationCode(JSONObject json) { + PackageVerificationCode packageVerificationCode = new PackageVerificationCode(); + JSONObject objectPackageVerificationCode = json.getJSONObject("packageVerificationCode"); + if (objectPackageVerificationCode == null) { + return packageVerificationCode; + } + try { + packageVerificationCode = mapper.readValue(objectPackageVerificationCode.toJSONString(), + PackageVerificationCode.class); + } catch (JsonProcessingException e) { + log.error("Error when parse PackageVerificationCode",e); + } + return packageVerificationCode; + } + + private static Set parseChecksum(JSONObject json) { + Set checkSums = new HashSet<>(); + JSONArray arrayCheckSums = json.getJSONArray("checksums"); + if (arrayCheckSums == null) { + return checkSums; + } + for (int i = 0; i < arrayCheckSums.length(); i++) { + try { + checkSums.add(mapper.readValue(arrayCheckSums.getString(i), CheckSum.class)); + } catch (JsonProcessingException e) { + log.error("Error when parse parse Checksum",e); + } + } + return checkSums; + } + + private static Set parseExternalReference(JSONObject json) { + Set externalRefs = new HashSet<>(); + JSONArray arrayExternalRefs = json.getJSONArray("externalRefs"); + if (arrayExternalRefs == null) { + return externalRefs; + } + for (int i = 0; i < arrayExternalRefs.length(); i++) { + try { + externalRefs.add(mapper.readValue(arrayExternalRefs.getString(i), ExternalReference.class)); + } catch (JsonProcessingException e) { + log.error("Error when parse ExternalReference",e); + } + } + return externalRefs; + } + +} 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 c199d8e9d5..85e0157d23 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 @@ -159,10 +159,10 @@ protected void renderRequestPreparation(PortletRequest request, MimeResponse res 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.isSetComponentsName()) + jsonObject.put("componentsName", requestPreparation.componentsName); + if (requestPreparation.isSetReleasesName()) + jsonObject.put("releasesName", requestPreparation.releasesName); if (requestPreparation.isSetMessage()) jsonObject.put("message", requestPreparation.message); 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 4d3695d3ee..8d65bd1b86 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 @@ -12,10 +12,12 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; +import com.google.common.base.Predicate; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.liferay.portal.kernel.json.JSONArray; @@ -55,12 +57,17 @@ import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseNameWithText; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.projects.ProjectService; +import org.eclipse.sw360.datahandler.thrift.spdx.annotations.Annotations; import org.eclipse.sw360.datahandler.thrift.users.RequestedAction; import org.eclipse.sw360.datahandler.thrift.users.User; import org.eclipse.sw360.datahandler.thrift.users.UserGroup; import org.eclipse.sw360.datahandler.thrift.vendors.Vendor; import org.eclipse.sw360.datahandler.thrift.vendors.VendorService; import org.eclipse.sw360.datahandler.thrift.vulnerabilities.*; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.*; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.*; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation._Fields; import org.eclipse.sw360.exporter.ComponentExporter; import org.eclipse.sw360.portal.common.*; import org.eclipse.sw360.portal.common.datatables.PaginationParser; @@ -104,6 +111,7 @@ import static org.eclipse.sw360.portal.common.PortletUtils.setDepartmentSearchAttribute; import org.apache.thrift.transport.TTransportException; +import org.apache.thrift.protocol.TType; @org.osgi.service.component.annotations.Component( immediate = true, @@ -183,6 +191,8 @@ protected Set getAttachments(String documentId, String documentType, private static final String CONFIG_KEY_URL = "url"; + private _Fields field; + //! Serve resource and helpers @Override public void serveResource(ResourceRequest request, ResourceResponse response) throws IOException, PortletException { @@ -332,7 +342,6 @@ 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); - try { final RequestSummary requestSummary = componentClient.importBomFromAttachmentContent(user, attachmentContentId); @@ -979,7 +988,8 @@ 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)); - + boolean isSpdxDocument = SW360Constants.SPDX_DOCUMENT_ENABLED; + request.setAttribute(IS_SPDX_DOCUMENT, isSpdxDocument); if (isNullOrEmpty(id) && isNullOrEmpty(releaseId)) { throw new PortletException("Component or Release ID not set!"); } @@ -989,6 +999,10 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) Component component; Release release = (Release) request.getAttribute(RELEASE); + SPDXDocument spdxDocument = new SPDXDocument(); + DocumentCreationInformation documentCreationInfo = new DocumentCreationInformation(); + Set packageInfos = new HashSet<>(); + PackageInformation packageInfo = new PackageInformation(); if (!isNullOrEmpty(releaseId)) { release = release == null ? client.getAccessibleReleaseByIdForEdit(releaseId, user) : release; Map sortedAdditionalData = getSortedMap(release.getAdditionalData(), true); @@ -1008,6 +1022,26 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) } component = client.getAccessibleComponentById(id, user); + if (SW360Constants.SPDX_DOCUMENT_ENABLED){ + String spdxDocumentId = release.getSpdxId(); + if (!isNullOrEmpty(spdxDocumentId)) { + SPDXDocumentService.Iface SPDXDocumentClient = thriftClients.makeSPDXClient(); + spdxDocument = SPDXDocumentClient.getSPDXDocumentForEdit(spdxDocumentId, user); + String spdxDocumentCreationInfoId = spdxDocument.getSpdxDocumentCreationInfoId(); + Set spdxPackageInfoIds = spdxDocument.getSpdxPackageInfoIds(); + if (!isNullOrEmpty(spdxDocumentCreationInfoId)) { + DocumentCreationInformationService.Iface doClient = thriftClients.makeSPDXDocumentInfoClient(); + documentCreationInfo = doClient.getDocumentCreationInfoForEdit(spdxDocumentCreationInfoId, user); + } + if (spdxPackageInfoIds != null && !spdxPackageInfoIds.isEmpty()) { + PackageInformationService.Iface paClient = thriftClients.makeSPDXPackageInfoClient(); + for (String spdxPackageInfoId : spdxPackageInfoIds) { + packageInfo = paClient.getPackageInformationForEdit(spdxPackageInfoId, user); + packageInfos.add(packageInfo); + } + } + } + } } else { component = client.getAccessibleComponentById(id, user); if(release == null) { @@ -1045,6 +1079,51 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) request.setAttribute(IS_USER_AT_LEAST_ECC_ADMIN, PermissionUtils.isUserAtLeast(UserGroup.ECC_ADMIN, user) || PermissionUtils.isUserAtLeastDesiredRoleInSecondaryGroup(UserGroup.ECC_ADMIN, allSecRoles) ? "Yes" : "No"); + if (SW360Constants.SPDX_DOCUMENT_ENABLED){ + + request.setAttribute(SPDX_DOCUMENT, spdxDocument); + request.setAttribute(SPDX_DOCUMENT_CREATION_INFO, documentCreationInfo); + request.setAttribute(SPDX_PACKAGE_INFO, packageInfos); + + ObjectMapper objectMapper = new ObjectMapper(); + try { + if (!spdxDocument.isSetId()) { + spdxDocument = generateSpdxDocument(); + } + String spdxDocumentJson = objectMapper.writeValueAsString(spdxDocument); + request.setAttribute("spdxDocumentJson", spdxDocumentJson); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String SpdxDocument",e); + } + try { + if (!documentCreationInfo.isSetId()) { + documentCreationInfo = generateDocumentCreationInformation(); + } + String documentCreationInfoJson = objectMapper.writeValueAsString(documentCreationInfo); + request.setAttribute("documentCreationInfoJson", documentCreationInfoJson); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String DocumentCreationInfo ",e); + } + try { + JSONArray packageArray = JSONFactoryUtil.createJSONArray(); + Set setPackage = new HashSet<>(); + if (!isNotEmpty(packageInfos)){ + packageInfo = generatePackageInfomation(); + String packageInfoJson = objectMapper.writeValueAsString(packageInfo); + setPackage.add(packageInfoJson); + packageArray.put(packageInfoJson); + } else { + for (PackageInformation pack : packageInfos) { + String packageInfoJson = objectMapper.writeValueAsString(pack); + setPackage.add(packageInfoJson); + packageArray.put(packageInfoJson); + } + } + request.setAttribute("packageInfoJson", setPackage); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String PackageInformation ",e); + } + } } catch (TException e) { if (e instanceof SW360Exception) { SW360Exception sw360Exp = (SW360Exception)e; @@ -1062,12 +1141,80 @@ private void prepareReleaseEdit(RenderRequest request, RenderResponse response) } } + private SPDXDocument generateSpdxDocument() { + SPDXDocument spdxDocument = new SPDXDocument(); + for (SPDXDocument._Fields field : SPDXDocument._Fields.values()) { + switch (SPDXDocument.metaDataMap.get(field).valueMetaData.type) { + case TType.SET: + spdxDocument.setFieldValue(field, new HashSet<>()); + break; + case TType.STRING: + spdxDocument.setFieldValue(field, ""); + break; + default: + break; + } + } + return spdxDocument; + } + + private DocumentCreationInformation generateDocumentCreationInformation() { + DocumentCreationInformation documentCreationInfo = new DocumentCreationInformation(); + for (DocumentCreationInformation._Fields field : DocumentCreationInformation._Fields.values()) { + switch (DocumentCreationInformation.metaDataMap.get(field).valueMetaData.type) { + case TType.SET: + documentCreationInfo.setFieldValue(field, new HashSet<>()); + break; + case TType.STRING: + documentCreationInfo.setFieldValue(field, ""); + break; + default: + break; + } + } + return documentCreationInfo; + } + + private PackageInformation generatePackageInfomation() { + PackageInformation packageInfo = new PackageInformation(); + + for (PackageInformation._Fields field : PackageInformation._Fields.values()) { + + switch (field) { + case PACKAGE_VERIFICATION_CODE: { + PackageVerificationCode packageVerificationCode = new PackageVerificationCode(); + packageInfo.setPackageVerificationCode(packageVerificationCode); + break; + } + default: { + this.field = field; + switch (PackageInformation.metaDataMap.get(field).valueMetaData.type) { + case TType.SET: + packageInfo.setFieldValue(field, new HashSet<>()); + break; + case TType.STRING: + packageInfo.setFieldValue(field, ""); + break; + case TType.BOOL: + packageInfo.setFieldValue(field, true); + default: + break; + } + break; + } + } + } + return packageInfo; + } + private void prepareReleaseDuplicate(RenderRequest request, RenderResponse response) throws PortletException { String id = request.getParameter(COMPONENT_ID); String releaseId = request.getParameter(RELEASE_ID); request.setAttribute(DOCUMENT_TYPE, SW360Constants.TYPE_RELEASE); final User user = UserCacheHolder.getUserFromRequest(request); request.setAttribute(IS_USER_AT_LEAST_CLEARING_ADMIN, PermissionUtils.isUserAtLeast(UserGroup.CLEARING_ADMIN, user)); + boolean isSpdxDocument = SW360Constants.SPDX_DOCUMENT_ENABLED; + request.setAttribute(IS_SPDX_DOCUMENT, isSpdxDocument); if (isNullOrEmpty(releaseId)) { throw new PortletException("Release ID not set!"); @@ -1078,7 +1225,6 @@ private void prepareReleaseDuplicate(RenderRequest request, RenderResponse respo String emailFromRequest = LifeRayUserSession.getEmailFromRequest(request); Release release = PortletUtils.cloneRelease(emailFromRequest, client.getAccessibleReleaseById(releaseId, user)); - PortletUtils.setCustomFieldsEdit(request, user, release); if (isNullOrEmpty(id)) { @@ -1625,7 +1771,8 @@ private void prepareReleaseDetailView(RenderRequest request, RenderResponse resp String id = request.getParameter(COMPONENT_ID); String releaseId = request.getParameter(RELEASE_ID); final User user = UserCacheHolder.getUserFromRequest(request); - + boolean isSpdxDocument = SW360Constants.SPDX_DOCUMENT_ENABLED; + request.setAttribute(IS_SPDX_DOCUMENT, isSpdxDocument); if (isNullOrEmpty(id) && isNullOrEmpty(releaseId)) { throw new PortletException("Component or Release ID not set!"); } @@ -1697,6 +1844,70 @@ private void prepareReleaseDetailView(RenderRequest request, RenderResponse resp addReleaseBreadcrumb(request, response, release); } + if (SW360Constants.SPDX_DOCUMENT_ENABLED ){ + String spdxDocumentId; + try { + spdxDocumentId = release.getSpdxId(); + }catch (NullPointerException nullPointerException){ + spdxDocumentId = null; + log.warn("Error when Create Release with SPDX ID " + nullPointerException.getMessage()); + } + SPDXDocument spdxDocument = new SPDXDocument(); + DocumentCreationInformation documentCreationInfo = new DocumentCreationInformation(); + PackageInformation packageInfo ; + Set packageInfos = new HashSet<>(); + if (!isNullOrEmpty(spdxDocumentId)) { + SPDXDocumentService.Iface SPDXDocumentClient = thriftClients.makeSPDXClient(); + spdxDocument = SPDXDocumentClient.getSPDXDocumentById(spdxDocumentId, user); + String spdxDocumentCreationInfoId = spdxDocument.getSpdxDocumentCreationInfoId(); + Set spdxPackageInfoIds = spdxDocument.getSpdxPackageInfoIds(); + if (!isNullOrEmpty(spdxDocumentCreationInfoId)) { + DocumentCreationInformationService.Iface doClient = thriftClients.makeSPDXDocumentInfoClient(); + documentCreationInfo = doClient.getDocumentCreationInformationById(spdxDocumentCreationInfoId, user); + } + if (spdxPackageInfoIds != null) { + PackageInformationService.Iface paClient = thriftClients.makeSPDXPackageInfoClient(); + for (String spdxPackageInfoId : spdxPackageInfoIds) { + packageInfo = paClient.getPackageInformationById(spdxPackageInfoId, user); + packageInfos.add(packageInfo); + } + } + request.setAttribute(SPDX_DOCUMENT, spdxDocument); + request.setAttribute(SPDX_DOCUMENT_CREATION_INFO, documentCreationInfo); + request.setAttribute(SPDX_PACKAGE_INFO, packageInfos); + } + + ObjectMapper objectMapper = new ObjectMapper(); + try { + if (!spdxDocument.isSetId()) { + spdxDocument = generateSpdxDocument(); + } + String spdxDocumentJson = objectMapper.writeValueAsString(spdxDocument); + request.setAttribute("spdxDocumentJson", spdxDocumentJson); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String SpdxDocument",e); + } + try { + if (!documentCreationInfo.isSetId()) { + documentCreationInfo = generateDocumentCreationInformation(); + } + String documentCreationInfoJson = objectMapper.writeValueAsString(documentCreationInfo); + request.setAttribute("documentCreationInfoJson", documentCreationInfoJson); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String DocumentCreationInfo",e); + } + try { + Set setPackage = new HashSet<>(); + for (PackageInformation pack : packageInfos) { + String packageInfoJson = objectMapper.writeValueAsString(pack); + setPackage.add(packageInfoJson); + } + request.setAttribute("packageInfoJson", setPackage); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String PackageInformation",e); + } + } + } catch (TException e) { if (e instanceof SW360Exception) { SW360Exception sw360Exp = (SW360Exception)e; @@ -2104,7 +2315,7 @@ public void updateRelease(ActionRequest request, ActionResponse response) throws response.setRenderParameter(RELEASE_ID, releaseId); return; } - + Set moderators = release.getModerators(); RequestStatus requestStatus = client.updateRelease(release, user); setSessionMessage(request, requestStatus, "Release", "update", printName(release)); if (RequestStatus.DUPLICATE.equals(requestStatus) || RequestStatus.DUPLICATE_ATTACHMENT.equals(requestStatus) || @@ -2138,13 +2349,15 @@ else if (RequestStatus.NAMINGERROR.equals(requestStatus)) request.setAttribute(WebKeys.REDIRECT, redirectUrl.toString()); sendRedirect(request, response); + if(SW360Constants.SPDX_DOCUMENT_ENABLED){ + SpdxUtils.updateSPDX(request, response, user, releaseId, moderators,false); + } } } else { release = new Release(); release.setComponentId(component.getId()); release.setClearingState(ClearingState.NEW_CLEARING); ComponentPortletUtils.updateReleaseFromRequest(request, release); - String cyclicLinkedReleasePath = client.getCyclicLinkedReleasePath(release, user); if (!isNullEmptyOrWhitespace(cyclicLinkedReleasePath)) { FossologyAwarePortlet.addCustomErrorMessage(CYCLIC_LINKED_RELEASE + cyclicLinkedReleasePath, @@ -2153,12 +2366,35 @@ else if (RequestStatus.NAMINGERROR.equals(requestStatus)) response.setRenderParameter(COMPONENT_ID, request.getParameter(COMPONENT_ID)); return; } - + Set moderators = release.getModerators(); AddDocumentRequestSummary summary = client.addRelease(release, user); AddDocumentRequestStatus status = summary.getRequestStatus(); switch(status){ case SUCCESS: + ObjectMapper objectMapper = new ObjectMapper(); + try { + String spdxDocumentJson = objectMapper.writeValueAsString(generateSpdxDocument()); + request.setAttribute(SPDXDocument._Fields.TYPE.toString(), spdxDocumentJson); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String SpdxDocumentJson",e); + } + try { + String documentCreationInfoJson = objectMapper.writeValueAsString(generateDocumentCreationInformation()); + request.setAttribute(SPDXDocument._Fields.SPDX_DOCUMENT_CREATION_INFO_ID.toString(), documentCreationInfoJson); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String DocumentCreationInfoJson",e); + } + try { + String packageInfoJson = objectMapper.writeValueAsString(generatePackageInfomation()); + packageInfoJson = "[" + packageInfoJson + "]"; + request.setAttribute(SPDXDocument._Fields.SPDX_PACKAGE_INFO_IDS.toString(), packageInfoJson); + } catch (JsonProcessingException e) { + log.error("Error when write Value As String PackageInfoJson",e); + } + if(SW360Constants.SPDX_DOCUMENT_ENABLED){ + SpdxUtils.updateSPDX(request, response, user, summary.getId(), moderators,true); + } response.setRenderParameter(RELEASE_ID, summary.getId()); String successMsg = "Release " + printName(release) + " added successfully"; SessionMessages.add(request, "request_processed", successMsg); 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 c832f35532..78715000bd 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 @@ -56,6 +56,12 @@ import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.projects.ProjectLink; import org.eclipse.sw360.datahandler.thrift.projects.ProjectService; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformationService; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocumentService; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformationService; import org.eclipse.sw360.datahandler.thrift.users.RequestedAction; import org.eclipse.sw360.datahandler.thrift.users.User; import org.eclipse.sw360.datahandler.thrift.users.UserGroup; @@ -602,6 +608,42 @@ private void acceptModerationRequest(User user, User requestingUser, ModerationR UserUtils.activateLiferayUser(request, moderationRequest.getUser()); } break; + case SPDX_DOCUMENT: { + SPDXDocumentService.Iface SpdxDocumentClient = thriftClients.makeSPDXClient(); + if (moderationRequest.isRequestDocumentDelete()) { + SpdxDocumentClient.deleteSPDXDocument(moderationRequest.getDocumentId(), user); + } else { + SpdxDocumentClient.updateSPDXDocumentFromModerationRequest( + moderationRequest.getSPDXDocumentAdditions(), + moderationRequest.getSPDXDocumentDeletions(), + user); + } + } + break; + case SPDX_DOCUMENT_CREATION_INFO: { + DocumentCreationInformationService.Iface documentCreationInfoClient = thriftClients.makeSPDXDocumentInfoClient(); + if (moderationRequest.isRequestDocumentDelete()) { + documentCreationInfoClient.deleteDocumentCreationInformation(moderationRequest.getDocumentId(), user); + } else { + documentCreationInfoClient.updateDocumentCreationInfomationFromModerationRequest( + moderationRequest.getDocumentCreationInfoAdditions(), + moderationRequest.getDocumentCreationInfoDeletions(), + user); + } + } + break; + case SPDX_PACKAGE_INFO: { + PackageInformationService.Iface packageInfoClient = thriftClients.makeSPDXPackageInfoClient(); + if (moderationRequest.isRequestDocumentDelete()) { + packageInfoClient.deletePackageInformation(moderationRequest.getDocumentId(), user); + } else { + packageInfoClient.updatePackageInfomationFromModerationRequest( + moderationRequest.getPackageInfoAdditions(), + moderationRequest.getPackageInfoDeletions(), + user); + } + } + break; } } @@ -772,6 +814,15 @@ private void renderEditViewForId(RenderRequest request, RenderResponse response, case USER: renderUserModeration(request, response, moderationRequest, user); break; + case SPDX_DOCUMENT: + renderSPDXDocumentModeration(request, response, moderationRequest, user); + break; + case SPDX_DOCUMENT_CREATION_INFO: + renderDocumentCreationInfoModeration(request, response, moderationRequest, user); + break; + case SPDX_PACKAGE_INFO: + renderPackageInfoModeration(request, response, moderationRequest, user); + break; } } } @@ -1005,6 +1056,93 @@ public void renderUserModeration(RenderRequest request, RenderResponse response include("/html/moderation/users/merge.jsp", request, response); } + public void renderSPDXDocumentModeration(RenderRequest request, RenderResponse response, ModerationRequest moderationRequest, User user) throws IOException, PortletException, TException { + final boolean requestDocumentDelete = moderationRequest.isRequestDocumentDelete(); + Boolean is_used = false; + SPDXDocument actual_SPDXDocuemnt = null; + try { + SPDXDocumentService.Iface client = thriftClients.makeSPDXClient(); + actual_SPDXDocuemnt = client.getSPDXDocumentForEdit(moderationRequest.getDocumentId(), user); + request.setAttribute(PortalConstants.ACTUAL_SPDX_DOCUMENT, actual_SPDXDocuemnt); + } catch (TException e) { + log.error("Could not retrieve SPDX Document", e); + } + + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (actual_SPDXDocuemnt == null) { + renderNextModeration(request, response, user, LanguageUtil.get(resourceBundle,"ignored.unretrievable.target"), thriftClients.makeModerationClient(), moderationRequest); + return; + } + + if (refuseToDeleteUsedDocument(request, response, moderationRequest, user, requestDocumentDelete, is_used)) + return; + + request.setAttribute(DOCUMENT_TYPE, SW360Constants.TYPE_SPDX_DOCUMENT); + if (moderationRequest.isRequestDocumentDelete()) { + include("/html/moderation/spdx/spdxDocument/delete.jsp", request, response); + } else { + include("/html/moderation/spdx/spdxDocument/merge.jsp", request, response); + } + } + + public void renderDocumentCreationInfoModeration(RenderRequest request, RenderResponse response, ModerationRequest moderationRequest, User user) throws IOException, PortletException, TException { + final boolean requestDocumentDelete = moderationRequest.isRequestDocumentDelete(); + Boolean is_used = false; + DocumentCreationInformation actual_DocuemntCreationInfo = null; + try { + DocumentCreationInformationService.Iface client = thriftClients.makeSPDXDocumentInfoClient(); + actual_DocuemntCreationInfo = client.getDocumentCreationInfoForEdit(moderationRequest.getDocumentId(), user); + request.setAttribute(PortalConstants.ACTUAL_DOCUMENT_CREATION_INFO, actual_DocuemntCreationInfo); + } catch (TException e) { + log.error("Could not retrieve Document Creation Information", e); + } + + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (actual_DocuemntCreationInfo == null) { + renderNextModeration(request, response, user, LanguageUtil.get(resourceBundle,"ignored.unretrievable.target"), thriftClients.makeModerationClient(), moderationRequest); + return; + } + + if (refuseToDeleteUsedDocument(request, response, moderationRequest, user, requestDocumentDelete, is_used)) + return; + + request.setAttribute(DOCUMENT_TYPE, SW360Constants.TYPE_SPDX_DOCUMENT_CREATION_INFO); + if (moderationRequest.isRequestDocumentDelete()) { + include("/html/moderation/spdx/documentCreationInfo/delete.jsp", request, response); + } else { + include("/html/moderation/spdx/documentCreationInfo/merge.jsp", request, response); + } + } + + public void renderPackageInfoModeration(RenderRequest request, RenderResponse response, ModerationRequest moderationRequest, User user) throws IOException, PortletException, TException { + final boolean requestDocumentDelete = moderationRequest.isRequestDocumentDelete(); + Boolean is_used = false; + PackageInformation actual_PackageInfo = null; + try { + PackageInformationService.Iface client = thriftClients.makeSPDXPackageInfoClient(); + actual_PackageInfo = client.getPackageInformationForEdit(moderationRequest.getDocumentId(), user); + request.setAttribute(PortalConstants.ACTUAL_PACKAGE_INFO, actual_PackageInfo); + } catch (TException e) { + log.error("Could not retrieve Package Information", e); + } + + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (actual_PackageInfo == null) { + renderNextModeration(request, response, user, LanguageUtil.get(resourceBundle,"ignored.unretrievable.target"), thriftClients.makeModerationClient(), moderationRequest); + return; + } + + if (refuseToDeleteUsedDocument(request, response, moderationRequest, user, requestDocumentDelete, is_used)) + return; + + request.setAttribute(DOCUMENT_TYPE, SW360Constants.TYPE_SPDX_PACKAGE_INFO); + if (moderationRequest.isRequestDocumentDelete()) { + include("/html/moderation/spdx/packageInfo/delete.jsp", request, response); + } else { + include("/html/moderation/spdx/packageInfo/merge.jsp", request, response); + } + } + @UsedAsLiferayAction public void applyFilters(ActionRequest request, ActionResponse response) throws PortletException, IOException { for (ModerationRequest._Fields moderationFilteredField : MODERATION_FILTERED_FIELDS) { diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplayDocumentCreationInfoChanges.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplayDocumentCreationInfoChanges.java new file mode 100644 index 0000000000..530c238355 --- /dev/null +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplayDocumentCreationInfoChanges.java @@ -0,0 +1,302 @@ +/* + * 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.portal.tags; + +import com.google.common.base.Strings; +import org.apache.commons.lang.StringEscapeUtils; +import com.liferay.portal.kernel.language.LanguageUtil; +import com.liferay.portal.kernel.util.ResourceBundleUtil; + +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; + +import org.apache.thrift.meta_data.FieldMetaData; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.ResourceBundle; +import java.util.Set; + +import static org.eclipse.sw360.portal.tags.TagUtils.*; + +public class DisplayDocumentCreationInfoChanges extends UserAwareTag { + private DocumentCreationInformation actual; + private DocumentCreationInformation additions; + private DocumentCreationInformation deletions; + private String tableClasses = ""; + private String idPrefix = ""; + + public void setActual(DocumentCreationInformation actual) { + this.actual = actual; + } + + public void setAdditions(DocumentCreationInformation additions) { + this.additions = additions; + } + + public void setDeletions(DocumentCreationInformation deletions) { + this.deletions = deletions; + } + + public void setTableClasses(String tableClasses) { + this.tableClasses = tableClasses; + } + + public void setIdPrefix(String idPrefix) { + this.idPrefix = idPrefix; + } + + public int doStartTag() throws JspException { + + JspWriter jspWriter = pageContext.getOut(); + + StringBuilder display = new StringBuilder(); + + if (additions == null || deletions == null) { + return SKIP_BODY; + } + + try { + for (DocumentCreationInformation._Fields field : DocumentCreationInformation._Fields.values()) { + switch (field) { + // ignored Fields + case ID: + case REVISION: + case TYPE: + case CREATED_BY: + case PERMISSIONS: + case DOCUMENT_STATE: + case EXTERNAL_DOCUMENT_REFS: + case CREATOR: + break; + default: + FieldMetaData fieldMetaData = DocumentCreationInformation.metaDataMap.get(field); + displaySimpleFieldOrSet(display, actual, additions, deletions, field, fieldMetaData, "", false); + } + } + + String renderString = display.toString(); + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), + getClass()); + + if (Strings.isNullOrEmpty(renderString)) { + renderString = "
    " + + LanguageUtil.get(resourceBundle, "no.changes.in.basic.fields") + "
    "; + } else { + renderString = String.format("", tableClasses, idPrefix) + + "" + + String.format("", + LanguageUtil.get(resourceBundle, "field.name"), + LanguageUtil.get(resourceBundle, "current.value"), + LanguageUtil.get(resourceBundle, "former.value"), + LanguageUtil.get(resourceBundle, "suggested.value")) + + renderString + "
    " + LanguageUtil.get(resourceBundle, "changes.for.basic.fields") + + "
    %s%s%s%s
    "; + } + String externalDocumentRefsRenderString = renderExternalDocumentRefs(); + String creatorRenderString = renderCreator(); + jspWriter.print(renderString + externalDocumentRefsRenderString.toString() + creatorRenderString.toString()); + } catch (Exception e) { + throw new JspException(e); + } + return SKIP_BODY; + } + + private boolean ensureSomethingTodoAndNoNull(DocumentCreationInformation._Fields field) { + if (!deletions.isSet(field) && !additions.isSet(field)) { + return false; + } + + if (field == DocumentCreationInformation._Fields.EXTERNAL_DOCUMENT_REFS) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } else if (field == DocumentCreationInformation._Fields.CREATOR) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } + return true; + } + + private String renderExternalDocumentRefs() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(DocumentCreationInformation._Fields.EXTERNAL_DOCUMENT_REFS)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(DocumentCreationInformation._Fields.EXTERNAL_DOCUMENT_REFS)) { + actual.externalDocumentRefs = new HashSet<>(); + } + + Set additionsExternalDocumentRefs = additions.getExternalDocumentRefs(); + Set deletionsExternalDocumentRefs = deletions.getExternalDocumentRefs(); + Set currentExternalDocumentRefs = actual.getExternalDocumentRefs(); + int changeSize = 0; + if (additionsExternalDocumentRefs.size() > deletionsExternalDocumentRefs.size()) { + changeSize = additionsExternalDocumentRefs.size() + currentExternalDocumentRefs.size() - deletionsExternalDocumentRefs.size(); + } else { + changeSize = currentExternalDocumentRefs.size(); + } + + for (int i = 0; i < changeSize; i++) { + ExternalDocumentReferences externalDocumentRefDeletions = getExternalDocumentRefsByIndex(deletions, i); + ExternalDocumentReferences externalDocumentRefAdditions = getExternalDocumentRefsByIndex(additions, i); + ExternalDocumentReferences externalDocumentRef = getExternalDocumentRefsByIndex(actual, i); + String checkSumRendeString = null; + + for (ExternalDocumentReferences._Fields field : ExternalDocumentReferences._Fields.values()) { + FieldMetaData fieldMetaData = ExternalDocumentReferences.metaDataMap.get(field); + if (field == ExternalDocumentReferences._Fields.CHECKSUM) { + checkSumRendeString = renderCheckSum(externalDocumentRef, externalDocumentRefAdditions, externalDocumentRefDeletions); + } else { + displaySimpleFieldOrSet( + display, + externalDocumentRef, + externalDocumentRefAdditions, + externalDocumentRefDeletions, + field, fieldMetaData, "", false); + } + } + if (checkSumRendeString != null) { + display.append(checkSumRendeString); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.external.document.references")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private ExternalDocumentReferences getExternalDocumentRefsByIndex(DocumentCreationInformation document, int index) { + ExternalDocumentReferences externalDocumentRefs; + Iterator externalDocumentRefsIterator = document.getExternalDocumentRefsIterator(); + while (externalDocumentRefsIterator.hasNext()) { + externalDocumentRefs = externalDocumentRefsIterator.next(); + if (externalDocumentRefs.getIndex() == index) { + externalDocumentRefs.setIndex(0); // Set 0 to not show Index when add or delete + return externalDocumentRefs; + } + } + return new ExternalDocumentReferences(); + } + + private String renderCreator() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(DocumentCreationInformation._Fields.CREATOR)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(DocumentCreationInformation._Fields.CREATOR)) { + actual.creator = new HashSet<>(); + } + + Set additionsCreators = additions.getCreator(); + Set deletionsCreators = deletions.getCreator(); + Set currentCreators = actual.getCreator(); + int changeSize = 0; + if (additionsCreators.size() > deletionsCreators.size()) { + changeSize = additionsCreators.size() + currentCreators.size() - deletionsCreators.size(); + } else { + changeSize = currentCreators.size(); + } + + for (int i = 0; i < changeSize; i++) { + Creator creatorDeletions = getCreatorByIndex(deletions, i); + Creator creatorAdditions = getCreatorByIndex(additions, i); + Creator creator = getCreatorByIndex(actual, i); + + for (Creator._Fields field : Creator._Fields.values()) { + FieldMetaData fieldMetaData = Creator.metaDataMap.get(field); + displaySimpleFieldOrSet( + display, + creator, + creatorAdditions, + creatorDeletions, + field, fieldMetaData, "", false); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.creator")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private Creator getCreatorByIndex(DocumentCreationInformation document, int index) { + Creator creator; + Iterator creatorIterator = document.getCreatorIterator(); + while (creatorIterator.hasNext()) { + creator = creatorIterator.next(); + if (creator.getIndex() == index) { + creator.setIndex(0); // Set 0 to not show Index when add or delete + return creator; + } + } + return new Creator(); + } + + private String renderCheckSum(ExternalDocumentReferences actualChecsum, ExternalDocumentReferences additionsChecsum, ExternalDocumentReferences deletionsChecsum) { + + if (!deletionsChecsum.isSet(ExternalDocumentReferences._Fields.CHECKSUM) + && !additionsChecsum.isSet(ExternalDocumentReferences._Fields.CHECKSUM)) { + return ""; + } + + if (!actualChecsum.isSet(ExternalDocumentReferences._Fields.CHECKSUM)) { + actualChecsum.checksum = new CheckSum(); + actualChecsum.checksum.algorithm = NOT_SET; + actualChecsum.checksum.checksumValue = NOT_SET; + } + + if (!deletionsChecsum.isSet(ExternalDocumentReferences._Fields.CHECKSUM)) { + deletionsChecsum.checksum = new CheckSum(); + deletionsChecsum.checksum.algorithm = NOT_SET; + deletionsChecsum.checksum.checksumValue = NOT_SET; + } + + if (!additionsChecsum.isSet(ExternalDocumentReferences._Fields.CHECKSUM)) { + additionsChecsum.checksum = new CheckSum(); + additionsChecsum.checksum.algorithm = NOT_SET; + additionsChecsum.checksum.checksumValue = NOT_SET; + } + + if (actualChecsum.checksum.algorithm.equals(additionsChecsum.checksum.algorithm) + && actualChecsum.checksum.checksumValue.equals(additionsChecsum.checksum.checksumValue)) { + return ""; + } + + String display = " CheckSum:
    • algorithm: " + + StringEscapeUtils.escapeXml(actualChecsum.checksum.algorithm) + "
    • checksumValue: " + + StringEscapeUtils.escapeXml(actualChecsum.checksum.checksumValue) + "
  • algorithm: " + + StringEscapeUtils.escapeXml(deletionsChecsum.checksum.algorithm) + "
  • checksumValue: " + + StringEscapeUtils.escapeXml(deletionsChecsum.checksum.checksumValue) + "
  • algorithm: " + + StringEscapeUtils.escapeXml(additionsChecsum.checksum.algorithm) + "
  • checksumValue: " + + StringEscapeUtils.escapeXml(additionsChecsum.checksum.checksumValue) + "
  • "; + return display; + } + +} diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplayPackageInfoChanges.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplayPackageInfoChanges.java new file mode 100644 index 0000000000..fc563e8827 --- /dev/null +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplayPackageInfoChanges.java @@ -0,0 +1,360 @@ +/* + * 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.portal.tags; + +import com.google.common.base.Strings; +import com.liferay.portal.kernel.language.LanguageUtil; +import com.liferay.portal.kernel.util.ResourceBundleUtil; + +import org.eclipse.sw360.datahandler.thrift.spdx.annotations.Annotations; +import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.*; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.ExternalReference; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageVerificationCode; +import org.apache.thrift.meta_data.FieldMetaData; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.ResourceBundle; +import java.util.Set; + +import static org.eclipse.sw360.portal.tags.TagUtils.*; + +public class DisplayPackageInfoChanges extends UserAwareTag { + private PackageInformation actual; + private PackageInformation additions; + private PackageInformation deletions; + private String tableClasses = ""; + private String idPrefix = ""; + + public void setActual(PackageInformation actual) { + this.actual = actual; + } + + public void setAdditions(PackageInformation additions) { + this.additions = additions; + } + + public void setDeletions(PackageInformation deletions) { + this.deletions = deletions; + } + + public void setTableClasses(String tableClasses) { + this.tableClasses = tableClasses; + } + + public void setIdPrefix(String idPrefix) { + this.idPrefix = idPrefix; + } + + public int doStartTag() throws JspException { + + JspWriter jspWriter = pageContext.getOut(); + + StringBuilder display = new StringBuilder(); + + if (additions == null || deletions == null) { + return SKIP_BODY; + } + + try { + for (PackageInformation._Fields field : PackageInformation._Fields.values()) { + switch (field) { + // ignored Fields + case ID: + case REVISION: + case TYPE: + case CREATED_BY: + case PERMISSIONS: + case DOCUMENT_STATE: + case PACKAGE_VERIFICATION_CODE: + case ANNOTATIONS: + case CHECKSUMS: + case EXTERNAL_REFS: + break; + default: + FieldMetaData fieldMetaData = PackageInformation.metaDataMap.get(field); + displaySimpleFieldOrSet(display, actual, additions, deletions, field, fieldMetaData, "", false); + } + } + + String renderString = display.toString(); + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), + getClass()); + + if (Strings.isNullOrEmpty(renderString)) { + renderString = "
    " + + LanguageUtil.get(resourceBundle, "no.changes.in.basic.fields") + "
    "; + } else { + renderString = String.format("", tableClasses, idPrefix) + + "" + + String.format("", + LanguageUtil.get(resourceBundle, "field.name"), + LanguageUtil.get(resourceBundle, "current.value"), + LanguageUtil.get(resourceBundle, "former.value"), + LanguageUtil.get(resourceBundle, "suggested.value")) + + renderString + "
    " + LanguageUtil.get(resourceBundle, "changes.for.basic.fields") + + "
    %s%s%s%s
    "; + } + String packageVerificationCodeRenderString = renderPackageVerificationCode(); + String annotaionsRenderString = renderAnnotaions(); + String checkSumRenderString = renderCheckSum(); + String externalReferenceRenderString = renderExternalReference(); + jspWriter.print(renderString + packageVerificationCodeRenderString.toString() + checkSumRenderString.toString() + externalReferenceRenderString.toString() + annotaionsRenderString.toString()); + } catch (Exception e) { + throw new JspException(e); + } + return SKIP_BODY; + } + + private boolean ensureSomethingTodoAndNoNull(PackageInformation._Fields field) { + if (!deletions.isSet(field) && !additions.isSet(field)) { + return false; + } + + if (field == PackageInformation._Fields.CHECKSUMS) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } else if (field == PackageInformation._Fields.EXTERNAL_REFS) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } else if (field == PackageInformation._Fields.ANNOTATIONS) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } else if (field == PackageInformation._Fields.PACKAGE_VERIFICATION_CODE) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } + + return true; + } + + private String renderCheckSum() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(PackageInformation._Fields.CHECKSUMS)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(PackageInformation._Fields.CHECKSUMS)) { + actual.checksums = new HashSet<>(); + } + + Set additionsCheckSums = additions.getChecksums(); + Set deletionsCheckSums = deletions.getChecksums(); + Set currentCheckSums = actual.getChecksums(); + int changeSize = 0; + if (additionsCheckSums.size() > deletionsCheckSums.size()) { + changeSize = additionsCheckSums.size() + currentCheckSums.size() - deletionsCheckSums.size(); + } else { + changeSize = currentCheckSums.size(); + } + + for (int i = 0; i < changeSize; i++) { + CheckSum checkSumDeletions = getChecksumsByIndex(deletions, i); + CheckSum checkSumAdditions = getChecksumsByIndex(additions, i); + CheckSum checkSum = getChecksumsByIndex(actual, i); + + for (CheckSum._Fields field : CheckSum._Fields.values()) { + FieldMetaData fieldMetaData = CheckSum.metaDataMap.get(field); + displaySimpleFieldOrSet( + display, + checkSum, + checkSumAdditions, + checkSumDeletions, + field, fieldMetaData, "", false); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.checksum")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private CheckSum getChecksumsByIndex(PackageInformation packageInfo, int index) { + CheckSum checksum; + Iterator checksumIterator = packageInfo.getChecksumsIterator(); + while (checksumIterator.hasNext()) { + checksum = checksumIterator.next(); + if (checksum.getIndex() == index) { + checksum.setIndex(0); // Set 0 to not show Index when add or delete + return checksum; + } + } + return new CheckSum(); + } + + private String renderAnnotaions() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(PackageInformation._Fields.ANNOTATIONS)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(PackageInformation._Fields.ANNOTATIONS)) { + actual.annotations = new HashSet<>(); + } + + Set additionsAnnotations = additions.getAnnotations(); + Set deletionsAnnotations = deletions.getAnnotations(); + Set currentAnnotations = actual.getAnnotations(); + int changeSize = 0; + if (additionsAnnotations.size() > deletionsAnnotations.size()) { + changeSize = additionsAnnotations.size() + currentAnnotations.size() - deletionsAnnotations.size(); + } else { + changeSize = currentAnnotations.size(); + } + + for (int i = 0; i < changeSize; i++) { + Annotations annotationDeletions = getAnnotationsByIndex(deletions, i); + Annotations annotationAdditions = getAnnotationsByIndex(additions, i); + Annotations annotation = getAnnotationsByIndex(actual, i); + + for (Annotations._Fields field : Annotations._Fields.values()) { + FieldMetaData fieldMetaData = Annotations.metaDataMap.get(field); + displaySimpleFieldOrSet( + display, + annotation, + annotationAdditions, + annotationDeletions, + field, fieldMetaData, "", false); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.annotaions.information")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private Annotations getAnnotationsByIndex(PackageInformation packageInfo, int index) { + Annotations annotations; + Iterator annotationsIterator = packageInfo.getAnnotationsIterator(); + while (annotationsIterator.hasNext()) { + annotations = annotationsIterator.next(); + if (annotations.getIndex() == index) { + annotations.setIndex(0); // Set 0 to not show Index when add or delete + return annotations; + } + } + return new Annotations(); + } + + private String renderExternalReference() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(PackageInformation._Fields.EXTERNAL_REFS)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(PackageInformation._Fields.EXTERNAL_REFS)) { + actual.externalRefs = new HashSet<>(); + } + + Set additionsExternalReferences = additions.getExternalRefs(); + Set deletionsExternalReferences = deletions.getExternalRefs(); + Set currentExternalReferences = actual.getExternalRefs(); + int changeSize = 0; + if (additionsExternalReferences.size() > deletionsExternalReferences.size()) { + changeSize = additionsExternalReferences.size() + currentExternalReferences.size() - deletionsExternalReferences.size(); + } else { + changeSize = currentExternalReferences.size(); + } + + for (int i = 0; i < changeSize; i++) { + ExternalReference externalRefDeletions = getExternalReferenceByIndex(deletions, i); + ExternalReference externalRefAdditions = getExternalReferenceByIndex(additions, i); + ExternalReference externalRef = getExternalReferenceByIndex(actual, i); + + for (ExternalReference._Fields field : ExternalReference._Fields.values()) { + FieldMetaData fieldMetaData = ExternalReference.metaDataMap.get(field); + displaySimpleFieldOrSet( + display, + externalRef, + externalRefAdditions, + externalRefDeletions, + field, fieldMetaData, "", false); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.external.references")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private ExternalReference getExternalReferenceByIndex(PackageInformation packageInfo, int index) { + ExternalReference externalReference; + Iterator externalReferenceIterator = packageInfo.getExternalRefsIterator(); + while (externalReferenceIterator.hasNext()) { + externalReference = externalReferenceIterator.next(); + if (externalReference.getIndex() == index) { + externalReference.setIndex(0); // Set 0 to not show Index when add or delete + return externalReference; + } + } + return new ExternalReference(); + } + + private String renderPackageVerificationCode() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(PackageInformation._Fields.PACKAGE_VERIFICATION_CODE)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(PackageInformation._Fields.PACKAGE_VERIFICATION_CODE)) { + actual.packageVerificationCode = new PackageVerificationCode(); + } + + for (PackageVerificationCode._Fields field : PackageVerificationCode._Fields.values()) { + FieldMetaData fieldMetaData = PackageVerificationCode.metaDataMap.get(field); + displaySimpleFieldOrSet( + display, + actual.getPackageVerificationCode(), + additions.getPackageVerificationCode(), + deletions.getPackageVerificationCode(), + field, fieldMetaData, "", false); + } + + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.package.verification.code")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } +} \ No newline at end of file diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplaySPDXDocumentChanges.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplaySPDXDocumentChanges.java new file mode 100644 index 0000000000..64ea3d700a --- /dev/null +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/DisplaySPDXDocumentChanges.java @@ -0,0 +1,476 @@ +/* + * 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 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.portal.tags; + +import com.google.common.base.Strings; +import org.apache.commons.lang.StringEscapeUtils; +import com.liferay.portal.kernel.language.LanguageUtil; +import com.liferay.portal.kernel.util.ResourceBundleUtil; + +import org.eclipse.sw360.datahandler.thrift.spdx.annotations.Annotations; +import org.eclipse.sw360.datahandler.thrift.spdx.otherlicensinginformationdetected.OtherLicensingInformationDetected; +import org.eclipse.sw360.datahandler.thrift.spdx.relationshipsbetweenspdxelements.RelationshipsBetweenSPDXElements; +import org.eclipse.sw360.datahandler.thrift.spdx.snippetinformation.SnippetInformation; +import org.eclipse.sw360.datahandler.thrift.spdx.snippetinformation.SnippetRange; +import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.*; +import org.apache.thrift.meta_data.FieldMetaData; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.ResourceBundle; +import java.util.Set; + +import static org.eclipse.sw360.portal.tags.TagUtils.*; + +public class DisplaySPDXDocumentChanges extends UserAwareTag { + private SPDXDocument actual; + private SPDXDocument additions; + private SPDXDocument deletions; + private String tableClasses = ""; + private String idPrefix = ""; + + public void setActual(SPDXDocument actual) { + this.actual = actual; + } + + public void setAdditions(SPDXDocument additions) { + this.additions = additions; + } + + public void setDeletions(SPDXDocument deletions) { + this.deletions = deletions; + } + + public void setTableClasses(String tableClasses) { + this.tableClasses = tableClasses; + } + + public void setIdPrefix(String idPrefix) { + this.idPrefix = idPrefix; + } + + public int doStartTag() throws JspException { + + JspWriter jspWriter = pageContext.getOut(); + + StringBuilder display = new StringBuilder(); + + if (additions == null || deletions == null) { + return SKIP_BODY; + } + + try { + for (SPDXDocument._Fields field : SPDXDocument._Fields.values()) { + switch (field) { + // ignored Fields + case ID: + case REVISION: + case TYPE: + case CREATED_BY: + case PERMISSIONS: + case DOCUMENT_STATE: + case OTHER_LICENSING_INFORMATION_DETECTEDS: + case SNIPPETS: + case ANNOTATIONS: + case RELATIONSHIPS: + break; + default: + FieldMetaData fieldMetaData = SPDXDocument.metaDataMap.get(field); + displaySimpleFieldOrSet(display, actual, additions, deletions, field, fieldMetaData, "", false); + } + } + + String renderString = display.toString(); + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), + getClass()); + + if (Strings.isNullOrEmpty(renderString)) { + renderString = "
    " + + LanguageUtil.get(resourceBundle, "no.changes.in.basic.fields") + "
    "; + } else { + renderString = String.format("", tableClasses, idPrefix) + + "" + + String.format("", + LanguageUtil.get(resourceBundle, "field.name"), + LanguageUtil.get(resourceBundle, "current.value"), + LanguageUtil.get(resourceBundle, "former.value"), + LanguageUtil.get(resourceBundle, "suggested.value")) + + renderString + "
    " + LanguageUtil.get(resourceBundle, "changes.for.basic.fields") + + "
    %s%s%s%s
    "; + } + String snippetRenderString = renderSnippetInformation(); + String relationshipSRenderString = renderRelationshipInformation(); + String annotaionsRenderString = renderAnnotaionsInformation(); + String otherLicensingRenderString = renderOtherLicensingInformationDetected(); + jspWriter.print(renderString + snippetRenderString.toString() + + relationshipSRenderString.toString() + + annotaionsRenderString.toString() + + otherLicensingRenderString.toString()); + } catch (Exception e) { + throw new JspException(e); + } + return SKIP_BODY; + } + + private boolean ensureSomethingTodoAndNoNull(SPDXDocument._Fields field) { + if (!deletions.isSet(field) && !additions.isSet(field)) { + return false; + } + + if (field == SPDXDocument._Fields.SNIPPETS) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } else if (field == SPDXDocument._Fields.RELATIONSHIPS) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } else if (field == SPDXDocument._Fields.ANNOTATIONS) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } else if (field == SPDXDocument._Fields.OTHER_LICENSING_INFORMATION_DETECTEDS) { + if (!deletions.isSet(field)) { + deletions.setFieldValue(field, new HashSet<>()); + } + if (!additions.isSet(field)) { + additions.setFieldValue(field, new HashSet<>()); + } + } + return true; + } + + private String renderSnippetInformation() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(SPDXDocument._Fields.SNIPPETS)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(SPDXDocument._Fields.SNIPPETS)) { + actual.snippets = new HashSet<>(); + } + + Set additionsSnippetInformations = additions.getSnippets(); + Set deletionsSnippetInformations = deletions.getSnippets(); + Set currentSnippetInformations = actual.getSnippets(); + int changeSize = 0; + if (additionsSnippetInformations.size() > deletionsSnippetInformations.size()) { + changeSize = additionsSnippetInformations.size() + currentSnippetInformations.size() - deletionsSnippetInformations.size(); + } else { + changeSize = currentSnippetInformations.size(); + } + + for (int i = 0; i < changeSize; i++) { + SnippetInformation snippetDeletions = getSnippetInformationByIndex(deletions, i); + SnippetInformation snippetAdditions = getSnippetInformationByIndex(additions, i); + SnippetInformation snippet = getSnippetInformationByIndex(actual, i); + + String snippetRangeRendeString = null; + for (SnippetInformation._Fields field : SnippetInformation._Fields.values()) { + FieldMetaData fieldMetaData = SnippetInformation.metaDataMap.get(field); + if (field == SnippetInformation._Fields.SNIPPET_RANGES) { + snippetRangeRendeString = renderSnippetRange(snippet, snippetAdditions, snippetDeletions); + } else { + displaySimpleFieldOrSet( + display, + snippet, + snippetAdditions, + snippetDeletions, + field, fieldMetaData, "", false); + } + } + if (snippetRangeRendeString != null) { + display.append(snippetRangeRendeString); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.snippets.information")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private SnippetInformation getSnippetInformationByIndex(SPDXDocument spdx, int index) { + SnippetInformation snippet; + Iterator snippetsIterator = spdx.getSnippetsIterator(); + while (snippetsIterator.hasNext()) { + snippet = snippetsIterator.next(); + if (snippet.getIndex() == index) { + snippet.setIndex(0); // Set 0 to not show Index when add or delete + return snippet; + } + } + return new SnippetInformation(); + } + + private String renderRelationshipInformation() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(SPDXDocument._Fields.RELATIONSHIPS)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(SPDXDocument._Fields.RELATIONSHIPS)) { + actual.relationships = new HashSet<>(); + } + + Set additionsRelationshipsBetweenSPDXElementss = additions.getRelationships(); + Set deletionsRelationshipsBetweenSPDXElementss = deletions.getRelationships(); + Set currentRelationshipsBetweenSPDXElementss = actual.getRelationships(); + int changeSize = 0; + if (additionsRelationshipsBetweenSPDXElementss.size() > deletionsRelationshipsBetweenSPDXElementss.size()) { + changeSize = additionsRelationshipsBetweenSPDXElementss.size() + currentRelationshipsBetweenSPDXElementss.size() + - deletionsRelationshipsBetweenSPDXElementss.size(); + } else { + changeSize = currentRelationshipsBetweenSPDXElementss.size(); + } + + for (int i = 0; i < changeSize; i++) { + + RelationshipsBetweenSPDXElements relationshipDeletions = getRelationshipByIndex(deletions, i); + RelationshipsBetweenSPDXElements relationshipAdditions = getRelationshipByIndex(additions, i); + RelationshipsBetweenSPDXElements relationship = getRelationshipByIndex(actual, i); + + for (RelationshipsBetweenSPDXElements._Fields field : RelationshipsBetweenSPDXElements._Fields.values()) { + FieldMetaData fieldMetaData = RelationshipsBetweenSPDXElements.metaDataMap.get(field); + displaySimpleFieldOrSet( + display, + relationship, + relationshipAdditions, + relationshipDeletions, + field, fieldMetaData, "", false); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.relationship.information")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private RelationshipsBetweenSPDXElements getRelationshipByIndex(SPDXDocument spdx, int index) { + RelationshipsBetweenSPDXElements relationship; + Iterator relationshipIterator = spdx.getRelationshipsIterator(); + while (relationshipIterator.hasNext()) { + relationship = relationshipIterator.next(); + if (relationship.getIndex() == index) { + return relationship; // Set 0 to not show Index when add or delete + } + } + return new RelationshipsBetweenSPDXElements(); + } + + private String renderAnnotaionsInformation() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(SPDXDocument._Fields.ANNOTATIONS)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(SPDXDocument._Fields.ANNOTATIONS)) { + actual.annotations = new HashSet<>(); + } + + Set additionsAnnotations = additions.getAnnotations(); + Set deletionsAnnotations = deletions.getAnnotations(); + Set currentAnnotations = actual.getAnnotations(); + int changeSize = 0; + if (additionsAnnotations.size() > deletionsAnnotations.size()) { + changeSize = additionsAnnotations.size() + currentAnnotations.size() - deletionsAnnotations.size(); + } else { + changeSize = currentAnnotations.size(); + } + + for (int i = 0; i < changeSize; i++) { + Annotations annotationDeletions = getAnnotationsByIndex(deletions, i); + Annotations annotationAdditions = getAnnotationsByIndex(additions, i); + Annotations annotation = getAnnotationsByIndex(actual, i); + + for (Annotations._Fields field : Annotations._Fields.values()) { + FieldMetaData fieldMetaData = Annotations.metaDataMap.get(field); + displaySimpleFieldOrSet( + display, + annotation, + annotationAdditions, + annotationDeletions, + field, fieldMetaData, "", false); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.annotaions.information")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private Annotations getAnnotationsByIndex(SPDXDocument spdx, int index) { + Annotations annotations; + Iterator annotationsIterator = spdx.getAnnotationsIterator(); + while (annotationsIterator.hasNext()) { + annotations = annotationsIterator.next(); + if (annotations.getIndex() == index) { + annotations.setIndex(0); // Set 0 to not show Index when add or delete + return annotations; + } + } + return new Annotations(); + } + + private String renderOtherLicensingInformationDetected() { + HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); + ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass()); + if (!ensureSomethingTodoAndNoNull(SPDXDocument._Fields.OTHER_LICENSING_INFORMATION_DETECTEDS)) { + return ""; + } + StringBuilder display = new StringBuilder(); + if (! actual.isSet(SPDXDocument._Fields.OTHER_LICENSING_INFORMATION_DETECTEDS)) { + actual.otherLicensingInformationDetecteds = new HashSet<>(); + } + + Set additionsOtherLicensingInformationDetecteds = additions.getOtherLicensingInformationDetecteds(); + Set deletionsOtherLicensingInformationDetecteds = deletions.getOtherLicensingInformationDetecteds(); + Set currentOtherLicensingInformationDetecteds = actual.getOtherLicensingInformationDetecteds(); + int changeSize = 0; + if (additionsOtherLicensingInformationDetecteds.size() > deletionsOtherLicensingInformationDetecteds.size()) { + changeSize = additionsOtherLicensingInformationDetecteds.size() + + currentOtherLicensingInformationDetecteds.size() + - deletionsOtherLicensingInformationDetecteds.size(); + } else { + changeSize = currentOtherLicensingInformationDetecteds.size(); + } + + for (int i = 0; i < changeSize; i++) { + OtherLicensingInformationDetected otherLicensingDeletions = getOtherLicensingByIndex(deletions, i); + OtherLicensingInformationDetected otherLicensingAdditions = getOtherLicensingByIndex(additions, i); + OtherLicensingInformationDetected otherLicensing = getOtherLicensingByIndex(actual, i); + for (OtherLicensingInformationDetected._Fields field : OtherLicensingInformationDetected._Fields.values()) { + FieldMetaData fieldMetaData = OtherLicensingInformationDetected.metaDataMap.get(field); + displaySimpleFieldOrSet( + display, + otherLicensing, + otherLicensingAdditions, + otherLicensingDeletions, + field, fieldMetaData, "", false); + } + } + return "

    "+LanguageUtil.get(resourceBundle,"changes.in.other.licensing.information.detecteds")+ "

    " + + String.format("", tableClasses, idPrefix) + + String.format("", + LanguageUtil.get(resourceBundle,"field.name"), LanguageUtil.get(resourceBundle,"current.value"), + LanguageUtil.get(resourceBundle,"former.value"), LanguageUtil.get(resourceBundle,"suggested.value")) + + display.toString() + "
    %s%s%s%s
    "; + } + + private OtherLicensingInformationDetected getOtherLicensingByIndex(SPDXDocument spdx, int index) { + OtherLicensingInformationDetected otherLicensing; + Iterator otherLicensingIterator = spdx.getOtherLicensingInformationDetectedsIterator(); + while (otherLicensingIterator.hasNext()) { + otherLicensing = otherLicensingIterator.next(); + if (otherLicensing.getIndex() == index) { + otherLicensing.setIndex(0); // Set 0 to not show Index when add or delete + return otherLicensing; + } + } + return new OtherLicensingInformationDetected(); + } + + private String renderSnippetRange(SnippetInformation actual, SnippetInformation additions, SnippetInformation deletions) { + StringBuilder display = new StringBuilder(); + display.append("snippetRange:"); + if (! actual.isSet(SnippetInformation._Fields.SNIPPET_RANGES)) { + actual.snippetRanges = new HashSet<>(); + } + if (! additions.isSet(SnippetInformation._Fields.SNIPPET_RANGES)) { + additions.snippetRanges = new HashSet<>(); + } + if (! deletions.isSet(SnippetInformation._Fields.SNIPPET_RANGES)) { + deletions.snippetRanges = new HashSet<>(); + } + if (additions.snippetRanges.isEmpty() && deletions.snippetRanges.isEmpty()) { + return ""; + } + + Set additionsSnippetRanges = additions.getSnippetRanges(); + Set deletionsSnippetRanges = deletions.getSnippetRanges(); + Set currentSnippetRanges = actual.getSnippetRanges(); + int changeSize = 0; + if (additionsSnippetRanges.size() > deletionsSnippetRanges.size()) { + changeSize = additionsSnippetRanges.size() + currentSnippetRanges.size() - deletionsSnippetRanges.size(); + } else { + changeSize = currentSnippetRanges.size(); + } + + for (int i = 0; i < changeSize; i++) { + SnippetRange snippetRangeDeletions = getSnippetRangeByIndex(deletions, i); + SnippetRange snippetRangeAdditions = getSnippetRangeByIndex(additions, i); + SnippetRange snippetRange = getSnippetRangeByIndex(actual, i); + String renderActual = ""; + String renderDeletions = ""; + String renderAdditions = ""; + + for (SnippetRange._Fields field : SnippetRange._Fields.values()) { + if (snippetRange.getFieldValue(field) == null) { + snippetRange.setFieldValue(field, NOT_SET); + } + if (snippetRangeAdditions.getFieldValue(field) == null) { + snippetRangeAdditions.setFieldValue(field, NOT_SET); + } + if (snippetRangeDeletions.getFieldValue(field) == null) { + snippetRangeDeletions.setFieldValue(field, NOT_SET); + } + if (!snippetRange.equals(snippetRangeAdditions) && !SnippetRange._Fields.INDEX.equals(field)) { + renderActual = renderActual + "
  • " + field.getFieldName() + ": " + StringEscapeUtils.escapeXml(snippetRange.getFieldValue(field).toString()) + "
  • "; + renderDeletions = renderDeletions + "
  • " + field.getFieldName() + ": " + StringEscapeUtils.escapeXml(snippetRangeDeletions.getFieldValue(field).toString()) + "
  • "; + renderAdditions = renderAdditions + "
  • " + field.getFieldName() + ": " + StringEscapeUtils.escapeXml(snippetRangeAdditions.getFieldValue(field).toString()) + "
  • "; + } + } + String renderTotal = "
      " + renderActual + "
      " + + renderDeletions + "
      " + + renderAdditions + "
    "; + if (renderActual != "") { + display.append(renderTotal); + } + } + return display.toString(); + } + + private SnippetRange getSnippetRangeByIndex(SnippetInformation snippet, int index) { + SnippetRange snippetRange; + Iterator snippetRangeIterator = snippet.getSnippetRangesIterator(); + while (snippetRangeIterator.hasNext()) { + snippetRange = snippetRangeIterator.next(); + if (snippetRange.getIndex() == index) { + snippet.setIndex(0); // Set 0 to not show Index when add or delete + return snippetRange; + } + } + return new SnippetRange(); + } + +} \ No newline at end of file diff --git a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/OutTag.java b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/OutTag.java index 53a4205516..485ee10d14 100644 --- a/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/OutTag.java +++ b/frontend/sw360-portlet/src/main/java/org/eclipse/sw360/portal/tags/OutTag.java @@ -30,6 +30,7 @@ public class OutTag extends OutSupport { private boolean jsQuoting = false; private boolean stripNewlines = true; + private boolean hashSet = false; private boolean bare = false; private Integer maxChar = -1; @@ -58,6 +59,11 @@ public int doStartTag() throws JspException { candidate = candidate.replaceAll("[\r\n]+", " "); } + if (hashSet) { + candidate = StringUtils.removeStart(candidate, "["); + candidate = StringUtils.chop(candidate); + } + this.value = candidate; if (!bare && abbreviated) { @@ -95,6 +101,10 @@ public void setStripNewlines(boolean stripNewlines) { this.stripNewlines = stripNewlines; } + public void setHashSet(boolean hashSet) { + this.hashSet = hashSet; + } + public void setBare(boolean bare) { this.bare = bare; } private String prepareTitleAttribute(String value) { 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 309d63fa7e..d22d18ad53 100644 --- a/frontend/sw360-portlet/src/main/resources/META-INF/customTags.tld +++ b/frontend/sw360-portlet/src/main/resources/META-INF/customTags.tld @@ -1257,6 +1257,12 @@ java.lang.Boolean true + + hashSet + false + java.lang.Boolean + true + maxChar false @@ -1432,4 +1438,128 @@ org.eclipse.sw360.datahandler.common.SW360Utils java.lang.String printName(org.eclipse.sw360.datahandler.thrift.users.User) + + + printSPDXDocumentName + org.eclipse.sw360.datahandler.common.SW360Utils + java.lang.String printName(org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument) + + + printDocumentCreationInfoName + org.eclipse.sw360.datahandler.common.SW360Utils + java.lang.String printName(org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation) + + + printPackageInfoName + org.eclipse.sw360.datahandler.common.SW360Utils + java.lang.String printName(org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation) + + + + DisplaySPDXDocumentChanges + org.eclipse.sw360.portal.tags.DisplaySPDXDocumentChanges + empty + + actual + true + org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument + true + + + additions + true + org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument + true + + + deletions + true + org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument + true + + + tableClasses + true + java.lang.String + true + + + idPrefix + true + java.lang.String + true + + + + + DisplayDocumentCreationInfoChanges + org.eclipse.sw360.portal.tags.DisplayDocumentCreationInfoChanges + empty + + actual + true + org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation + true + + + additions + true + org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation + true + + + deletions + true + org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation + true + + + tableClasses + true + java.lang.String + true + + + idPrefix + true + java.lang.String + true + + + + + DisplayPackageInfoChanges + org.eclipse.sw360.portal.tags.DisplayPackageInfoChanges + empty + + actual + true + org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation + true + + + additions + true + org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation + true + + + deletions + true + org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation + true + + + tableClasses + true + java.lang.String + true + + + idPrefix + true + java.lang.String + true + + diff --git a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/detailRelease.jsp b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/detailRelease.jsp index 93b7e01c24..6177b48f1c 100644 --- a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/detailRelease.jsp +++ b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/detailRelease.jsp @@ -36,6 +36,7 @@ + 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 8ace03fcc9..2d2916fce2 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"> diff --git a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/editRelease.jsp b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/editRelease.jsp index d037398c4f..2e21f33966 100644 --- a/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/editRelease.jsp +++ b/frontend/sw360-portlet/src/main/resources/META-INF/resources/html/components/editRelease.jsp @@ -12,6 +12,7 @@ <%@ page import="org.eclipse.sw360.datahandler.thrift.attachments.Attachment" %> <%@ page import="org.eclipse.sw360.datahandler.thrift.components.ComponentType" %> <%@ page import="org.eclipse.sw360.datahandler.thrift.components.Release" %> +<%@ page import="org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument" %> <%@ page import="org.eclipse.sw360.portal.common.PortalConstants" %> <%@ page import="org.eclipse.sw360.datahandler.thrift.users.RequestedAction" %> <%@ page import="org.eclipse.sw360.datahandler.thrift.attachments.CheckStatus" %> @@ -45,20 +46,17 @@ - - + + - - - + @@ -70,14 +68,15 @@ <%@include file="/html/utils/includes/logError.jspf" %> -