From 2cb8204d3c474ce9a7cb6946c43a0beab0ba92a2 Mon Sep 17 00:00:00 2001 From: nwoodward Date: Mon, 8 Jul 2024 12:33:07 -0500 Subject: [PATCH 001/632] updated creative commons licenses version from 3.0 to 4.0 --- .../rest/submit/factory/impl/CCLicenseAddPatchOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CCLicenseAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CCLicenseAddPatchOperation.java index 602ae5e9690b..80624257e6ce 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CCLicenseAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CCLicenseAddPatchOperation.java @@ -26,7 +26,7 @@ * Example: * curl -X PATCH http://${dspace.server.url}/api/submission/workspaceitems/31599 -H "Content-Type: * application/json" -d '[{ "op": "add", "path": "/sections/cclicense/uri", - * "value":"https://creativecommons.org/licenses/by-nc-sa/3.0/us/"}]' + * "value":"https://creativecommons.org/licenses/by-nc-sa/4.0/us/"}]' * */ public class CCLicenseAddPatchOperation extends AddPatchOperation { From 86b28bf927d1614aa3d5b162c736fb834d25495d Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 9 Jul 2024 14:10:05 -0500 Subject: [PATCH 002/632] [maven-release-plugin] prepare for next development iteration --- dspace-api/pom.xml | 2 +- dspace-iiif/pom.xml | 2 +- dspace-oai/pom.xml | 2 +- dspace-rdf/pom.xml | 2 +- dspace-rest/pom.xml | 4 ++-- dspace-server-webapp/pom.xml | 2 +- dspace-services/pom.xml | 2 +- dspace-sword/pom.xml | 2 +- dspace-swordv2/pom.xml | 2 +- dspace/modules/additions/pom.xml | 2 +- dspace/modules/pom.xml | 2 +- dspace/modules/rest/pom.xml | 2 +- dspace/modules/server/pom.xml | 2 +- dspace/pom.xml | 2 +- pom.xml | 32 ++++++++++++++++---------------- 15 files changed, 31 insertions(+), 31 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index a15a21e6bc07..16b151b092e5 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -12,7 +12,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index 58ea58687e05..64dd5106f0af 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index a76a878454e8..28b610e996c1 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -8,7 +8,7 @@ dspace-parent org.dspace - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index 43e637587947..e656a920a1e6 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace-rest/pom.xml b/dspace-rest/pom.xml index 1192f9ed7cdd..d1f3b95aafb0 100644 --- a/dspace-rest/pom.xml +++ b/dspace-rest/pom.xml @@ -3,7 +3,7 @@ org.dspace dspace-rest war - 7.6.2 + 7.6.3-SNAPSHOT DSpace (Deprecated) REST Webapp DSpace RESTful Web Services API. NOTE: this REST API is DEPRECATED. Please consider using the REST API in the dspace-server-webapp instead! @@ -12,7 +12,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index feb8c2af6e4b..e0ec7ef5ed76 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 20110a814459..51c6dea62413 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index d9fd8843a542..1403c779e720 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 2b6c75901e56..470388883126 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -13,7 +13,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace/modules/additions/pom.xml b/dspace/modules/additions/pom.xml index 0a4f43d84bf9..db9343804013 100644 --- a/dspace/modules/additions/pom.xml +++ b/dspace/modules/additions/pom.xml @@ -17,7 +17,7 @@ org.dspace modules - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace/modules/pom.xml b/dspace/modules/pom.xml index d4f47af66a00..3f15bdd01f4f 100644 --- a/dspace/modules/pom.xml +++ b/dspace/modules/pom.xml @@ -11,7 +11,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT ../../pom.xml diff --git a/dspace/modules/rest/pom.xml b/dspace/modules/rest/pom.xml index 3f4e99b482aa..e2e0041cb298 100644 --- a/dspace/modules/rest/pom.xml +++ b/dspace/modules/rest/pom.xml @@ -13,7 +13,7 @@ org.dspace modules - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index d5882c9270c1..5134ffb94733 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -13,7 +13,7 @@ just adding new jar in the classloader modules org.dspace - 7.6.2 + 7.6.3-SNAPSHOT .. diff --git a/dspace/pom.xml b/dspace/pom.xml index cc2968fab99f..b3b474bfbcbc 100644 --- a/dspace/pom.xml +++ b/dspace/pom.xml @@ -16,7 +16,7 @@ org.dspace dspace-parent - 7.6.2 + 7.6.3-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 0670e2cf4832..b662e333225d 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.dspace dspace-parent pom - 7.6.2 + 7.6.3-SNAPSHOT DSpace Parent Project DSpace open source software is a turnkey institutional repository application. @@ -874,14 +874,14 @@ org.dspace dspace-rest - 7.6.2 + 7.6.3-SNAPSHOT jar classes org.dspace dspace-rest - 7.6.2 + 7.6.3-SNAPSHOT war @@ -1032,69 +1032,69 @@ org.dspace dspace-api - 7.6.2 + 7.6.3-SNAPSHOT org.dspace dspace-api test-jar - 7.6.2 + 7.6.3-SNAPSHOT test org.dspace.modules additions - 7.6.2 + 7.6.3-SNAPSHOT org.dspace dspace-sword - 7.6.2 + 7.6.3-SNAPSHOT org.dspace dspace-swordv2 - 7.6.2 + 7.6.3-SNAPSHOT org.dspace dspace-oai - 7.6.2 + 7.6.3-SNAPSHOT org.dspace dspace-services - 7.6.2 + 7.6.3-SNAPSHOT org.dspace dspace-server-webapp test-jar - 7.6.2 + 7.6.3-SNAPSHOT test org.dspace dspace-rdf - 7.6.2 + 7.6.3-SNAPSHOT org.dspace dspace-iiif - 7.6.2 + 7.6.3-SNAPSHOT org.dspace dspace-server-webapp - 7.6.2 + 7.6.3-SNAPSHOT jar classes org.dspace dspace-server-webapp - 7.6.2 + 7.6.3-SNAPSHOT war @@ -1940,7 +1940,7 @@ scm:git:git@github.com:DSpace/DSpace.git scm:git:git@github.com:DSpace/DSpace.git git@github.com:DSpace/DSpace.git - dspace-7.6.2 + dspace-7_x From 17a46a2fb6c2cb63bedc475caf9bf3953d9f76ce Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 10 Jul 2024 12:24:25 -0500 Subject: [PATCH 003/632] Remove unused services & unnecessary cache cleanup. This can result in random failures if these services are not yet loaded by another test. --- .../controller/LinksetRestControllerIT.java | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/signposting/controller/LinksetRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/signposting/controller/LinksetRestControllerIT.java index 6d1d242cad7f..a65357f97bfe 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/signposting/controller/LinksetRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/signposting/controller/LinksetRestControllerIT.java @@ -40,15 +40,12 @@ import org.dspace.content.RelationshipType; import org.dspace.content.WorkspaceItem; import org.dspace.content.authority.Choices; -import org.dspace.content.authority.service.ChoiceAuthorityService; -import org.dspace.content.authority.service.MetadataAuthorityService; import org.dspace.content.service.BitstreamService; import org.dspace.content.service.ItemService; import org.dspace.content.service.RelationshipTypeService; import org.dspace.core.Constants; import org.dspace.eperson.Group; import org.dspace.services.ConfigurationService; -import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.util.SimpleMapConverter; import org.hamcrest.Matchers; import org.junit.Before; @@ -67,12 +64,6 @@ public class LinksetRestControllerIT extends AbstractControllerIntegrationTest { @Autowired private ConfigurationService configurationService; - @Autowired - private MetadataAuthorityService metadataAuthorityService; - - @Autowired - private ChoiceAuthorityService choiceAuthorityService; - @Autowired private ItemService itemService; @@ -735,10 +726,6 @@ public void findTypedLinkForBitstream() throws Exception { .andExpect(jsonPath("$[?(@.href == '" + uiUrl + "/signposting/linksets/" + item.getID() + "/json" + "' && @.rel == 'linkset' " + "&& @.type == 'application/linkset+json')]").exists()); - - DSpaceServicesFactory.getInstance().getConfigurationService().reloadConfig(); - metadataAuthorityService.clearCache(); - choiceAuthorityService.clearCache(); } @Test @@ -780,10 +767,6 @@ public void findTypedLinkForBitstreamWithType() throws Exception { "&& @.type == 'application/linkset+json')]").exists()) .andExpect(jsonPath("$[?(@.href == 'https://schema.org/ScholarlyArticle' " + "&& @.rel == 'type')]").exists()); - - DSpaceServicesFactory.getInstance().getConfigurationService().reloadConfig(); - metadataAuthorityService.clearCache(); - choiceAuthorityService.clearCache(); } @Test @@ -813,10 +796,6 @@ public void findTypedLinkForRestrictedBitstream() throws Exception { getClient().perform(get("/signposting/links/" + bitstream.getID())) .andExpect(status().isUnauthorized()); - - DSpaceServicesFactory.getInstance().getConfigurationService().reloadConfig(); - metadataAuthorityService.clearCache(); - choiceAuthorityService.clearCache(); } @Test @@ -844,10 +823,6 @@ public void findTypedLinkForBitstreamUnderEmbargo() throws Exception { getClient().perform(get("/signposting/links/" + bitstream.getID())) .andExpect(status().isUnauthorized()); - - DSpaceServicesFactory.getInstance().getConfigurationService().reloadConfig(); - metadataAuthorityService.clearCache(); - choiceAuthorityService.clearCache(); } @Test @@ -874,10 +849,6 @@ public void findTypedLinkForBitstreamOfWorkspaceItem() throws Exception { getClient().perform(get("/signposting/links/" + bitstream.getID())) .andExpect(status().isUnauthorized()); - - DSpaceServicesFactory.getInstance().getConfigurationService().reloadConfig(); - metadataAuthorityService.clearCache(); - choiceAuthorityService.clearCache(); } @Test @@ -890,10 +861,6 @@ public void findTypedLinkForUnDiscoverableItem() throws Exception { getClient().perform(get("/signposting/links/" + item.getID())) .andExpect(status().isUnauthorized()); - - DSpaceServicesFactory.getInstance().getConfigurationService().reloadConfig(); - metadataAuthorityService.clearCache(); - choiceAuthorityService.clearCache(); } @Test From 3bb93be79310fc7931359d0cc82bbfa87f9cec85 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 10 Jul 2024 14:21:59 -0500 Subject: [PATCH 004/632] Fix random pagination failures in ManageGroupsFeatureIT by using the "feature" param to filter for the feature we are looking for. If this feature appeared on page 2, then the tests would fail. --- .../authorization/ManageGroupsFeatureIT.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ManageGroupsFeatureIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ManageGroupsFeatureIT.java index a42f219909aa..1997a6147f3a 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ManageGroupsFeatureIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ManageGroupsFeatureIT.java @@ -176,7 +176,7 @@ public void testSubGroupOfAdminGroup() throws Exception { // Verify an ePerson in a subgroup of the site administrators has this feature getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/site/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/site/" + siteService.findSite(context).getID() + "&feature=canManageGroups")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='canManageGroups')]") @@ -285,7 +285,7 @@ public void testSubSubGroupOfAdminGroup() throws Exception { // Verify an ePerson in a sub-subgroup of the site administrators has this feature getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/site/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/site/" + siteService.findSite(context).getID() + "&feature=canManageGroups")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='canManageGroups')]") @@ -502,7 +502,7 @@ public void testSubGroupOfAdminGroupNoCommunityGroupPermission() throws Exceptio // Verify an ePerson in a subgroup of the site administrators has this feature getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/site/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/site/" + siteService.findSite(context).getID() + "&feature=canManageGroups")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='canManageGroups')]") @@ -636,7 +636,7 @@ public void testSubSubGroupOfAdminGroupNoCommunityGroupPermission() throws Excep // Verify an ePerson in a sub-subgroup of the site administrators has this feature getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/site/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/site/" + siteService.findSite(context).getID() + "&feature=canManageGroups")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='canManageGroups')]") @@ -897,7 +897,7 @@ public void testSubGroupOfAdminGroupNoCollectionGroupPermission() throws Excepti // Verify an ePerson in a subgroup of the site administrators has this feature getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/site/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/site/" + siteService.findSite(context).getID() + "&feature=canManageGroups")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='canManageGroups')]") @@ -1051,7 +1051,7 @@ public void testSubSubGroupOfAdminGroupNoCollectionGroupPermission() throws Exce // Verify an ePerson in a sub-subgroup of the site administrators has this feature getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/site/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/site/" + siteService.findSite(context).getID() + "&feature=canManageGroups")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='canManageGroups')]") @@ -1352,7 +1352,7 @@ public void testSubGroupOfAdminGroupNoComColGroupPermission() throws Exception { // Verify an ePerson in a subgroup of the site administrators has this feature getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/site/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/site/" + siteService.findSite(context).getID() + "&feature=canManageGroups")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='canManageGroups')]") @@ -1526,7 +1526,7 @@ public void testSubSubGroupOfAdminGroupNoComColGroupPermission() throws Exceptio // Verify an ePerson in a sub-subgroup of the site administrators has this feature getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/site/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/site/" + siteService.findSite(context).getID() + "&feature=canManageGroups")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='canManageGroups')]") From 22f40943563c404bbf43e8a857ab30c8c4268e88 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 17 Jul 2024 15:33:38 +0200 Subject: [PATCH 005/632] fix FromAsCasing warning (cherry picked from commit 51635d5ff1449c4956f7ad1750a8053de201949b) --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 964b76a2565d..75817980379c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ ARG JDK_VERSION=17 ARG DSPACE_VERSION=latest # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:${DSPACE_VERSION} as build +FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -31,7 +31,7 @@ RUN mvn --no-transfer-progress package ${MAVEN_FLAGS} && \ RUN rm -rf /install/webapps/server/ # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} as ant_build +FROM eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src From 6512513c4f3102bdd3b5b52826c1938f14da7d11 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 17 Jul 2024 15:34:52 +0200 Subject: [PATCH 006/632] fix FromAsCasing warning (cherry picked from commit f40e0aaf4eb13fdef1070bd35867fae08a2dfd61) --- Dockerfile.cli | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.cli b/Dockerfile.cli index 7dd35c9651d9..5254d1eb4d69 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -9,7 +9,7 @@ ARG JDK_VERSION=17 ARG DSPACE_VERSION=latest # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:${DSPACE_VERSION} as build +FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -25,7 +25,7 @@ RUN mvn --no-transfer-progress package && \ mvn clean # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} as ant_build +FROM eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src From 4d014778823ef5c835f7a66df0c9d1a8c688d073 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 17 Jul 2024 15:35:21 +0200 Subject: [PATCH 007/632] fix FromAsCasing warning (cherry picked from commit ac43ec48edc408d3a08ea47bb0c9572bf23e39d4) --- Dockerfile.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.test b/Dockerfile.test index cdfd5e83af5f..f3acef00e825 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -11,7 +11,7 @@ ARG JDK_VERSION=17 ARG DSPACE_VERSION=latest # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:${DSPACE_VERSION} as build +FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -30,7 +30,7 @@ RUN mvn --no-transfer-progress package && \ RUN rm -rf /install/webapps/server/ # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} as ant_build +FROM eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src From ff280bef24ce7cca88dcbb0d426b35763a5bd680 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 17 Jul 2024 15:35:54 +0200 Subject: [PATCH 008/632] fix FromAsCasing warning (cherry picked from commit bed23969199549444d65b43f21315a33f9dd4cab) --- Dockerfile.dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.dependencies b/Dockerfile.dependencies index 2ca4d3040e98..f3bf1f833205 100644 --- a/Dockerfile.dependencies +++ b/Dockerfile.dependencies @@ -7,7 +7,7 @@ ARG JDK_VERSION=17 # Step 1 - Run Maven Build -FROM maven:3-eclipse-temurin-${JDK_VERSION} as build +FROM maven:3-eclipse-temurin-${JDK_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # Create the 'dspace' user account & home directory From 83f3ea4d052859994f66b881e4bd692dd552e576 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 17 Jul 2024 15:33:38 +0200 Subject: [PATCH 009/632] fix FromAsCasing warning --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index ee48dec5083c..9d89710fe11c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ ARG JDK_VERSION=11 # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:dspace-7_x as build +FROM dspace/dspace-dependencies:dspace-7_x AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -28,7 +28,7 @@ RUN mvn --no-transfer-progress package ${MAVEN_FLAGS} && \ mvn clean # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} as ant_build +FROM eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src From f340dfadbec9143009fbb670296c500e05ee00e9 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 17 Jul 2024 15:34:52 +0200 Subject: [PATCH 010/632] fix FromAsCasing warning --- Dockerfile.cli | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.cli b/Dockerfile.cli index 53040a2fad89..8a69b32e2dc6 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -8,7 +8,7 @@ ARG JDK_VERSION=11 # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:dspace-7_x as build +FROM dspace/dspace-dependencies:dspace-7_x AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -24,7 +24,7 @@ RUN mvn --no-transfer-progress package && \ mvn clean # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} as ant_build +FROM eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src From 9b6b7ded97d542f034f95159ce402ecb527a2e7a Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 17 Jul 2024 15:35:21 +0200 Subject: [PATCH 011/632] fix FromAsCasing warning --- Dockerfile.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.test b/Dockerfile.test index f6f8c1a290f9..031394ad256c 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -10,7 +10,7 @@ ARG JDK_VERSION=11 # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:dspace-7_x as build +FROM dspace/dspace-dependencies:dspace-7_x AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -27,7 +27,7 @@ RUN mvn --no-transfer-progress package -Pdspace-rest && \ mvn clean # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} as ant_build +FROM eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src From e4209d5d0b6ac0a301ccf080136e05005e68af11 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 17 Jul 2024 15:35:54 +0200 Subject: [PATCH 012/632] fix FromAsCasing warning --- Dockerfile.dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.dependencies b/Dockerfile.dependencies index 1400b356d418..123206ea5887 100644 --- a/Dockerfile.dependencies +++ b/Dockerfile.dependencies @@ -7,7 +7,7 @@ ARG JDK_VERSION=11 # Step 1 - Run Maven Build -FROM maven:3-eclipse-temurin-${JDK_VERSION} as build +FROM maven:3-eclipse-temurin-${JDK_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # Create the 'dspace' user account & home directory From 03cff072c30888979e89a8c2f8adc4900f269686 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 22 Jul 2024 15:08:59 +0200 Subject: [PATCH 013/632] 116542: fix issues with CSV importing and the Any language being set on metadata values --- .../org/dspace/administer/StructBuilder.java | 2 +- .../org/dspace/app/bulkedit/DSpaceCSV.java | 18 ++++++ .../java/org/dspace/content/Collection.java | 2 +- .../org/dspace/content/MetadataValue.java | 4 ++ .../dspace/app/bulkedit/MetadataImportIT.java | 27 +++++++- .../builder/AbstractDSpaceObjectBuilder.java | 3 +- .../dspace/content/ItemComparatorTest.java | 64 +++++++++---------- .../java/org/dspace/content/ItemTest.java | 38 +++++------ .../content/dao/RelationshipDAOImplTest.java | 4 +- .../dao/RelationshipTypeDAOImplTest.java | 4 +- .../org/dspace/app/rest/PatchMetadataIT.java | 2 +- .../rest/RelationshipRestRepositoryIT.java | 26 ++++---- 12 files changed, 120 insertions(+), 74 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java b/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java index 13a1b3b5bbf8..8bbcfe0ff753 100644 --- a/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java +++ b/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java @@ -802,7 +802,7 @@ private static Element[] handleCollections(Context context, // default the short description to the empty string collectionService.setMetadataSingleValue(context, collection, - MD_SHORT_DESCRIPTION, Item.ANY, " "); + MD_SHORT_DESCRIPTION, null, " "); // import the rest of the metadata for (Map.Entry entry : collectionMap.entrySet()) { diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java index cbc052b5573f..3533a2397b3d 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java @@ -188,6 +188,15 @@ public DSpaceCSV(InputStream inputStream, Context c) throws Exception { // Verify that the heading is valid in the metadata registry String[] clean = element.split("\\["); String[] parts = clean[0].split("\\."); + // Check language if present, if it's ANY then throw an exception + if (clean.length > 1 && clean[1].equals(Item.ANY + "]")) { + throw new MetadataImportInvalidHeadingException("Language ANY (*) was found in the heading " + + "of the metadata value to import, " + + "this should never be the case", + MetadataImportInvalidHeadingException.ENTRY, + columnCounter); + + } if (parts.length < 2) { throw new MetadataImportInvalidHeadingException(element, @@ -223,6 +232,15 @@ public DSpaceCSV(InputStream inputStream, Context c) throws Exception { } } + // Verify there isn’t already a header that is the same; if it already exists, + // throw MetadataImportInvalidHeadingException + String header = authorityPrefix + element; + if (headings.contains(header)) { + throw new MetadataImportInvalidHeadingException("Duplicate heading found: " + header, + MetadataImportInvalidHeadingException.ENTRY, + columnCounter); + } + // Store the heading headings.add(authorityPrefix + element); } diff --git a/dspace-api/src/main/java/org/dspace/content/Collection.java b/dspace-api/src/main/java/org/dspace/content/Collection.java index ffec3b45cc87..0036230a8b9d 100644 --- a/dspace-api/src/main/java/org/dspace/content/Collection.java +++ b/dspace-api/src/main/java/org/dspace/content/Collection.java @@ -230,7 +230,7 @@ public String getLicenseCollection() { * @throws SQLException if database error */ public void setLicense(Context context, String license) throws SQLException { - getCollectionService().setMetadataSingleValue(context, this, MD_LICENSE, Item.ANY, license); + getCollectionService().setMetadataSingleValue(context, this, MD_LICENSE, null, license); } /** diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataValue.java b/dspace-api/src/main/java/org/dspace/content/MetadataValue.java index 9ff3cb9ec2af..56ed81ecbac8 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataValue.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataValue.java @@ -20,6 +20,7 @@ import javax.persistence.SequenceGenerator; import javax.persistence.Table; +import org.apache.commons.lang3.StringUtils; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; import org.hibernate.annotations.Type; @@ -142,6 +143,9 @@ public String getLanguage() { * @param language new language */ public void setLanguage(String language) { + if (StringUtils.equals(language, Item.ANY)) { + language = null; + } this.language = language; } diff --git a/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataImportIT.java b/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataImportIT.java index ac5e1e6ae6b9..481aa09e531f 100644 --- a/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataImportIT.java +++ b/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataImportIT.java @@ -75,6 +75,31 @@ public void setUp() throws Exception { context.restoreAuthSystemState(); } + @Test + public void metadataImportTestWithDuplicateHeader() { + String[] csv = {"id,collection,dc.title,dc.title,dc.contributor.author", + "+," + collection.getHandle() + ",\"Test Import 1\",\"Test Import 2\"," + "\"Donald, SmithImported\"," + + "+," + collection.getHandle() + ",\"Test Import 3\",\"Test Import 4\"," + "\"Donald, SmithImported\""}; + // Should throw an exception because of duplicate header + try { + performImportScript(csv); + } catch (Exception e) { + assertTrue(e instanceof MetadataImportInvalidHeadingException); + } + } + + @Test + public void metadataImportTestWithAnyLanguage() { + String[] csv = {"id,collection,dc.title[*],dc.contributor.author", + "+," + collection.getHandle() + ",\"Test Import 1\"," + "\"Donald, SmithImported\""}; + // Should throw an exception because of invalid ANY language (*) in metadata field + try { + performImportScript(csv); + } catch (Exception e) { + assertTrue(e instanceof MetadataImportInvalidHeadingException); + } + } + @Test public void metadataImportTest() throws Exception { String[] csv = {"id,collection,dc.title,dc.contributor.author", @@ -228,7 +253,7 @@ public void metadataImportRemovingValueTest() throws Exception { itemService.getMetadata(item, "dc", "contributor", "author", Item.ANY).get(0).getValue(), "TestAuthorToRemove")); - String[] csv = {"id,collection,dc.title,dc.contributor.author[*]", + String[] csv = {"id,collection,dc.title,dc.contributor.author", item.getID().toString() + "," + personCollection.getHandle() + "," + item.getName() + ","}; performImportScript(csv); item = findItemByName("title"); diff --git a/dspace-api/src/test/java/org/dspace/builder/AbstractDSpaceObjectBuilder.java b/dspace-api/src/test/java/org/dspace/builder/AbstractDSpaceObjectBuilder.java index ff1083d318d9..c6106c3a75e3 100644 --- a/dspace-api/src/test/java/org/dspace/builder/AbstractDSpaceObjectBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/AbstractDSpaceObjectBuilder.java @@ -14,7 +14,6 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; import org.dspace.content.DSpaceObject; -import org.dspace.content.Item; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Constants; import org.dspace.core.Context; @@ -103,7 +102,7 @@ protected > B setMetadataSingleValue(fi final String qualifier, final String value) { try { - getService().setMetadataSingleValue(context, dso, schema, element, qualifier, Item.ANY, value); + getService().setMetadataSingleValue(context, dso, schema, element, qualifier, null, value); } catch (Exception e) { return handleException(e); } diff --git a/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java b/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java index 54ff9ce02624..be670d9b5097 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java @@ -141,37 +141,37 @@ public void testCompare() throws SQLException { assertTrue("testCompare 0", result == 0); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 1", result >= 1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 2", result <= -1); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); //value in both items ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "2"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "2"); result = ic.compare(one, two); assertTrue("testCompare 3", result <= -1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 4", result == 0); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 5", result >= 1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); @@ -179,60 +179,60 @@ public void testCompare() throws SQLException { //multiple values (min, max) ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "0"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "3"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "0"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "3"); result = ic.compare(one, two); assertTrue("testCompare 3", result <= -1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "0"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "-1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "0"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "-1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 4", result == 0); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "-1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "-1"); result = ic.compare(one, two); assertTrue("testCompare 5", result >= 1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, false); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "3"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "3"); result = ic.compare(one, two); assertTrue("testCompare 3", result <= -1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, false); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "5"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "5"); result = ic.compare(one, two); assertTrue("testCompare 4", result == 0); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, false); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "3"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "4"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "3"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "4"); result = ic.compare(one, two); assertTrue("testCompare 5", result >= 1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); diff --git a/dspace-api/src/test/java/org/dspace/content/ItemTest.java b/dspace-api/src/test/java/org/dspace/content/ItemTest.java index 15e425e23a2a..24d6e515bbdf 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemTest.java @@ -516,11 +516,11 @@ public void testAddMetadata_5args_1() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; String[] values = {"value0", "value1"}; itemService.addMetadata(context, it, schema, element, qualifier, lang, Arrays.asList(values)); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_5args_1 0", dc, notNullValue()); assertTrue("testAddMetadata_5args_1 1", dc.size() == 2); assertThat("testAddMetadata_5args_1 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -550,13 +550,13 @@ public void testAddMetadata_7args_1_authority() String schema = "dc"; String element = "language"; String qualifier = "iso"; - String lang = Item.ANY; + String lang = null; List values = Arrays.asList("en_US", "en"); List authorities = Arrays.asList("accepted", "uncertain"); List confidences = Arrays.asList(0, 0); itemService.addMetadata(context, it, schema, element, qualifier, lang, values, authorities, confidences); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_7args_1 0", dc, notNullValue()); assertTrue("testAddMetadata_7args_1 1", dc.size() == 2); assertThat("testAddMetadata_7args_1 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -587,13 +587,13 @@ public void testAddMetadata_7args_1_noauthority() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; List values = Arrays.asList("value0", "value1"); List authorities = Arrays.asList("auth0", "auth2"); List confidences = Arrays.asList(0, 0); itemService.addMetadata(context, it, schema, element, qualifier, lang, values, authorities, confidences); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_7args_1 0", dc, notNullValue()); assertTrue("testAddMetadata_7args_1 1", dc.size() == 2); assertThat("testAddMetadata_7args_1 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -622,11 +622,11 @@ public void testAddMetadata_5args_2() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; List values = Arrays.asList("value0", "value1"); itemService.addMetadata(context, it, schema, element, qualifier, lang, values); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_5args_2 0", dc, notNullValue()); assertTrue("testAddMetadata_5args_2 1", dc.size() == 2); assertThat("testAddMetadata_5args_2 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -654,13 +654,13 @@ public void testAddMetadata_7args_2_authority() throws SQLException { String schema = "dc"; String element = "language"; String qualifier = "iso"; - String lang = Item.ANY; + String lang = null; String values = "en"; String authorities = "accepted"; int confidences = 0; itemService.addMetadata(context, it, schema, element, qualifier, lang, values, authorities, confidences); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_7args_2 0", dc, notNullValue()); assertTrue("testAddMetadata_7args_2 1", dc.size() == 1); assertThat("testAddMetadata_7args_2 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -683,13 +683,13 @@ public void testAddMetadata_7args_2_noauthority() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "editor"; - String lang = Item.ANY; + String lang = null; String values = "value0"; String authorities = "auth0"; int confidences = 0; itemService.addMetadata(context, it, schema, element, qualifier, lang, values, authorities, confidences); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_7args_2 0", dc, notNullValue()); assertTrue("testAddMetadata_7args_2 1", dc.size() == 1); assertThat("testAddMetadata_7args_2 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -710,13 +710,13 @@ public void testClearMetadata() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; String values = "value0"; itemService.addMetadata(context, it, schema, element, qualifier, lang, values); - itemService.clearMetadata(context, it, schema, element, qualifier, lang); + itemService.clearMetadata(context, it, schema, element, qualifier, Item.ANY); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testClearMetadata 0", dc, notNullValue()); assertTrue("testClearMetadata 1", dc.size() == 0); } @@ -758,11 +758,11 @@ public void testGetCollections() throws Exception { context.turnOffAuthorisationSystem(); Collection collection = collectionService.create(context, owningCommunity); collectionService.setMetadataSingleValue(context, collection, MetadataSchemaEnum.DC.getName(), - "title", null, Item.ANY, "collection B"); + "title", null, null, "collection B"); it.addCollection(collection); collection = collectionService.create(context, owningCommunity); collectionService.setMetadataSingleValue(context, collection, MetadataSchemaEnum.DC.getName(), - "title", null, Item.ANY, "collection A"); + "title", null, null, "collection A"); it.addCollection(collection); context.restoreAuthSystemState(); assertThat("testGetCollections 0", it.getCollections(), notNullValue()); @@ -1602,7 +1602,7 @@ public void testFindByMetadataField() throws Exception { // add new metadata to item context.turnOffAuthorisationSystem(); - itemService.addMetadata(context, it, schema, element, qualifier, Item.ANY, value); + itemService.addMetadata(context, it, schema, element, qualifier, null, value); itemService.update(context, it); context.restoreAuthSystemState(); @@ -1667,7 +1667,7 @@ public void testFindByAuthorityValue() throws Exception { // add new metadata (with authority) to item context.turnOffAuthorisationSystem(); - itemService.addMetadata(context, it, schema, element, qualifier, Item.ANY, value, authority, confidence); + itemService.addMetadata(context, it, schema, element, qualifier, null, value, authority, confidence); itemService.update(context, it); context.restoreAuthSystemState(); diff --git a/dspace-api/src/test/java/org/dspace/content/dao/RelationshipDAOImplTest.java b/dspace-api/src/test/java/org/dspace/content/dao/RelationshipDAOImplTest.java index b6f5da6be065..05e5ba0e1162 100644 --- a/dspace-api/src/test/java/org/dspace/content/dao/RelationshipDAOImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/dao/RelationshipDAOImplTest.java @@ -87,8 +87,8 @@ public void init() { WorkspaceItem workspaceItemTwo = workspaceItemService.create(context, collection, false); itemOne = installItemService.installItem(context, workspaceItem); itemTwo = installItemService.installItem(context, workspaceItemTwo); - itemService.addMetadata(context, itemOne, "dspace", "entity", "type", Item.ANY, "Publication"); - itemService.addMetadata(context, itemTwo, "dspace", "entity", "type", Item.ANY, "Person"); + itemService.addMetadata(context, itemOne, "dspace", "entity", "type", null, "Publication"); + itemService.addMetadata(context, itemTwo, "dspace", "entity", "type", null, "Person"); itemService.update(context, itemOne); itemService.update(context, itemTwo); entityTypeOne = entityTypeService.create(context, "Person"); diff --git a/dspace-api/src/test/java/org/dspace/content/dao/RelationshipTypeDAOImplTest.java b/dspace-api/src/test/java/org/dspace/content/dao/RelationshipTypeDAOImplTest.java index 3fff6fec4762..4d405c6a27e7 100644 --- a/dspace-api/src/test/java/org/dspace/content/dao/RelationshipTypeDAOImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/dao/RelationshipTypeDAOImplTest.java @@ -82,8 +82,8 @@ public void init() { WorkspaceItem workspaceItemTwo = workspaceItemService.create(context, collection, false); itemOne = installItemService.installItem(context, workspaceItem); itemTwo = installItemService.installItem(context, workspaceItemTwo); - itemService.addMetadata(context, itemOne, "dspace", "entity", "type", Item.ANY, "Publication"); - itemService.addMetadata(context, itemTwo, "dspace", "entity", "type", Item.ANY, "Person"); + itemService.addMetadata(context, itemOne, "dspace", "entity", "type", null, "Publication"); + itemService.addMetadata(context, itemTwo, "dspace", "entity", "type", null, "Person"); itemService.update(context, itemOne); itemService.update(context, itemTwo); entityTypeOne = entityTypeService.create(context, "Person"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java index b78436f1fb38..f3ccfe9fc10e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java @@ -247,7 +247,7 @@ private void initSimplePublicationItem() throws Exception { for (String author : authorsOriginalOrder) { itemService.addMetadata( - context, publicationItem, "dc", "contributor", "author", Item.ANY, author + context, publicationItem, "dc", "contributor", "author", null, author ); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java index d8e53c770c70..264fb0d246ad 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java @@ -819,7 +819,7 @@ public void addRelationshipsAndMetadataToValidatePlaceTest() throws Exception { // Make sure we grab the latest instance of the Item from the database publication1 = itemService.find(context, publication1.getID()); // Add a plain text dc.contributor.author value - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text"); itemService.update(context, publication1); List list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -885,7 +885,7 @@ public void addRelationshipsAndMetadataToValidatePlaceTest() throws Exception { // Ensure we have the latest instance of the Item from the database publication1 = itemService.find(context, publication1.getID()); // Add a fourth dc.contributor.author mdv - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text two"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text two"); itemService.update(context, publication1); context.restoreAuthSystemState(); @@ -954,7 +954,7 @@ public void addRelationshipsAndMetadataToValidatePlaceTest() throws Exception { context.turnOffAuthorisationSystem(); // The following additions of Metadata will perform the same sequence of logic and tests as described above publication1 = itemService.find(context, publication1.getID()); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text three"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text three"); itemService.update(context, publication1); context.restoreAuthSystemState(); @@ -984,10 +984,10 @@ public void addRelationshipsAndMetadataToValidatePlaceTest() throws Exception { context.turnOffAuthorisationSystem(); publication1 = itemService.find(context, publication1.getID()); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text four"); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text five"); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text six"); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text seven"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text four"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text five"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text six"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text seven"); itemService.update(context, publication1); context.restoreAuthSystemState(); @@ -1115,7 +1115,7 @@ public void deleteMetadataValueAndValidatePlace() throws Exception { publication1 = itemService.find(context, publication1.getID()); // Add a plain text metadatavalue to the publication // After this addition, the list of authors should like like "Donald Smith", "plain text" - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text"); itemService.update(context, publication1); context.restoreAuthSystemState(); List list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1158,7 +1158,7 @@ public void deleteMetadataValueAndValidatePlace() throws Exception { // Get the publication from the DB again to ensure that we have the latest object publication1 = itemService.find(context, publication1.getID()); // Add a fourth metadata value to the publication - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text two"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text two"); itemService.update(context, publication1); context.restoreAuthSystemState(); list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1196,7 +1196,7 @@ public void deleteMetadataValueAndValidatePlace() throws Exception { context.turnOffAuthorisationSystem(); publication1 = itemService.find(context, publication1.getID()); // Create another plain text metadata value on the publication - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text three"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text three"); itemService.update(context, publication1); context.restoreAuthSystemState(); list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1324,7 +1324,7 @@ public void deleteRelationshipsAndValidatePlace() throws Exception { publication1 = itemService.find(context, publication1.getID()); // Add a plain text metadatavalue to the publication // After this addition, the list of authors should like like "Donald Smith", "plain text" - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text"); itemService.update(context, publication1); context.restoreAuthSystemState(); List list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1368,7 +1368,7 @@ public void deleteRelationshipsAndValidatePlace() throws Exception { // Get the publication from the DB again to ensure that we have the latest object publication1 = itemService.find(context, publication1.getID()); // Add a fourth metadata value to the publication - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text two"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text two"); itemService.update(context, publication1); context.restoreAuthSystemState(); list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1406,7 +1406,7 @@ public void deleteRelationshipsAndValidatePlace() throws Exception { context.turnOffAuthorisationSystem(); publication1 = itemService.find(context, publication1.getID()); // Create another plain text metadata value on the publication - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text three"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text three"); itemService.update(context, publication1); context.restoreAuthSystemState(); list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); From 7082e3259595dbcbd31f339c53a15c17cd47110b Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 22 Jul 2024 15:18:44 +0200 Subject: [PATCH 014/632] 116542: resolve issues after merge with latest 7-x branch --- .../test/java/org/dspace/content/ItemTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/ItemTest.java b/dspace-api/src/test/java/org/dspace/content/ItemTest.java index 87f42cf42935..00dbf2994d98 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemTest.java @@ -544,7 +544,7 @@ public void testAddMetadata_5args_no_values() throws Exception { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; String[] values = {}; itemService.addMetadata(context, it, schema, element, qualifier, lang, Arrays.asList(values)); fail("IllegalArgumentException expected"); @@ -632,7 +632,7 @@ public void testAddMetadata_7args_no_values() throws Exception { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; List values = new ArrayList(); List authorities = new ArrayList(); List confidences = new ArrayList(); @@ -645,7 +645,7 @@ public void testAddMetadata_list_with_virtual_metadata() throws Exception { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; // Create two fake virtual metadata ("virtual::[relationship-id]") values List values = new ArrayList<>(Arrays.asList("uuid-1", "uuid-2")); List authorities = new ArrayList<>(Arrays.asList(Constants.VIRTUAL_AUTHORITY_PREFIX + "relationship-1", @@ -674,7 +674,7 @@ public void testAddMetadata_list_with_virtual_metadata() throws Exception { assertEquals(1, valuesAdded.size()); // Get metadata and ensure new value is the ONLY ONE for this metadata field - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertNotNull(dc); assertEquals(1, dc.size()); assertEquals(schema, dc.get(0).getMetadataField().getMetadataSchema().getName()); @@ -693,7 +693,7 @@ public void testAddMetadata_5args_2() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; String value = "value0"; itemService.addMetadata(context, it, schema, element, qualifier, lang, value); @@ -772,7 +772,7 @@ public void testAddMetadata_single_virtual_metadata() throws Exception { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; // Create a single fake virtual metadata ("virtual::[relationship-id]") value String value = "uuid-1"; String authority = Constants.VIRTUAL_AUTHORITY_PREFIX + "relationship-1"; @@ -786,7 +786,7 @@ public void testAddMetadata_single_virtual_metadata() throws Exception { assertNull(valuesAdded); // Verify this metadata field does NOT exist on the item - List mv = itemService.getMetadata(it, schema, element, qualifier, lang); + List mv = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertNotNull(mv); assertTrue(mv.isEmpty()); @@ -797,7 +797,7 @@ public void testAddMetadata_single_virtual_metadata() throws Exception { assertNull(valuesAdded); // Verify this metadata field does NOT exist on the item - mv = itemService.getMetadata(it, schema, element, qualifier, lang); + mv = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertNotNull(mv); assertTrue(mv.isEmpty()); } From fff8cc3cb4f05ace42b035b3eb2c3a9b46f3b5f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 14:34:41 +0000 Subject: [PATCH 015/632] Bump dnsjava:dnsjava from 2.1.9 to 3.6.0 in /dspace-api Bumps [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) from 2.1.9 to 3.6.0. - [Release notes](https://github.com/dnsjava/dnsjava/releases) - [Changelog](https://github.com/dnsjava/dnsjava/blob/master/Changelog) - [Commits](https://github.com/dnsjava/dnsjava/compare/v2.1.9...v3.6.0) --- updated-dependencies: - dependency-name: dnsjava:dnsjava dependency-type: direct:production ... Signed-off-by: dependabot[bot] (cherry picked from commit 1775c88919cacf063788e4a6a0b67cdf1ef23fec) --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 16b151b092e5..bdf035179bee 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -629,7 +629,7 @@ dnsjava dnsjava - 2.1.9 + 3.6.0 From f41113e198f49091ceeaa09c2d9369771b6f15bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 14:34:41 +0000 Subject: [PATCH 016/632] Bump dnsjava:dnsjava from 2.1.9 to 3.6.0 in /dspace-api Bumps [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) from 2.1.9 to 3.6.0. - [Release notes](https://github.com/dnsjava/dnsjava/releases) - [Changelog](https://github.com/dnsjava/dnsjava/blob/master/Changelog) - [Commits](https://github.com/dnsjava/dnsjava/compare/v2.1.9...v3.6.0) --- updated-dependencies: - dependency-name: dnsjava:dnsjava dependency-type: direct:production ... Signed-off-by: dependabot[bot] (cherry picked from commit 1775c88919cacf063788e4a6a0b67cdf1ef23fec) --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index d2d2d123c350..dfb3f030ac0e 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -623,7 +623,7 @@ dnsjava dnsjava - 2.1.9 + 3.6.0 From 30b6eddeb66c0e89c951090d8c2b2d6d0f3a31ab Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 23 Jul 2024 12:17:07 +0200 Subject: [PATCH 017/632] Update spider list URLs to satisfy cloudflare redirects Update spider list URLs to satisfy cloudflare redirects Update spider list URLs to satisfy cloudflare redirects (cherry picked from commit d22ea117ca6970fd52b296ac18d3f71878c1a857) --- dspace/config/modules/solr-statistics.cfg | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dspace/config/modules/solr-statistics.cfg b/dspace/config/modules/solr-statistics.cfg index 073850ca232e..632ff5078b48 100644 --- a/dspace/config/modules/solr-statistics.cfg +++ b/dspace/config/modules/solr-statistics.cfg @@ -32,10 +32,10 @@ solr-statistics.configset = statistics solr-statistics.autoCommit = true # URLs to download IP addresses of search engine spiders from -solr-statistics.spiderips.urls = http://iplists.com/google.txt, \ - http://iplists.com/inktomi.txt, \ - http://iplists.com/lycos.txt, \ - http://iplists.com/infoseek.txt, \ - http://iplists.com/altavista.txt, \ - http://iplists.com/excite.txt, \ - http://iplists.com/misc.txt +solr-statistics.spiderips.urls = https://www.iplists.com/google.txt, \ + https://www.iplists.com/inktomi.txt, \ + https://www.iplists.com/lycos.txt, \ + https://www.iplists.com/infoseek.txt, \ + https://www.iplists.com/altavista.txt, \ + https://www.iplists.com/excite.txt, \ + https://www.iplists.com/misc.txt From 0d3f80e5d7ee150c4d840f344eade206334a5f6c Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 23 Jul 2024 12:17:07 +0200 Subject: [PATCH 018/632] Update spider list URLs to satisfy cloudflare redirects Update spider list URLs to satisfy cloudflare redirects Update spider list URLs to satisfy cloudflare redirects (cherry picked from commit d22ea117ca6970fd52b296ac18d3f71878c1a857) --- dspace/config/modules/solr-statistics.cfg | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dspace/config/modules/solr-statistics.cfg b/dspace/config/modules/solr-statistics.cfg index 28273809de70..57c061dac75d 100644 --- a/dspace/config/modules/solr-statistics.cfg +++ b/dspace/config/modules/solr-statistics.cfg @@ -28,10 +28,10 @@ solr-statistics.configset = statistics solr-statistics.autoCommit = true # URLs to download IP addresses of search engine spiders from -solr-statistics.spiderips.urls = http://iplists.com/google.txt, \ - http://iplists.com/inktomi.txt, \ - http://iplists.com/lycos.txt, \ - http://iplists.com/infoseek.txt, \ - http://iplists.com/altavista.txt, \ - http://iplists.com/excite.txt, \ - http://iplists.com/misc.txt +solr-statistics.spiderips.urls = https://www.iplists.com/google.txt, \ + https://www.iplists.com/inktomi.txt, \ + https://www.iplists.com/lycos.txt, \ + https://www.iplists.com/infoseek.txt, \ + https://www.iplists.com/altavista.txt, \ + https://www.iplists.com/excite.txt, \ + https://www.iplists.com/misc.txt From affa4b00ff59cffa69d47de6a3a7d4137008dd40 Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Wed, 24 Jul 2024 19:07:44 +0200 Subject: [PATCH 019/632] [CST-14905] Orcid revoke token feature --- .../org/dspace/orcid/client/OrcidClient.java | 8 + .../dspace/orcid/client/OrcidClientImpl.java | 37 +++++ .../orcid/client/OrcidConfiguration.java | 9 ++ .../impl/OrcidSynchronizationServiceImpl.java | 14 ++ .../ResearcherProfileRestRepositoryIT.java | 146 ++++++++++++++++-- dspace/config/modules/orcid.cfg | 1 + dspace/config/spring/api/orcid-services.xml | 1 + 7 files changed, 200 insertions(+), 16 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java index 99d1920aa53a..d21f61a922f5 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Optional; +import org.dspace.orcid.OrcidToken; import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.orcid.jaxb.model.v3.release.record.Person; @@ -161,4 +162,11 @@ public interface OrcidClient { */ OrcidResponse deleteByPutCode(String accessToken, String orcid, String putCode, String path); + /** + * Revokes the given {@param accessToken} with a POST method. + * @param orcidToken the access token to revoke + * @throws OrcidClientException if some error occurs during the search + */ + void revokeToken(OrcidToken orcidToken); + } diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java index 3e7ca7b21029..1532abe63412 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java @@ -42,6 +42,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicNameValuePair; +import org.dspace.orcid.OrcidToken; import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidEntityType; import org.dspace.orcid.model.OrcidProfileSectionType; @@ -178,6 +179,16 @@ public OrcidResponse deleteByPutCode(String accessToken, String orcid, String pu return execute(buildDeleteUriRequest(accessToken, "/" + orcid + path + "/" + putCode), true); } + @Override + public void revokeToken(OrcidToken orcidToken) { + List params = new ArrayList<>(); + params.add(new BasicNameValuePair("client_id", orcidConfiguration.getClientId())); + params.add(new BasicNameValuePair("client_secret", orcidConfiguration.getClientSecret())); + params.add(new BasicNameValuePair("token", orcidToken.getAccessToken())); + + executeSuccessful(buildPostForRevokeToken(new UrlEncodedFormEntity(params, Charset.defaultCharset()))); + } + @Override public OrcidTokenResponseDTO getReadPublicAccessToken() { return getClientCredentialsAccessToken("/read-public"); @@ -220,6 +231,14 @@ private HttpUriRequest buildPostUriRequest(String accessToken, String relativePa .build(); } + private HttpUriRequest buildPostForRevokeToken(HttpEntity entity) { + return post(orcidConfiguration.getRevokeUrl()) + .addHeader("Accept", "application/json") + .addHeader("Content-Type", "application/x-www-form-urlencoded") + .setEntity(entity) + .build(); + } + private HttpUriRequest buildPutUriRequest(String accessToken, String relativePath, Object object) { return put(orcidConfiguration.getApiUrl() + relativePath.trim()) .addHeader("Content-Type", "application/vnd.orcid+xml") @@ -234,6 +253,24 @@ private HttpUriRequest buildDeleteUriRequest(String accessToken, String relative .build(); } + private void executeSuccessful(HttpUriRequest httpUriRequest) { + try { + HttpClient client = HttpClientBuilder.create().build(); + HttpResponse response = client.execute(httpUriRequest); + + if (isNotSuccessfull(response)) { + throw new OrcidClientException( + getStatusCode(response), + "Operation " + httpUriRequest.getMethod() + " for the resource " + httpUriRequest.getURI() + + " was not successful: " + new String(response.getEntity().getContent().readAllBytes(), + StandardCharsets.UTF_8) + ); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + private T executeAndParseJson(HttpUriRequest httpUriRequest, Class clazz) { HttpClient client = HttpClientBuilder.create().build(); diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java index 550b0215c435..dfa90fcae03a 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java @@ -35,6 +35,8 @@ public final class OrcidConfiguration { private String scopes; + private String revokeUrl; + public String getApiUrl() { return apiUrl; } @@ -111,4 +113,11 @@ public boolean isApiConfigured() { return !StringUtils.isAnyBlank(clientId, clientSecret); } + public String getRevokeUrl() { + return revokeUrl; + } + + public void setRevokeUrl(String revokeUrl) { + this.revokeUrl = revokeUrl; + } } diff --git a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java index 97d832d3de82..a302c58f2c5e 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java @@ -37,6 +37,7 @@ import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; import org.dspace.orcid.OrcidToken; +import org.dspace.orcid.client.OrcidClient; import org.dspace.orcid.model.OrcidEntityType; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.dspace.orcid.service.OrcidSynchronizationService; @@ -47,6 +48,8 @@ import org.dspace.profile.OrcidSynchronizationMode; import org.dspace.profile.service.ResearcherProfileService; import org.dspace.services.ConfigurationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; /** @@ -57,6 +60,7 @@ */ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationService { + private static final Logger log = LoggerFactory.getLogger(OrcidSynchronizationServiceImpl.class); @Autowired private ItemService itemService; @@ -75,6 +79,9 @@ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationServ @Autowired private ResearcherProfileService researcherProfileService; + @Autowired + private OrcidClient orcidClient; + @Override public void linkProfile(Context context, Item profile, OrcidTokenResponseDTO token) throws SQLException { @@ -118,7 +125,14 @@ public void unlinkProfile(Context context, Item profile) throws SQLException { itemService.clearMetadata(context, profile, "dspace", "orcid", "scope", Item.ANY); itemService.clearMetadata(context, profile, "dspace", "orcid", "authenticated", Item.ANY); + OrcidToken profileToken = orcidTokenService.findByProfileItem(context, profile); + if (profileToken == null) { + log.warn("Cannot find any token related to the user profile: {}", profile.getID()); + return; + } + orcidTokenService.deleteByProfileItem(context, profile); + orcidClient.revokeToken(profileToken); updateItem(context, profile); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java index 70009d049fc5..0d46f4268cae 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java @@ -30,7 +30,10 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -44,6 +47,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; import java.sql.SQLException; import java.util.List; import java.util.UUID; @@ -79,11 +83,13 @@ import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.dspace.orcid.service.OrcidQueueService; +import org.dspace.orcid.service.OrcidSynchronizationService; import org.dspace.orcid.service.OrcidTokenService; import org.dspace.services.ConfigurationService; import org.dspace.util.UUIDUtils; import org.junit.After; import org.junit.Test; +import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MvcResult; @@ -114,7 +120,11 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra @Autowired private OrcidClient orcidClient; - private OrcidClient orcidClientMock = mock(OrcidClient.class); + @Mock + private OrcidClient orcidClientMock; + + @Autowired + private OrcidSynchronizationService orcidSynchronizationService; private EPerson user; @@ -158,16 +168,36 @@ public void setUp() throws Exception { context.restoreAuthSystemState(); - researcherProfileAddOrcidOperation.setOrcidClient(orcidClientMock); - + useInstanceForBean(orcidSynchronizationService, orcidClientMock); + useInstanceForBean(researcherProfileAddOrcidOperation, orcidClientMock); } @After public void after() { orcidTokenService.deleteAll(context); - researcherProfileAddOrcidOperation.setOrcidClient(orcidClient); + useInstanceForBean(orcidSynchronizationService, orcidClient); + useInstanceForBean(researcherProfileAddOrcidOperation, orcidClient); + } + + private void useInstanceForBean(B bean, I instance) { + Field[] fields = bean.getClass().getDeclaredFields(); + + for (Field field : fields) { + if (field.getType().isAssignableFrom(instance.getClass())) { + boolean accessible = field.isAccessible(); + try { + field.setAccessible(true); + field.set(bean, instance); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } finally { + field.setAccessible(accessible); + } + } + } } + /** * Verify that the findById endpoint returns the own profile. * @@ -608,30 +638,38 @@ public void testDeleteWithProfileLinkedWithOrcid() throws Exception { .withOrcidAuthenticated("authenticated") .build(); + context.restoreAuthSystemState(); + String id = user.getID().toString(); String authToken = getAuthToken(user.getEmail(), password); + OrcidToken orcidToken = orcidTokenService.findByProfileItem(context, profileItem); - context.restoreAuthSystemState(); - - getClient(authToken).perform(get("/api/eperson/profiles/{id}", id)) + getClient(authToken) + .perform(get("/api/eperson/profiles/{id}", id)) .andExpect(status().isOk()); assertThat(profileItem.getMetadata(), hasItem(with("person.identifier.orcid", "0000-1111-2222-3333"))); assertThat(profileItem.getMetadata(), hasItem(with("dspace.orcid.authenticated", "authenticated"))); - assertThat(getOrcidAccessToken(profileItem), notNullValue()); + assertThat(orcidToken.getAccessToken(), notNullValue()); getClient(authToken).perform(get("/api/eperson/profiles/{id}/item", id)) .andExpect(status().isOk()) .andExpect(jsonPath("$", hasJsonPath("$.metadata", matchMetadataNotEmpty("dspace.object.owner")))); + getClient(authToken).perform(delete("/api/eperson/profiles/{id}", id)) .andExpect(status().isNoContent()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profileItem = context.reloadEntity(profileItem); + orcidToken = orcidTokenService.findByProfileItem(context, profileItem); + assertThat(profileItem.getMetadata(), not(hasItem(with("person.identifier.orcid", "0000-1111-2222-3333")))); assertThat(profileItem.getMetadata(), not(hasItem(with("dspace.orcid.authenticated", "authenticated")))); - assertThat(getOrcidAccessToken(profileItem), nullValue()); + assertThat(orcidToken, nullValue()); } @@ -1850,7 +1888,8 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -1872,6 +1911,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -1880,6 +1922,54 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration assertThat(getOrcidAccessToken(profile), nullValue()); } + @Test + public void testPatchToDisconnectProfileFromOrcidDoesntRevokeOrcidToken() throws Exception { + + configurationService.setProperty("orcid.disconnection.allowed-users", "admin_and_owner"); + + context.turnOffAuthorisationSystem(); + + EPerson ePerson = EPersonBuilder.createEPerson(context) + .withCanLogin(true) + .withOrcid("0000-1111-2222-3333") + .withOrcidScope("/read") + .withOrcidScope("/write") + .withEmail("test@email.it") + .withPassword(password) + .withNameInMetadata("Test", "User") + .build(); + + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + + Item profile = createProfile(ePerson); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); + assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); + + context.restoreAuthSystemState(); + + doThrow(new OrcidClientException(403, "")).when(orcidClientMock).revokeToken(any(OrcidToken.class)); + + getClient(getAuthToken(ePerson.getEmail(), password)) + .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) + .content(getPatchContent(asList(new RemoveOperation("/orcid")))) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isInternalServerError()); + + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + + profile = context.reloadEntity(profile); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); + assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); + } + @Test public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration() throws Exception { @@ -2023,7 +2113,8 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -2034,6 +2125,7 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration context.restoreAuthSystemState(); + getClient(getAuthToken(admin.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) @@ -2045,6 +2137,9 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2111,17 +2206,18 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .withPassword(password) .withNameInMetadata("Test", "User") .build(); - - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); + context.restoreAuthSystemState(); + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); - context.restoreAuthSystemState(); getClient(getAuthToken(ePerson.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) @@ -2134,6 +2230,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2159,7 +2258,8 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -2170,6 +2270,7 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura context.restoreAuthSystemState(); + getClient(getAuthToken(admin.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) @@ -2181,6 +2282,10 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2627,4 +2732,13 @@ private OrcidTokenResponseDTO buildOrcidTokenResponse(String orcid, String acces return token; } + private static OrcidToken matchesToken(OrcidToken orcidToken) { + return argThat( + token -> + token != null && + orcidToken.getAccessToken().equals(token.getAccessToken()) && + orcidToken.getID().equals(token.getID()) + ); + } + } diff --git a/dspace/config/modules/orcid.cfg b/dspace/config/modules/orcid.cfg index cde819677447..93da0a5f4cb9 100644 --- a/dspace/config/modules/orcid.cfg +++ b/dspace/config/modules/orcid.cfg @@ -14,6 +14,7 @@ orcid.disconnection.allowed-users = admin_and_owner # ORCID API (https://github.com/ORCID/ORCID-Source/tree/master/orcid-api-web#endpoints) orcid.domain-url= https://sandbox.orcid.org orcid.authorize-url = ${orcid.domain-url}/oauth/authorize +orcid.revoke-url = ${orcid.domain-url}/oauth/revoke orcid.token-url = ${orcid.domain-url}/oauth/token orcid.api-url = https://api.sandbox.orcid.org/v3.0 orcid.public-url = https://pub.sandbox.orcid.org/v3.0 diff --git a/dspace/config/spring/api/orcid-services.xml b/dspace/config/spring/api/orcid-services.xml index e5fb002c314f..eb31acb29c4d 100644 --- a/dspace/config/spring/api/orcid-services.xml +++ b/dspace/config/spring/api/orcid-services.xml @@ -30,6 +30,7 @@ + From be2434bce12c2a059488716983b9fc9dec8da15e Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Wed, 24 Jul 2024 19:07:44 +0200 Subject: [PATCH 020/632] [CST-14905] Orcid revoke token feature --- .../org/dspace/orcid/client/OrcidClient.java | 8 + .../dspace/orcid/client/OrcidClientImpl.java | 37 +++ .../orcid/client/OrcidConfiguration.java | 9 + .../impl/OrcidSynchronizationServiceImpl.java | 39 +++- .../ResearcherProfileRestRepositoryIT.java | 216 ++++++++++++++++-- dspace/config/modules/orcid.cfg | 1 + dspace/config/spring/api/orcid-services.xml | 1 + 7 files changed, 284 insertions(+), 27 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java index 99d1920aa53a..d21f61a922f5 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Optional; +import org.dspace.orcid.OrcidToken; import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.orcid.jaxb.model.v3.release.record.Person; @@ -161,4 +162,11 @@ public interface OrcidClient { */ OrcidResponse deleteByPutCode(String accessToken, String orcid, String putCode, String path); + /** + * Revokes the given {@param accessToken} with a POST method. + * @param orcidToken the access token to revoke + * @throws OrcidClientException if some error occurs during the search + */ + void revokeToken(OrcidToken orcidToken); + } diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java index 8356167692e3..6c2a1512980c 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java @@ -42,6 +42,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicNameValuePair; +import org.dspace.orcid.OrcidToken; import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidEntityType; import org.dspace.orcid.model.OrcidProfileSectionType; @@ -178,6 +179,16 @@ public OrcidResponse deleteByPutCode(String accessToken, String orcid, String pu return execute(buildDeleteUriRequest(accessToken, "/" + orcid + path + "/" + putCode), true); } + @Override + public void revokeToken(OrcidToken orcidToken) { + List params = new ArrayList<>(); + params.add(new BasicNameValuePair("client_id", orcidConfiguration.getClientId())); + params.add(new BasicNameValuePair("client_secret", orcidConfiguration.getClientSecret())); + params.add(new BasicNameValuePair("token", orcidToken.getAccessToken())); + + executeSuccessful(buildPostForRevokeToken(new UrlEncodedFormEntity(params, Charset.defaultCharset()))); + } + @Override public OrcidTokenResponseDTO getReadPublicAccessToken() { return getClientCredentialsAccessToken("/read-public"); @@ -220,6 +231,14 @@ private HttpUriRequest buildPostUriRequest(String accessToken, String relativePa .build(); } + private HttpUriRequest buildPostForRevokeToken(HttpEntity entity) { + return post(orcidConfiguration.getRevokeUrl()) + .addHeader("Accept", "application/json") + .addHeader("Content-Type", "application/x-www-form-urlencoded") + .setEntity(entity) + .build(); + } + private HttpUriRequest buildPutUriRequest(String accessToken, String relativePath, Object object) { return put(orcidConfiguration.getApiUrl() + relativePath.trim()) .addHeader("Content-Type", "application/vnd.orcid+xml") @@ -234,6 +253,24 @@ private HttpUriRequest buildDeleteUriRequest(String accessToken, String relative .build(); } + private void executeSuccessful(HttpUriRequest httpUriRequest) { + try { + HttpClient client = HttpClientBuilder.create().build(); + HttpResponse response = client.execute(httpUriRequest); + + if (isNotSuccessfull(response)) { + throw new OrcidClientException( + getStatusCode(response), + "Operation " + httpUriRequest.getMethod() + " for the resource " + httpUriRequest.getURI() + + " was not successful: " + new String(response.getEntity().getContent().readAllBytes(), + StandardCharsets.UTF_8) + ); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + private T executeAndParseJson(HttpUriRequest httpUriRequest, Class clazz) { HttpClient client = HttpClientBuilder.create().build(); diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java index 550b0215c435..dfa90fcae03a 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java @@ -35,6 +35,8 @@ public final class OrcidConfiguration { private String scopes; + private String revokeUrl; + public String getApiUrl() { return apiUrl; } @@ -111,4 +113,11 @@ public boolean isApiConfigured() { return !StringUtils.isAnyBlank(clientId, clientSecret); } + public String getRevokeUrl() { + return revokeUrl; + } + + public void setRevokeUrl(String revokeUrl) { + this.revokeUrl = revokeUrl; + } } diff --git a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java index 59e4dea64145..f976864d07f9 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java @@ -37,6 +37,7 @@ import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; import org.dspace.orcid.OrcidToken; +import org.dspace.orcid.client.OrcidClient; import org.dspace.orcid.model.OrcidEntityType; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.dspace.orcid.service.OrcidSynchronizationService; @@ -47,6 +48,8 @@ import org.dspace.profile.OrcidSynchronizationMode; import org.dspace.profile.service.ResearcherProfileService; import org.dspace.services.ConfigurationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; /** @@ -57,6 +60,7 @@ */ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationService { + private static final Logger log = LoggerFactory.getLogger(OrcidSynchronizationServiceImpl.class); @Autowired private ItemService itemService; @@ -75,6 +79,9 @@ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationServ @Autowired private ResearcherProfileService researcherProfileService; + @Autowired + private OrcidClient orcidClient; + @Override public void linkProfile(Context context, Item profile, OrcidTokenResponseDTO token) throws SQLException { @@ -114,20 +121,33 @@ public void linkProfile(Context context, Item profile, OrcidTokenResponseDTO tok @Override public void unlinkProfile(Context context, Item profile) throws SQLException { - itemService.clearMetadata(context, profile, "person", "identifier", "orcid", Item.ANY); - itemService.clearMetadata(context, profile, "dspace", "orcid", "scope", Item.ANY); - itemService.clearMetadata(context, profile, "dspace", "orcid", "authenticated", Item.ANY); + clearOrcidProfileMetadata(context, profile); - if (!configurationService.getBooleanProperty("orcid.disconnection.remain-sync", false)) { - clearSynchronizationSettings(context, profile); - } + clearSynchronizationSettings(context, profile); - orcidTokenService.deleteByProfileItem(context, profile); + clearOrcidToken(context, profile); updateItem(context, profile); } + private void clearOrcidToken(Context context, Item profile) { + OrcidToken profileToken = orcidTokenService.findByProfileItem(context, profile); + if (profileToken == null) { + log.warn("Cannot find any token related to the user profile: {}", profile.getID()); + return; + } + + orcidTokenService.deleteByProfileItem(context, profile); + orcidClient.revokeToken(profileToken); + } + + private void clearOrcidProfileMetadata(Context context, Item profile) throws SQLException { + itemService.clearMetadata(context, profile, "person", "identifier", "orcid", Item.ANY); + itemService.clearMetadata(context, profile, "dspace", "orcid", "scope", Item.ANY); + itemService.clearMetadata(context, profile, "dspace", "orcid", "authenticated", Item.ANY); + } + @Override public boolean setEntityPreference(Context context, Item profile, OrcidEntityType type, OrcidEntitySyncPreference value) throws SQLException { @@ -273,6 +293,11 @@ private boolean updatePreferenceForSynchronizingWithOrcid(Context context, Item private void clearSynchronizationSettings(Context context, Item profile) throws SQLException { + + if (configurationService.getBooleanProperty("orcid.disconnection.remain-sync", false)) { + return; + } + itemService.clearMetadata(context, profile, "dspace", "orcid", "sync-mode", Item.ANY); itemService.clearMetadata(context, profile, "dspace", "orcid", "sync-profile", Item.ANY); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java index b3c70f8128d4..493b3bf94628 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java @@ -31,7 +31,10 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -45,6 +48,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; import java.sql.SQLException; import java.util.List; import java.util.UUID; @@ -80,11 +84,13 @@ import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.dspace.orcid.service.OrcidQueueService; +import org.dspace.orcid.service.OrcidSynchronizationService; import org.dspace.orcid.service.OrcidTokenService; import org.dspace.services.ConfigurationService; import org.dspace.util.UUIDUtils; import org.junit.After; import org.junit.Test; +import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MvcResult; @@ -115,7 +121,11 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra @Autowired private OrcidClient orcidClient; - private OrcidClient orcidClientMock = mock(OrcidClient.class); + @Mock + private OrcidClient orcidClientMock; + + @Autowired + private OrcidSynchronizationService orcidSynchronizationService; private EPerson user; @@ -159,16 +169,36 @@ public void setUp() throws Exception { context.restoreAuthSystemState(); - researcherProfileAddOrcidOperation.setOrcidClient(orcidClientMock); - + useInstanceForBean(orcidSynchronizationService, orcidClientMock); + useInstanceForBean(researcherProfileAddOrcidOperation, orcidClientMock); } @After public void after() { orcidTokenService.deleteAll(context); - researcherProfileAddOrcidOperation.setOrcidClient(orcidClient); + useInstanceForBean(orcidSynchronizationService, orcidClient); + useInstanceForBean(researcherProfileAddOrcidOperation, orcidClient); } + private void useInstanceForBean(B bean, I instance) { + Field[] fields = bean.getClass().getDeclaredFields(); + + for (Field field : fields) { + if (field.getType().isAssignableFrom(instance.getClass())) { + boolean accessible = field.isAccessible(); + try { + field.setAccessible(true); + field.set(bean, instance); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } finally { + field.setAccessible(accessible); + } + } + } + } + + /** * Verify that the findById endpoint returns the own profile. * @@ -609,30 +639,38 @@ public void testDeleteWithProfileLinkedWithOrcid() throws Exception { .withOrcidAuthenticated("authenticated") .build(); + context.restoreAuthSystemState(); + String id = user.getID().toString(); String authToken = getAuthToken(user.getEmail(), password); + OrcidToken orcidToken = orcidTokenService.findByProfileItem(context, profileItem); - context.restoreAuthSystemState(); - - getClient(authToken).perform(get("/api/eperson/profiles/{id}", id)) + getClient(authToken) + .perform(get("/api/eperson/profiles/{id}", id)) .andExpect(status().isOk()); assertThat(profileItem.getMetadata(), hasItem(with("person.identifier.orcid", "0000-1111-2222-3333"))); assertThat(profileItem.getMetadata(), hasItem(with("dspace.orcid.authenticated", "authenticated"))); - assertThat(getOrcidAccessToken(profileItem), notNullValue()); + assertThat(orcidToken.getAccessToken(), notNullValue()); getClient(authToken).perform(get("/api/eperson/profiles/{id}/item", id)) .andExpect(status().isOk()) .andExpect(jsonPath("$", hasJsonPath("$.metadata", matchMetadataNotEmpty("dspace.object.owner")))); + getClient(authToken).perform(delete("/api/eperson/profiles/{id}", id)) .andExpect(status().isNoContent()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profileItem = context.reloadEntity(profileItem); + orcidToken = orcidTokenService.findByProfileItem(context, profileItem); + assertThat(profileItem.getMetadata(), not(hasItem(with("person.identifier.orcid", "0000-1111-2222-3333")))); assertThat(profileItem.getMetadata(), not(hasItem(with("dspace.orcid.authenticated", "authenticated")))); - assertThat(getOrcidAccessToken(profileItem), nullValue()); + assertThat(orcidToken, nullValue()); } @@ -1851,7 +1889,60 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + + Item profile = createProfile(ePerson); + + context.restoreAuthSystemState(); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); + assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); + + getClient(getAuthToken(ePerson.getEmail(), password)) + .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) + .content(getPatchContent(asList(new RemoveOperation("/orcid")))) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(ePerson.getID().toString()))) + .andExpect(jsonPath("$.visible", is(false))) + .andExpect(jsonPath("$.type", is("profile"))) + .andExpect(jsonPath("$.orcid").doesNotExist()) + .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + + verify(orcidClientMock, times(1)) + .revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + + profile = context.reloadEntity(profile); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), empty()); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), empty()); + assertThat(getOrcidAccessToken(profile), nullValue()); + } + + @Test + public void testPatchToDisconnectProfileFromOrcidRevokesOrcidToken() throws Exception { + + configurationService.setProperty("orcid.disconnection.allowed-users", "admin_and_owner"); + + context.turnOffAuthorisationSystem(); + + EPerson ePerson = EPersonBuilder.createEPerson(context) + .withCanLogin(true) + .withOrcid("0000-1111-2222-3333") + .withOrcidScope("/read") + .withOrcidScope("/write") + .withEmail("test@email.it") + .withPassword(password) + .withNameInMetadata("Test", "User") + .build(); + + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -1873,6 +1964,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -1881,6 +1975,54 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration assertThat(getOrcidAccessToken(profile), nullValue()); } + @Test + public void testPatchToDisconnectProfileFromOrcidDoesntRevokeOrcidToken() throws Exception { + + configurationService.setProperty("orcid.disconnection.allowed-users", "admin_and_owner"); + + context.turnOffAuthorisationSystem(); + + EPerson ePerson = EPersonBuilder.createEPerson(context) + .withCanLogin(true) + .withOrcid("0000-1111-2222-3333") + .withOrcidScope("/read") + .withOrcidScope("/write") + .withEmail("test@email.it") + .withPassword(password) + .withNameInMetadata("Test", "User") + .build(); + + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + + Item profile = createProfile(ePerson); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); + assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); + + context.restoreAuthSystemState(); + + doThrow(new OrcidClientException(403, "")).when(orcidClientMock).revokeToken(any(OrcidToken.class)); + + getClient(getAuthToken(ePerson.getEmail(), password)) + .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) + .content(getPatchContent(asList(new RemoveOperation("/orcid")))) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isInternalServerError()); + + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + + profile = context.reloadEntity(profile); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); + assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); + } + @Test public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration() throws Exception { @@ -2024,7 +2166,8 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -2035,6 +2178,7 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration context.restoreAuthSystemState(); + getClient(getAuthToken(admin.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) @@ -2046,6 +2190,9 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2112,17 +2259,18 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .withPassword(password) .withNameInMetadata("Test", "User") .build(); - - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); + context.restoreAuthSystemState(); + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); - context.restoreAuthSystemState(); getClient(getAuthToken(ePerson.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) @@ -2135,6 +2283,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2160,7 +2311,8 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -2171,6 +2323,7 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura context.restoreAuthSystemState(); + getClient(getAuthToken(admin.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) @@ -2182,6 +2335,10 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2250,7 +2407,8 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemoved() .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -2285,6 +2443,7 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemoved() assertThat(metadata, hasItem(with("dspace.orcid.sync-fundings",ALL.name()))); assertThat(getMetadataValues(profile, "dspace.orcid.sync-profile"), hasSize(2)); + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) .contentType(MediaType.APPLICATION_JSON_VALUE)) @@ -2295,6 +2454,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemoved() .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2324,17 +2486,18 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemain() t .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); + context.restoreAuthSystemState(); + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); - context.restoreAuthSystemState(); - String authToken = getAuthToken(ePerson.getEmail(), password); String ePersonId = ePerson.getID().toString(); List operations = asList(new ReplaceOperation("/orcid/mode", "BATCH"), @@ -2359,6 +2522,7 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemain() t assertThat(metadata, hasItem(with("dspace.orcid.sync-fundings",ALL.name()))); assertThat(getMetadataValues(profile, "dspace.orcid.sync-profile"), hasSize(2)); + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) .contentType(MediaType.APPLICATION_JSON_VALUE)) @@ -2369,6 +2533,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemain() t .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2778,4 +2945,13 @@ private OrcidTokenResponseDTO buildOrcidTokenResponse(String orcid, String acces return token; } + private static OrcidToken matchesToken(OrcidToken orcidToken) { + return argThat( + token -> + token != null && + orcidToken.getAccessToken().equals(token.getAccessToken()) && + orcidToken.getID().equals(token.getID()) + ); + } + } diff --git a/dspace/config/modules/orcid.cfg b/dspace/config/modules/orcid.cfg index 28e8df60f83d..ad31371cb890 100644 --- a/dspace/config/modules/orcid.cfg +++ b/dspace/config/modules/orcid.cfg @@ -17,6 +17,7 @@ orcid.disconnection.remain-sync = true # ORCID API (https://github.com/ORCID/ORCID-Source/tree/master/orcid-api-web#endpoints) orcid.domain-url= https://sandbox.orcid.org orcid.authorize-url = ${orcid.domain-url}/oauth/authorize +orcid.revoke-url = ${orcid.domain-url}/oauth/revoke orcid.token-url = ${orcid.domain-url}/oauth/token orcid.api-url = https://api.sandbox.orcid.org/v3.0 orcid.public-url = https://pub.sandbox.orcid.org/v3.0 diff --git a/dspace/config/spring/api/orcid-services.xml b/dspace/config/spring/api/orcid-services.xml index 8286a16a88fb..6ec9be9fdf5d 100644 --- a/dspace/config/spring/api/orcid-services.xml +++ b/dspace/config/spring/api/orcid-services.xml @@ -30,6 +30,7 @@ + From a9400a7f48c7afa321310911e6c870197237394a Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Tue, 21 Nov 2023 11:51:25 +0100 Subject: [PATCH 021/632] [CST-14901][DSC-1357][#8662] Handles versioning for ORCID publications. feat: - ORCID publications waiting to be published are removed whenever a new version is created - ORCID publications already published will be updated with the ref to the last item version - ORCID consumer will process only latest item versions, ignoring all the other ones --- .../org/dspace/content/ItemServiceImpl.java | 42 ++++ .../dspace/content/service/ItemService.java | 10 + .../orcid/consumer/OrcidQueueConsumer.java | 49 +++-- .../org/dspace/orcid/dao/OrcidQueueDAO.java | 10 + .../orcid/dao/impl/OrcidQueueDAOImpl.java | 7 + .../orcid/service/OrcidQueueService.java | 10 + .../service/impl/OrcidQueueServiceImpl.java | 5 + .../dspace/versioning/VersioningConsumer.java | 35 +++- .../dspace/orcid/OrcidQueueConsumerIT.java | 185 ++++++++++++++++++ 9 files changed, 336 insertions(+), 17 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index 70bdf4b7d950..d300f22d5637 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -81,6 +81,9 @@ import org.dspace.profile.service.ResearcherProfileService; import org.dspace.qaevent.dao.QAEventsDAO; import org.dspace.services.ConfigurationService; +import org.dspace.versioning.Version; +import org.dspace.versioning.VersionHistory; +import org.dspace.versioning.service.VersionHistoryService; import org.dspace.versioning.service.VersioningService; import org.dspace.workflow.WorkflowItemService; import org.dspace.workflow.factory.WorkflowServiceFactory; @@ -176,6 +179,9 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It @Autowired private QAEventsDAO qaEventsDao; + @Autowired + private VersionHistoryService versionHistoryService; + protected ItemServiceImpl() { } @@ -1931,4 +1937,40 @@ private void deleteOrcidQueueRecords(Context context, Item item) throws SQLExcep } } + @Override + public boolean isLatestVersion(Context context, Item item) throws SQLException { + + VersionHistory history = versionHistoryService.findByItem(context, item); + if (history == null) { + // not all items have a version history + // if an item does not have a version history, it is by definition the latest + // version + return true; + } + + // start with the very latest version of the given item (may still be in + // workspace) + Version latestVersion = versionHistoryService.getLatestVersion(context, history); + + // find the latest version of the given item that is archived + while (latestVersion != null && !latestVersion.getItem().isArchived()) { + latestVersion = versionHistoryService.getPrevious(context, history, latestVersion); + } + + // could not find an archived version of the given item + if (latestVersion == null) { + // this scenario should never happen, but let's err on the side of showing too + // many items vs. to little + // (see discovery.xml, a lot of discovery configs filter out all items that are + // not the latest version) + return true; + } + + // sanity check + assert latestVersion.getItem().isArchived(); + + return item.equals(latestVersion.getItem()); + + } + } diff --git a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java index 47d2d5bdaa88..3fea75665bcb 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java @@ -1009,4 +1009,14 @@ List getMetadata(Item item, String schema, String element, String */ EntityType getEntityType(Context context, Item item) throws SQLException; + + /** + * Check whether the given item is the latest version. If the latest item cannot + * be determined, because either the version history or the latest version is + * not present, assume the item is latest. + * @param context the DSpace context. + * @param item the item that should be checked. + * @return true if the item is the latest version, false otherwise. + */ + public boolean isLatestVersion(Context context, Item item) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/orcid/consumer/OrcidQueueConsumer.java b/dspace-api/src/main/java/org/dspace/orcid/consumer/OrcidQueueConsumer.java index 97da341fb811..6b174e96957f 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/consumer/OrcidQueueConsumer.java +++ b/dspace-api/src/main/java/org/dspace/orcid/consumer/OrcidQueueConsumer.java @@ -14,9 +14,10 @@ import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import java.sql.SQLException; -import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -82,7 +83,7 @@ public class OrcidQueueConsumer implements Consumer { private RelationshipService relationshipService; - private final List alreadyConsumedItems = new ArrayList<>(); + private final Set itemsToConsume = new HashSet<>(); @Override public void initialize() throws Exception { @@ -117,17 +118,26 @@ public void consume(Context context, Event event) throws Exception { return; } - if (alreadyConsumedItems.contains(item.getID())) { - return; - } + itemsToConsume.add(item.getID()); + } + + @Override + public void end(Context context) throws Exception { + + for (UUID itemId : itemsToConsume) { + + Item item = itemService.find(context, itemId); + + context.turnOffAuthorisationSystem(); + try { + consumeItem(context, item); + } finally { + context.restoreAuthSystemState(); + } - context.turnOffAuthorisationSystem(); - try { - consumeItem(context, item); - } finally { - context.restoreAuthSystemState(); } + itemsToConsume.clear(); } /** @@ -146,7 +156,7 @@ private void consumeItem(Context context, Item item) throws SQLException { consumeProfile(context, item); } - alreadyConsumedItems.add(item.getID()); + itemsToConsume.add(item.getID()); } @@ -169,6 +179,10 @@ private void consumeEntity(Context context, Item entity) throws SQLException { continue; } + if (isNotLatestVersion(context, entity)) { + continue; + } + orcidQueueService.create(context, relatedItem, entity); } @@ -329,6 +343,14 @@ private boolean isNotProfileItem(Item profileItemItem) { return !getProfileType().equals(itemService.getEntityTypeLabel(profileItemItem)); } + private boolean isNotLatestVersion(Context context, Item entity) { + try { + return !itemService.isLatestVersion(context, entity); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + private String getMetadataValue(Item item, String metadataField) { return itemService.getMetadataFirstValue(item, new MetadataFieldName(metadataField), Item.ANY); } @@ -345,11 +367,6 @@ private boolean isOrcidSynchronizationDisabled() { return !configurationService.getBooleanProperty("orcid.synchronization-enabled", true); } - @Override - public void end(Context context) throws Exception { - alreadyConsumedItems.clear(); - } - @Override public void finish(Context context) throws Exception { // nothing to do diff --git a/dspace-api/src/main/java/org/dspace/orcid/dao/OrcidQueueDAO.java b/dspace-api/src/main/java/org/dspace/orcid/dao/OrcidQueueDAO.java index 235443b15033..b7e0b1ed2a85 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/dao/OrcidQueueDAO.java +++ b/dspace-api/src/main/java/org/dspace/orcid/dao/OrcidQueueDAO.java @@ -74,6 +74,16 @@ public List findByProfileItemAndEntity(Context context, Item profile */ public List findByProfileItemOrEntity(Context context, Item item) throws SQLException; + /** + * Get the OrcidQueue records where the given item is the entity. + * + * @param context DSpace context object + * @param item the item to search for + * @return the found OrcidQueue entities + * @throws SQLException if database error + */ + public List findByEntity(Context context, Item item) throws SQLException; + /** * Find all the OrcidQueue records with the given entity and record type. * diff --git a/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidQueueDAOImpl.java b/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidQueueDAOImpl.java index c8e48e3f17d6..091e59750517 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidQueueDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidQueueDAOImpl.java @@ -63,6 +63,13 @@ public List findByProfileItemOrEntity(Context context, Item item) th return query.getResultList(); } + @Override + public List findByEntity(Context context, Item item) throws SQLException { + Query query = createQuery(context, "FROM OrcidQueue WHERE entity.id = :itemId"); + query.setParameter("itemId", item.getID()); + return query.getResultList(); + } + @Override public List findByEntityAndRecordType(Context context, Item entity, String type) throws SQLException { Query query = createQuery(context, "FROM OrcidQueue WHERE entity = :entity AND recordType = :type"); diff --git a/dspace-api/src/main/java/org/dspace/orcid/service/OrcidQueueService.java b/dspace-api/src/main/java/org/dspace/orcid/service/OrcidQueueService.java index 8de25e9caf1e..b667088eabb4 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/service/OrcidQueueService.java +++ b/dspace-api/src/main/java/org/dspace/orcid/service/OrcidQueueService.java @@ -164,6 +164,16 @@ public List findByProfileItemAndEntity(Context context, Item profile */ public List findByProfileItemOrEntity(Context context, Item item) throws SQLException; + /** + * Get the OrcidQueue records where the given item is the entity. + * + * @param context DSpace context object + * @param item the item to search for + * @return the found OrcidQueue records + * @throws SQLException if database error + */ + public List findByEntity(Context context, Item item) throws SQLException; + /** * Get all the OrcidQueue records with attempts less than the given attempts. * diff --git a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidQueueServiceImpl.java b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidQueueServiceImpl.java index d3300fea6606..261f8ef9a9f7 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidQueueServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidQueueServiceImpl.java @@ -70,6 +70,11 @@ public List findByProfileItemOrEntity(Context context, Item item) th return orcidQueueDAO.findByProfileItemOrEntity(context, item); } + @Override + public List findByEntity(Context context, Item item) throws SQLException { + return orcidQueueDAO.findByEntity(context, item); + } + @Override public long countByProfileItemId(Context context, UUID profileItemId) throws SQLException { return orcidQueueDAO.countByProfileItemId(context, profileItemId); diff --git a/dspace-api/src/main/java/org/dspace/versioning/VersioningConsumer.java b/dspace-api/src/main/java/org/dspace/versioning/VersioningConsumer.java index 63b5391d0a28..27a81a157917 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/VersioningConsumer.java +++ b/dspace-api/src/main/java/org/dspace/versioning/VersioningConsumer.java @@ -33,6 +33,11 @@ import org.dspace.discovery.IndexEventConsumer; import org.dspace.event.Consumer; import org.dspace.event.Event; +import org.dspace.orcid.OrcidHistory; +import org.dspace.orcid.OrcidQueue; +import org.dspace.orcid.factory.OrcidServiceFactory; +import org.dspace.orcid.service.OrcidHistoryService; +import org.dspace.orcid.service.OrcidQueueService; import org.dspace.versioning.factory.VersionServiceFactory; import org.dspace.versioning.service.VersionHistoryService; import org.dspace.versioning.utils.RelationshipVersioningUtils; @@ -58,6 +63,8 @@ public class VersioningConsumer implements Consumer { private RelationshipTypeService relationshipTypeService; private RelationshipService relationshipService; private RelationshipVersioningUtils relationshipVersioningUtils; + private OrcidQueueService orcidQueueService; + private OrcidHistoryService orcidHistoryService; @Override public void initialize() throws Exception { @@ -67,6 +74,8 @@ public void initialize() throws Exception { relationshipTypeService = ContentServiceFactory.getInstance().getRelationshipTypeService(); relationshipService = ContentServiceFactory.getInstance().getRelationshipService(); relationshipVersioningUtils = VersionServiceFactory.getInstance().getRelationshipVersioningUtils(); + this.orcidQueueService = OrcidServiceFactory.getInstance().getOrcidQueueService(); + this.orcidHistoryService = OrcidServiceFactory.getInstance().getOrcidHistoryService(); } @Override @@ -132,7 +141,8 @@ public void consume(Context ctx, Event event) throws Exception { // unarchive previous item unarchiveItem(ctx, previousItem); - + // handles versions for ORCID publications waiting to be shipped, or already published (history-queue). + handleOrcidSynchronization(ctx, previousItem, latestItem); // update relationships updateRelationships(ctx, latestItem, previousItem); } @@ -148,6 +158,29 @@ protected void unarchiveItem(Context ctx, Item item) { )); } + private void handleOrcidSynchronization(Context ctx, Item previousItem, Item latestItem) { + try { + replaceOrcidHistoryEntities(ctx, previousItem, latestItem); + removeOrcidQueueEntries(ctx, previousItem); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private void removeOrcidQueueEntries(Context ctx, Item previousItem) throws SQLException { + List queueEntries = orcidQueueService.findByEntity(ctx, previousItem); + for (OrcidQueue queueEntry : queueEntries) { + orcidQueueService.delete(ctx, queueEntry); + } + } + + private void replaceOrcidHistoryEntities(Context ctx, Item previousItem, Item latestItem) throws SQLException { + List entries = orcidHistoryService.findByEntity(ctx, previousItem); + for (OrcidHistory entry : entries) { + entry.setEntity(latestItem); + } + } + /** * Update {@link Relationship#latestVersionStatus} of the relationships of both the old version and the new version * of the item. diff --git a/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java b/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java index f2e528d78cd6..e17fd0072efa 100644 --- a/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java +++ b/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java @@ -23,6 +23,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; import java.sql.SQLException; import java.time.Instant; @@ -41,13 +42,19 @@ import org.dspace.content.Item; import org.dspace.content.MetadataValue; import org.dspace.content.RelationshipType; +import org.dspace.content.WorkspaceItem; import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; +import org.dspace.content.service.WorkspaceItemService; import org.dspace.orcid.consumer.OrcidQueueConsumer; import org.dspace.orcid.factory.OrcidServiceFactory; import org.dspace.orcid.service.OrcidQueueService; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.utils.DSpace; +import org.dspace.versioning.Version; +import org.dspace.versioning.service.VersioningService; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -64,8 +71,15 @@ public class OrcidQueueConsumerIT extends AbstractIntegrationTestWithDatabase { private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + private WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService(); + + private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); + private VersioningService versioningService = new DSpace().getServiceManager() + .getServicesByType(VersioningService.class).get(0); + private Collection profileCollection; @Before @@ -763,6 +777,177 @@ public void testWithManyInsertionAndDeletionOfSameMetadataValue() throws Excepti } + @Test + public void testOrcidQueueRecordCreationForPublicationWithNotFoundAuthority() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .withOrcidSynchronizationPublicationsPreference(ALL) + .build(); + + Collection publicationCollection = createCollection("Publications", "Publication"); + + Item publication = ItemBuilder.createItem(context, publicationCollection) + .withTitle("Test publication") + .withAuthor("First User") + .withAuthor("Test User") + .build(); + + EntityType publicationType = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication").build(); + EntityType personType = EntityTypeBuilder.createEntityTypeBuilder(context, "Person").build(); + + RelationshipType isAuthorOfPublication = createRelationshipTypeBuilder(context, personType, publicationType, + "isAuthorOfPublication", + "isPublicationOfAuthor", 0, null, 0, + null).build(); + + RelationshipBuilder.createRelationshipBuilder(context, profile, publication, isAuthorOfPublication).build(); + + context.restoreAuthSystemState(); + context.commit(); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", INSERT)); + } + + @Test + public void testOrcidQueueWithItemVersioning() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .withOrcidSynchronizationPublicationsPreference(ALL) + .build(); + + Collection publicationCollection = createCollection("Publications", "Publication"); + + Item publication = ItemBuilder.createItem(context, publicationCollection) + .withTitle("Test publication") + .withAuthor("Test User") + .build(); + + EntityType publicationType = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication").build(); + EntityType personType = EntityTypeBuilder.createEntityTypeBuilder(context, "Person").build(); + + RelationshipType isAuthorOfPublication = createRelationshipTypeBuilder(context, personType, publicationType, + "isAuthorOfPublication", + "isPublicationOfAuthor", 0, null, 0, + null).build(); + + RelationshipBuilder.createRelationshipBuilder(context, profile, publication, isAuthorOfPublication).build(); + + context.restoreAuthSystemState(); + context.commit(); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", INSERT)); + + context.turnOffAuthorisationSystem(); + Version newVersion = versioningService.createNewVersion(context, publication); + context.restoreAuthSystemState(); + Item newPublication = newVersion.getItem(); + assertThat(newPublication.isArchived(), is(false)); + + context.commit(); + + orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", INSERT)); + + WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, newVersion.getItem()); + context.turnOffAuthorisationSystem(); + + installItemService.installItem(context, workspaceItem); + + context.restoreAuthSystemState(); + context.commit(); + + orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, newPublication, "Publication", INSERT)); + } + + @Test + public void testOrcidQueueUpdateWithItemVersioning() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .withOrcidSynchronizationPublicationsPreference(ALL) + .build(); + + Collection publicationCollection = createCollection("Publications", "Publication"); + + Item publication = ItemBuilder.createItem(context, publicationCollection) + .withTitle("Test publication") + .build(); + + OrcidHistory orcidHistory = OrcidHistoryBuilder.createOrcidHistory(context, profile, publication) + .withDescription("Test publication") + .withOperation(OrcidOperation.INSERT) + .withPutCode("12345") + .withStatus(201) + .build(); + + addMetadata(publication, "dc", "contributor", "author", "Test User", null); + + EntityType publicationType = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication").build(); + EntityType personType = EntityTypeBuilder.createEntityTypeBuilder(context, "Person").build(); + + RelationshipType isAuthorOfPublication = + createRelationshipTypeBuilder( + context, personType, publicationType, + "isAuthorOfPublication", + "isPublicationOfAuthor", 0, null, 0, + null + ).build(); + + RelationshipBuilder.createRelationshipBuilder(context, profile, publication, isAuthorOfPublication).build(); + + context.commit(); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", "12345", UPDATE)); + + Version newVersion = versioningService.createNewVersion(context, publication); + Item newPublication = newVersion.getItem(); + assertThat(newPublication.isArchived(), is(false)); + + context.commit(); + + orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", "12345", UPDATE)); + + WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, newVersion.getItem()); + installItemService.installItem(context, workspaceItem); + + context.commit(); + + context.restoreAuthSystemState(); + + orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, newPublication, "Publication", "12345", UPDATE)); + + orcidHistory = context.reloadEntity(orcidHistory); + assertThat(orcidHistory.getEntity(), is(newPublication)); + + } + private void addMetadata(Item item, String schema, String element, String qualifier, String value, String authority) throws Exception { context.turnOffAuthorisationSystem(); From 26905b7d45f058f1bd8476f9e915af9a5be1547f Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Tue, 21 Nov 2023 11:51:25 +0100 Subject: [PATCH 022/632] [CST-14901][DSC-1357][#8662] Handles versioning for ORCID publications. feat: - ORCID publications waiting to be published are removed whenever a new version is created - ORCID publications already published will be updated with the ref to the last item version - ORCID consumer will process only latest item versions, ignoring all the other ones --- .../org/dspace/content/ItemServiceImpl.java | 42 ++++ .../dspace/content/service/ItemService.java | 10 + .../orcid/consumer/OrcidQueueConsumer.java | 51 +++-- .../org/dspace/orcid/dao/OrcidQueueDAO.java | 10 + .../orcid/dao/impl/OrcidQueueDAOImpl.java | 7 + .../orcid/service/OrcidQueueService.java | 10 + .../service/impl/OrcidQueueServiceImpl.java | 5 + .../dspace/versioning/VersioningConsumer.java | 35 +++- .../dspace/orcid/OrcidQueueConsumerIT.java | 185 ++++++++++++++++++ 9 files changed, 337 insertions(+), 18 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index ac6c0d43d710..ae7081f73a37 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -79,6 +79,9 @@ import org.dspace.orcid.service.OrcidTokenService; import org.dspace.profile.service.ResearcherProfileService; import org.dspace.services.ConfigurationService; +import org.dspace.versioning.Version; +import org.dspace.versioning.VersionHistory; +import org.dspace.versioning.service.VersionHistoryService; import org.dspace.versioning.service.VersioningService; import org.dspace.workflow.WorkflowItemService; import org.dspace.workflow.factory.WorkflowServiceFactory; @@ -171,6 +174,9 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It @Autowired(required = true) protected SubscribeService subscribeService; + @Autowired + private VersionHistoryService versionHistoryService; + protected ItemServiceImpl() { super(); } @@ -1920,4 +1926,40 @@ private void deleteOrcidQueueRecords(Context context, Item item) throws SQLExcep } } + @Override + public boolean isLatestVersion(Context context, Item item) throws SQLException { + + VersionHistory history = versionHistoryService.findByItem(context, item); + if (history == null) { + // not all items have a version history + // if an item does not have a version history, it is by definition the latest + // version + return true; + } + + // start with the very latest version of the given item (may still be in + // workspace) + Version latestVersion = versionHistoryService.getLatestVersion(context, history); + + // find the latest version of the given item that is archived + while (latestVersion != null && !latestVersion.getItem().isArchived()) { + latestVersion = versionHistoryService.getPrevious(context, history, latestVersion); + } + + // could not find an archived version of the given item + if (latestVersion == null) { + // this scenario should never happen, but let's err on the side of showing too + // many items vs. to little + // (see discovery.xml, a lot of discovery configs filter out all items that are + // not the latest version) + return true; + } + + // sanity check + assert latestVersion.getItem().isArchived(); + + return item.equals(latestVersion.getItem()); + + } + } diff --git a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java index 12867ad18c3f..a307e7ceffad 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java @@ -983,4 +983,14 @@ public List getMetadata(Item item, String schema, String element, */ public EntityType getEntityType(Context context, Item item) throws SQLException; + + /** + * Check whether the given item is the latest version. If the latest item cannot + * be determined, because either the version history or the latest version is + * not present, assume the item is latest. + * @param context the DSpace context. + * @param item the item that should be checked. + * @return true if the item is the latest version, false otherwise. + */ + public boolean isLatestVersion(Context context, Item item) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/orcid/consumer/OrcidQueueConsumer.java b/dspace-api/src/main/java/org/dspace/orcid/consumer/OrcidQueueConsumer.java index d177e61607f1..ae989e1dd8f8 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/consumer/OrcidQueueConsumer.java +++ b/dspace-api/src/main/java/org/dspace/orcid/consumer/OrcidQueueConsumer.java @@ -14,9 +14,10 @@ import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import java.sql.SQLException; -import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -56,7 +57,7 @@ * be synchronized (based on the preferences set by the user) *
  • are publications/fundings related to profile items linked to orcid (based * on the preferences set by the user)
  • - * + * * * * @author Luca Giamminonni (luca.giamminonni at 4science.it) @@ -82,7 +83,7 @@ public class OrcidQueueConsumer implements Consumer { private RelationshipService relationshipService; - private List alreadyConsumedItems = new ArrayList<>(); + private final Set itemsToConsume = new HashSet<>(); @Override public void initialize() throws Exception { @@ -117,17 +118,26 @@ public void consume(Context context, Event event) throws Exception { return; } - if (alreadyConsumedItems.contains(item.getID())) { - return; - } + itemsToConsume.add(item.getID()); + } + + @Override + public void end(Context context) throws Exception { + + for (UUID itemId : itemsToConsume) { + + Item item = itemService.find(context, itemId); + + context.turnOffAuthorisationSystem(); + try { + consumeItem(context, item); + } finally { + context.restoreAuthSystemState(); + } - context.turnOffAuthorisationSystem(); - try { - consumeItem(context, item); - } finally { - context.restoreAuthSystemState(); } + itemsToConsume.clear(); } /** @@ -146,7 +156,7 @@ private void consumeItem(Context context, Item item) throws SQLException { consumeProfile(context, item); } - alreadyConsumedItems.add(item.getID()); + itemsToConsume.add(item.getID()); } @@ -169,6 +179,10 @@ private void consumeEntity(Context context, Item entity) throws SQLException { continue; } + if (isNotLatestVersion(context, entity)) { + continue; + } + orcidQueueService.create(context, relatedItem, entity); } @@ -329,6 +343,14 @@ private boolean isNotProfileItem(Item profileItemItem) { return !getProfileType().equals(itemService.getEntityTypeLabel(profileItemItem)); } + private boolean isNotLatestVersion(Context context, Item entity) { + try { + return !itemService.isLatestVersion(context, entity); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + private String getMetadataValue(Item item, String metadataField) { return itemService.getMetadataFirstValue(item, new MetadataFieldName(metadataField), Item.ANY); } @@ -345,11 +367,6 @@ private boolean isOrcidSynchronizationDisabled() { return !configurationService.getBooleanProperty("orcid.synchronization-enabled", true); } - @Override - public void end(Context context) throws Exception { - alreadyConsumedItems.clear(); - } - @Override public void finish(Context context) throws Exception { // nothing to do diff --git a/dspace-api/src/main/java/org/dspace/orcid/dao/OrcidQueueDAO.java b/dspace-api/src/main/java/org/dspace/orcid/dao/OrcidQueueDAO.java index 235443b15033..b7e0b1ed2a85 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/dao/OrcidQueueDAO.java +++ b/dspace-api/src/main/java/org/dspace/orcid/dao/OrcidQueueDAO.java @@ -74,6 +74,16 @@ public List findByProfileItemAndEntity(Context context, Item profile */ public List findByProfileItemOrEntity(Context context, Item item) throws SQLException; + /** + * Get the OrcidQueue records where the given item is the entity. + * + * @param context DSpace context object + * @param item the item to search for + * @return the found OrcidQueue entities + * @throws SQLException if database error + */ + public List findByEntity(Context context, Item item) throws SQLException; + /** * Find all the OrcidQueue records with the given entity and record type. * diff --git a/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidQueueDAOImpl.java b/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidQueueDAOImpl.java index 2114b2535759..8e941b056535 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidQueueDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidQueueDAOImpl.java @@ -63,6 +63,13 @@ public List findByProfileItemOrEntity(Context context, Item item) th return query.getResultList(); } + @Override + public List findByEntity(Context context, Item item) throws SQLException { + Query query = createQuery(context, "FROM OrcidQueue WHERE entity.id = :itemId"); + query.setParameter("itemId", item.getID()); + return query.getResultList(); + } + @Override public List findByEntityAndRecordType(Context context, Item entity, String type) throws SQLException { Query query = createQuery(context, "FROM OrcidQueue WHERE entity = :entity AND recordType = :type"); diff --git a/dspace-api/src/main/java/org/dspace/orcid/service/OrcidQueueService.java b/dspace-api/src/main/java/org/dspace/orcid/service/OrcidQueueService.java index 8de25e9caf1e..b667088eabb4 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/service/OrcidQueueService.java +++ b/dspace-api/src/main/java/org/dspace/orcid/service/OrcidQueueService.java @@ -164,6 +164,16 @@ public List findByProfileItemAndEntity(Context context, Item profile */ public List findByProfileItemOrEntity(Context context, Item item) throws SQLException; + /** + * Get the OrcidQueue records where the given item is the entity. + * + * @param context DSpace context object + * @param item the item to search for + * @return the found OrcidQueue records + * @throws SQLException if database error + */ + public List findByEntity(Context context, Item item) throws SQLException; + /** * Get all the OrcidQueue records with attempts less than the given attempts. * diff --git a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidQueueServiceImpl.java b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidQueueServiceImpl.java index d3300fea6606..261f8ef9a9f7 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidQueueServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidQueueServiceImpl.java @@ -70,6 +70,11 @@ public List findByProfileItemOrEntity(Context context, Item item) th return orcidQueueDAO.findByProfileItemOrEntity(context, item); } + @Override + public List findByEntity(Context context, Item item) throws SQLException { + return orcidQueueDAO.findByEntity(context, item); + } + @Override public long countByProfileItemId(Context context, UUID profileItemId) throws SQLException { return orcidQueueDAO.countByProfileItemId(context, profileItemId); diff --git a/dspace-api/src/main/java/org/dspace/versioning/VersioningConsumer.java b/dspace-api/src/main/java/org/dspace/versioning/VersioningConsumer.java index 63b5391d0a28..27a81a157917 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/VersioningConsumer.java +++ b/dspace-api/src/main/java/org/dspace/versioning/VersioningConsumer.java @@ -33,6 +33,11 @@ import org.dspace.discovery.IndexEventConsumer; import org.dspace.event.Consumer; import org.dspace.event.Event; +import org.dspace.orcid.OrcidHistory; +import org.dspace.orcid.OrcidQueue; +import org.dspace.orcid.factory.OrcidServiceFactory; +import org.dspace.orcid.service.OrcidHistoryService; +import org.dspace.orcid.service.OrcidQueueService; import org.dspace.versioning.factory.VersionServiceFactory; import org.dspace.versioning.service.VersionHistoryService; import org.dspace.versioning.utils.RelationshipVersioningUtils; @@ -58,6 +63,8 @@ public class VersioningConsumer implements Consumer { private RelationshipTypeService relationshipTypeService; private RelationshipService relationshipService; private RelationshipVersioningUtils relationshipVersioningUtils; + private OrcidQueueService orcidQueueService; + private OrcidHistoryService orcidHistoryService; @Override public void initialize() throws Exception { @@ -67,6 +74,8 @@ public void initialize() throws Exception { relationshipTypeService = ContentServiceFactory.getInstance().getRelationshipTypeService(); relationshipService = ContentServiceFactory.getInstance().getRelationshipService(); relationshipVersioningUtils = VersionServiceFactory.getInstance().getRelationshipVersioningUtils(); + this.orcidQueueService = OrcidServiceFactory.getInstance().getOrcidQueueService(); + this.orcidHistoryService = OrcidServiceFactory.getInstance().getOrcidHistoryService(); } @Override @@ -132,7 +141,8 @@ public void consume(Context ctx, Event event) throws Exception { // unarchive previous item unarchiveItem(ctx, previousItem); - + // handles versions for ORCID publications waiting to be shipped, or already published (history-queue). + handleOrcidSynchronization(ctx, previousItem, latestItem); // update relationships updateRelationships(ctx, latestItem, previousItem); } @@ -148,6 +158,29 @@ protected void unarchiveItem(Context ctx, Item item) { )); } + private void handleOrcidSynchronization(Context ctx, Item previousItem, Item latestItem) { + try { + replaceOrcidHistoryEntities(ctx, previousItem, latestItem); + removeOrcidQueueEntries(ctx, previousItem); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private void removeOrcidQueueEntries(Context ctx, Item previousItem) throws SQLException { + List queueEntries = orcidQueueService.findByEntity(ctx, previousItem); + for (OrcidQueue queueEntry : queueEntries) { + orcidQueueService.delete(ctx, queueEntry); + } + } + + private void replaceOrcidHistoryEntities(Context ctx, Item previousItem, Item latestItem) throws SQLException { + List entries = orcidHistoryService.findByEntity(ctx, previousItem); + for (OrcidHistory entry : entries) { + entry.setEntity(latestItem); + } + } + /** * Update {@link Relationship#latestVersionStatus} of the relationships of both the old version and the new version * of the item. diff --git a/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java b/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java index f2e528d78cd6..e17fd0072efa 100644 --- a/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java +++ b/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java @@ -23,6 +23,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; import java.sql.SQLException; import java.time.Instant; @@ -41,13 +42,19 @@ import org.dspace.content.Item; import org.dspace.content.MetadataValue; import org.dspace.content.RelationshipType; +import org.dspace.content.WorkspaceItem; import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; +import org.dspace.content.service.WorkspaceItemService; import org.dspace.orcid.consumer.OrcidQueueConsumer; import org.dspace.orcid.factory.OrcidServiceFactory; import org.dspace.orcid.service.OrcidQueueService; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.utils.DSpace; +import org.dspace.versioning.Version; +import org.dspace.versioning.service.VersioningService; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -64,8 +71,15 @@ public class OrcidQueueConsumerIT extends AbstractIntegrationTestWithDatabase { private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + private WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService(); + + private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); + private VersioningService versioningService = new DSpace().getServiceManager() + .getServicesByType(VersioningService.class).get(0); + private Collection profileCollection; @Before @@ -763,6 +777,177 @@ public void testWithManyInsertionAndDeletionOfSameMetadataValue() throws Excepti } + @Test + public void testOrcidQueueRecordCreationForPublicationWithNotFoundAuthority() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .withOrcidSynchronizationPublicationsPreference(ALL) + .build(); + + Collection publicationCollection = createCollection("Publications", "Publication"); + + Item publication = ItemBuilder.createItem(context, publicationCollection) + .withTitle("Test publication") + .withAuthor("First User") + .withAuthor("Test User") + .build(); + + EntityType publicationType = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication").build(); + EntityType personType = EntityTypeBuilder.createEntityTypeBuilder(context, "Person").build(); + + RelationshipType isAuthorOfPublication = createRelationshipTypeBuilder(context, personType, publicationType, + "isAuthorOfPublication", + "isPublicationOfAuthor", 0, null, 0, + null).build(); + + RelationshipBuilder.createRelationshipBuilder(context, profile, publication, isAuthorOfPublication).build(); + + context.restoreAuthSystemState(); + context.commit(); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", INSERT)); + } + + @Test + public void testOrcidQueueWithItemVersioning() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .withOrcidSynchronizationPublicationsPreference(ALL) + .build(); + + Collection publicationCollection = createCollection("Publications", "Publication"); + + Item publication = ItemBuilder.createItem(context, publicationCollection) + .withTitle("Test publication") + .withAuthor("Test User") + .build(); + + EntityType publicationType = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication").build(); + EntityType personType = EntityTypeBuilder.createEntityTypeBuilder(context, "Person").build(); + + RelationshipType isAuthorOfPublication = createRelationshipTypeBuilder(context, personType, publicationType, + "isAuthorOfPublication", + "isPublicationOfAuthor", 0, null, 0, + null).build(); + + RelationshipBuilder.createRelationshipBuilder(context, profile, publication, isAuthorOfPublication).build(); + + context.restoreAuthSystemState(); + context.commit(); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", INSERT)); + + context.turnOffAuthorisationSystem(); + Version newVersion = versioningService.createNewVersion(context, publication); + context.restoreAuthSystemState(); + Item newPublication = newVersion.getItem(); + assertThat(newPublication.isArchived(), is(false)); + + context.commit(); + + orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", INSERT)); + + WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, newVersion.getItem()); + context.turnOffAuthorisationSystem(); + + installItemService.installItem(context, workspaceItem); + + context.restoreAuthSystemState(); + context.commit(); + + orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, newPublication, "Publication", INSERT)); + } + + @Test + public void testOrcidQueueUpdateWithItemVersioning() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .withOrcidSynchronizationPublicationsPreference(ALL) + .build(); + + Collection publicationCollection = createCollection("Publications", "Publication"); + + Item publication = ItemBuilder.createItem(context, publicationCollection) + .withTitle("Test publication") + .build(); + + OrcidHistory orcidHistory = OrcidHistoryBuilder.createOrcidHistory(context, profile, publication) + .withDescription("Test publication") + .withOperation(OrcidOperation.INSERT) + .withPutCode("12345") + .withStatus(201) + .build(); + + addMetadata(publication, "dc", "contributor", "author", "Test User", null); + + EntityType publicationType = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication").build(); + EntityType personType = EntityTypeBuilder.createEntityTypeBuilder(context, "Person").build(); + + RelationshipType isAuthorOfPublication = + createRelationshipTypeBuilder( + context, personType, publicationType, + "isAuthorOfPublication", + "isPublicationOfAuthor", 0, null, 0, + null + ).build(); + + RelationshipBuilder.createRelationshipBuilder(context, profile, publication, isAuthorOfPublication).build(); + + context.commit(); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", "12345", UPDATE)); + + Version newVersion = versioningService.createNewVersion(context, publication); + Item newPublication = newVersion.getItem(); + assertThat(newPublication.isArchived(), is(false)); + + context.commit(); + + orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, publication, "Publication", "12345", UPDATE)); + + WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, newVersion.getItem()); + installItemService.installItem(context, workspaceItem); + + context.commit(); + + context.restoreAuthSystemState(); + + orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, newPublication, "Publication", "12345", UPDATE)); + + orcidHistory = context.reloadEntity(orcidHistory); + assertThat(orcidHistory.getEntity(), is(newPublication)); + + } + private void addMetadata(Item item, String schema, String element, String qualifier, String value, String authority) throws Exception { context.turnOffAuthorisationSystem(); From dc126f7e943e372c507348a349a302bda57c86c1 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 22 Jul 2024 15:08:59 +0200 Subject: [PATCH 023/632] 116542: fix issues with CSV importing and the Any language being set on metadata values (cherry picked from commit e03c402a9dfdc8df798ded03c96f23a2dfff0eea) --- .../org/dspace/administer/StructBuilder.java | 2 +- .../org/dspace/app/bulkedit/DSpaceCSV.java | 18 ++++++ .../java/org/dspace/content/Collection.java | 2 +- .../org/dspace/content/MetadataValue.java | 4 ++ .../dspace/app/bulkedit/MetadataImportIT.java | 27 +++++++- .../builder/AbstractDSpaceObjectBuilder.java | 3 +- .../dspace/content/ItemComparatorTest.java | 64 +++++++++---------- .../java/org/dspace/content/ItemTest.java | 34 +++++----- .../content/dao/RelationshipDAOImplIT.java | 4 +- .../dao/RelationshipTypeDAOImplIT.java | 4 +- .../org/dspace/app/rest/PatchMetadataIT.java | 2 +- .../rest/RelationshipRestRepositoryIT.java | 26 ++++---- 12 files changed, 118 insertions(+), 72 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java b/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java index 13a1b3b5bbf8..8bbcfe0ff753 100644 --- a/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java +++ b/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java @@ -802,7 +802,7 @@ private static Element[] handleCollections(Context context, // default the short description to the empty string collectionService.setMetadataSingleValue(context, collection, - MD_SHORT_DESCRIPTION, Item.ANY, " "); + MD_SHORT_DESCRIPTION, null, " "); // import the rest of the metadata for (Map.Entry entry : collectionMap.entrySet()) { diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java index cbc052b5573f..3533a2397b3d 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java @@ -188,6 +188,15 @@ public DSpaceCSV(InputStream inputStream, Context c) throws Exception { // Verify that the heading is valid in the metadata registry String[] clean = element.split("\\["); String[] parts = clean[0].split("\\."); + // Check language if present, if it's ANY then throw an exception + if (clean.length > 1 && clean[1].equals(Item.ANY + "]")) { + throw new MetadataImportInvalidHeadingException("Language ANY (*) was found in the heading " + + "of the metadata value to import, " + + "this should never be the case", + MetadataImportInvalidHeadingException.ENTRY, + columnCounter); + + } if (parts.length < 2) { throw new MetadataImportInvalidHeadingException(element, @@ -223,6 +232,15 @@ public DSpaceCSV(InputStream inputStream, Context c) throws Exception { } } + // Verify there isn’t already a header that is the same; if it already exists, + // throw MetadataImportInvalidHeadingException + String header = authorityPrefix + element; + if (headings.contains(header)) { + throw new MetadataImportInvalidHeadingException("Duplicate heading found: " + header, + MetadataImportInvalidHeadingException.ENTRY, + columnCounter); + } + // Store the heading headings.add(authorityPrefix + element); } diff --git a/dspace-api/src/main/java/org/dspace/content/Collection.java b/dspace-api/src/main/java/org/dspace/content/Collection.java index 22293dd35ffc..33692d04b3d1 100644 --- a/dspace-api/src/main/java/org/dspace/content/Collection.java +++ b/dspace-api/src/main/java/org/dspace/content/Collection.java @@ -229,7 +229,7 @@ public String getLicenseCollection() { * @throws SQLException if database error */ public void setLicense(Context context, String license) throws SQLException { - getCollectionService().setMetadataSingleValue(context, this, MD_LICENSE, Item.ANY, license); + getCollectionService().setMetadataSingleValue(context, this, MD_LICENSE, null, license); } /** diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataValue.java b/dspace-api/src/main/java/org/dspace/content/MetadataValue.java index 279bdd67c243..dc45579f4ef9 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataValue.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataValue.java @@ -19,6 +19,7 @@ import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import jakarta.persistence.Transient; +import org.apache.commons.lang3.StringUtils; import org.dspace.core.Context; import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; @@ -139,6 +140,9 @@ public String getLanguage() { * @param language new language */ public void setLanguage(String language) { + if (StringUtils.equals(language, Item.ANY)) { + language = null; + } this.language = language; } diff --git a/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataImportIT.java b/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataImportIT.java index ae079df560ed..de1dcc91c9a1 100644 --- a/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataImportIT.java +++ b/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataImportIT.java @@ -75,6 +75,31 @@ public void setUp() throws Exception { context.restoreAuthSystemState(); } + @Test + public void metadataImportTestWithDuplicateHeader() { + String[] csv = {"id,collection,dc.title,dc.title,dc.contributor.author", + "+," + collection.getHandle() + ",\"Test Import 1\",\"Test Import 2\"," + "\"Donald, SmithImported\"," + + "+," + collection.getHandle() + ",\"Test Import 3\",\"Test Import 4\"," + "\"Donald, SmithImported\""}; + // Should throw an exception because of duplicate header + try { + performImportScript(csv); + } catch (Exception e) { + assertTrue(e instanceof MetadataImportInvalidHeadingException); + } + } + + @Test + public void metadataImportTestWithAnyLanguage() { + String[] csv = {"id,collection,dc.title[*],dc.contributor.author", + "+," + collection.getHandle() + ",\"Test Import 1\"," + "\"Donald, SmithImported\""}; + // Should throw an exception because of invalid ANY language (*) in metadata field + try { + performImportScript(csv); + } catch (Exception e) { + assertTrue(e instanceof MetadataImportInvalidHeadingException); + } + } + @Test public void metadataImportTest() throws Exception { String[] csv = {"id,collection,dc.title,dc.contributor.author", @@ -230,7 +255,7 @@ public void metadataImportRemovingValueTest() throws Exception { itemService.getMetadata(item, "dc", "contributor", "author", Item.ANY).get(0).getValue(), "TestAuthorToRemove")); - String[] csv = {"id,collection,dc.title,dc.contributor.author[*]", + String[] csv = {"id,collection,dc.title,dc.contributor.author", item.getID().toString() + "," + personCollection.getHandle() + "," + item.getName() + ","}; performImportScript(csv); item = findItemByName(itemTitle); diff --git a/dspace-api/src/test/java/org/dspace/builder/AbstractDSpaceObjectBuilder.java b/dspace-api/src/test/java/org/dspace/builder/AbstractDSpaceObjectBuilder.java index e7ebd8768e7d..fa7306ad9955 100644 --- a/dspace-api/src/test/java/org/dspace/builder/AbstractDSpaceObjectBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/AbstractDSpaceObjectBuilder.java @@ -18,7 +18,6 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; import org.dspace.content.DSpaceObject; -import org.dspace.content.Item; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Constants; import org.dspace.core.Context; @@ -103,7 +102,7 @@ protected > B setMetadataSingleValue(fi final String qualifier, final String value) { try { - getService().setMetadataSingleValue(context, dso, schema, element, qualifier, Item.ANY, value); + getService().setMetadataSingleValue(context, dso, schema, element, qualifier, null, value); } catch (Exception e) { return handleException(e); } diff --git a/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java b/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java index 54ff9ce02624..be670d9b5097 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java @@ -141,37 +141,37 @@ public void testCompare() throws SQLException { assertTrue("testCompare 0", result == 0); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 1", result >= 1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 2", result <= -1); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); //value in both items ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "2"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "2"); result = ic.compare(one, two); assertTrue("testCompare 3", result <= -1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 4", result == 0); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 5", result >= 1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); @@ -179,60 +179,60 @@ public void testCompare() throws SQLException { //multiple values (min, max) ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "0"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "3"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "0"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "3"); result = ic.compare(one, two); assertTrue("testCompare 3", result <= -1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "0"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "-1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "0"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "-1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); result = ic.compare(one, two); assertTrue("testCompare 4", result == 0); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, true); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "-1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "-1"); result = ic.compare(one, two); assertTrue("testCompare 5", result >= 1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, false); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "3"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "3"); result = ic.compare(one, two); assertTrue("testCompare 3", result <= -1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, false); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "5"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "5"); result = ic.compare(one, two); assertTrue("testCompare 4", result == 0); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); itemService.clearMetadata(context, two, "dc", "test", "one", Item.ANY); ic = new ItemComparator("test", "one", Item.ANY, false); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "2"); - itemService.addMetadata(context, one, "dc", "test", "one", Item.ANY, "3"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "1"); - itemService.addMetadata(context, two, "dc", "test", "one", Item.ANY, "4"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "2"); + itemService.addMetadata(context, one, "dc", "test", "one", null, "3"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "1"); + itemService.addMetadata(context, two, "dc", "test", "one", null, "4"); result = ic.compare(one, two); assertTrue("testCompare 5", result >= 1); itemService.clearMetadata(context, one, "dc", "test", "one", Item.ANY); diff --git a/dspace-api/src/test/java/org/dspace/content/ItemTest.java b/dspace-api/src/test/java/org/dspace/content/ItemTest.java index aaa28769dca6..0ba1136d8f0a 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemTest.java @@ -518,11 +518,11 @@ public void testAddMetadata_5args_1() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; String[] values = {"value0", "value1"}; itemService.addMetadata(context, it, schema, element, qualifier, lang, Arrays.asList(values)); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_5args_1 0", dc, notNullValue()); assertTrue("testAddMetadata_5args_1 1", dc.size() == 2); assertThat("testAddMetadata_5args_1 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -563,13 +563,13 @@ public void testAddMetadata_7args_1_authority() String schema = "dc"; String element = "language"; String qualifier = "iso"; - String lang = Item.ANY; + String lang = null; List values = Arrays.asList("en_US", "en"); List authorities = Arrays.asList("accepted", "uncertain"); List confidences = Arrays.asList(0, 0); itemService.addMetadata(context, it, schema, element, qualifier, lang, values, authorities, confidences); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_7args_1 0", dc, notNullValue()); assertTrue("testAddMetadata_7args_1 1", dc.size() == 2); assertThat("testAddMetadata_7args_1 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -600,13 +600,13 @@ public void testAddMetadata_7args_1_noauthority() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; List values = Arrays.asList("value0", "value1"); List authorities = Arrays.asList("auth0", "auth2"); List confidences = Arrays.asList(0, 0); itemService.addMetadata(context, it, schema, element, qualifier, lang, values, authorities, confidences); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_7args_1 0", dc, notNullValue()); assertTrue("testAddMetadata_7args_1 1", dc.size() == 2); assertThat("testAddMetadata_7args_1 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -719,13 +719,13 @@ public void testAddMetadata_7args_2_authority() throws SQLException { String schema = "dc"; String element = "language"; String qualifier = "iso"; - String lang = Item.ANY; + String lang = null; String values = "en"; String authorities = "accepted"; int confidences = 0; itemService.addMetadata(context, it, schema, element, qualifier, lang, values, authorities, confidences); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_7args_2 0", dc, notNullValue()); assertTrue("testAddMetadata_7args_2 1", dc.size() == 1); assertThat("testAddMetadata_7args_2 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -748,13 +748,13 @@ public void testAddMetadata_7args_2_noauthority() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "editor"; - String lang = Item.ANY; + String lang = null; String values = "value0"; String authorities = "auth0"; int confidences = 0; itemService.addMetadata(context, it, schema, element, qualifier, lang, values, authorities, confidences); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_7args_2 0", dc, notNullValue()); assertTrue("testAddMetadata_7args_2 1", dc.size() == 1); assertThat("testAddMetadata_7args_2 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -811,13 +811,13 @@ public void testClearMetadata() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; String values = "value0"; itemService.addMetadata(context, it, schema, element, qualifier, lang, values); - itemService.clearMetadata(context, it, schema, element, qualifier, lang); + itemService.clearMetadata(context, it, schema, element, qualifier, Item.ANY); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testClearMetadata 0", dc, notNullValue()); assertTrue("testClearMetadata 1", dc.size() == 0); } @@ -859,11 +859,11 @@ public void testGetCollections() throws Exception { context.turnOffAuthorisationSystem(); Collection collection = collectionService.create(context, owningCommunity); collectionService.setMetadataSingleValue(context, collection, MetadataSchemaEnum.DC.getName(), - "title", null, Item.ANY, "collection B"); + "title", null, null, "collection B"); it.addCollection(collection); collection = collectionService.create(context, owningCommunity); collectionService.setMetadataSingleValue(context, collection, MetadataSchemaEnum.DC.getName(), - "title", null, Item.ANY, "collection A"); + "title", null, null, "collection A"); it.addCollection(collection); context.restoreAuthSystemState(); assertThat("testGetCollections 0", it.getCollections(), notNullValue()); @@ -1772,7 +1772,7 @@ public void testFindByMetadataField() throws Exception { // add new metadata to item context.turnOffAuthorisationSystem(); - itemService.addMetadata(context, it, schema, element, qualifier, Item.ANY, value); + itemService.addMetadata(context, it, schema, element, qualifier, null, value); itemService.update(context, it); context.restoreAuthSystemState(); @@ -1837,7 +1837,7 @@ public void testFindByAuthorityValue() throws Exception { // add new metadata (with authority) to item context.turnOffAuthorisationSystem(); - itemService.addMetadata(context, it, schema, element, qualifier, Item.ANY, value, authority, confidence); + itemService.addMetadata(context, it, schema, element, qualifier, null, value, authority, confidence); itemService.update(context, it); context.restoreAuthSystemState(); diff --git a/dspace-api/src/test/java/org/dspace/content/dao/RelationshipDAOImplIT.java b/dspace-api/src/test/java/org/dspace/content/dao/RelationshipDAOImplIT.java index 2d08223b2e3e..20710ab5f25b 100644 --- a/dspace-api/src/test/java/org/dspace/content/dao/RelationshipDAOImplIT.java +++ b/dspace-api/src/test/java/org/dspace/content/dao/RelationshipDAOImplIT.java @@ -87,8 +87,8 @@ public void init() { WorkspaceItem workspaceItemTwo = workspaceItemService.create(context, collection, false); itemOne = installItemService.installItem(context, workspaceItem); itemTwo = installItemService.installItem(context, workspaceItemTwo); - itemService.addMetadata(context, itemOne, "dspace", "entity", "type", Item.ANY, "Publication"); - itemService.addMetadata(context, itemTwo, "dspace", "entity", "type", Item.ANY, "Person"); + itemService.addMetadata(context, itemOne, "dspace", "entity", "type", null, "Publication"); + itemService.addMetadata(context, itemTwo, "dspace", "entity", "type", null, "Person"); itemService.update(context, itemOne); itemService.update(context, itemTwo); entityTypeOne = entityTypeService.create(context, "Person"); diff --git a/dspace-api/src/test/java/org/dspace/content/dao/RelationshipTypeDAOImplIT.java b/dspace-api/src/test/java/org/dspace/content/dao/RelationshipTypeDAOImplIT.java index ff7d03b49f6d..d76e5faa804a 100644 --- a/dspace-api/src/test/java/org/dspace/content/dao/RelationshipTypeDAOImplIT.java +++ b/dspace-api/src/test/java/org/dspace/content/dao/RelationshipTypeDAOImplIT.java @@ -82,8 +82,8 @@ public void init() { WorkspaceItem workspaceItemTwo = workspaceItemService.create(context, collection, false); itemOne = installItemService.installItem(context, workspaceItem); itemTwo = installItemService.installItem(context, workspaceItemTwo); - itemService.addMetadata(context, itemOne, "dspace", "entity", "type", Item.ANY, "Publication"); - itemService.addMetadata(context, itemTwo, "dspace", "entity", "type", Item.ANY, "Person"); + itemService.addMetadata(context, itemOne, "dspace", "entity", "type", null, "Publication"); + itemService.addMetadata(context, itemTwo, "dspace", "entity", "type", null, "Person"); itemService.update(context, itemOne); itemService.update(context, itemTwo); entityTypeOne = entityTypeService.create(context, "Person"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java index eec7ce95f8d4..9b9db41a7c92 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java @@ -261,7 +261,7 @@ private void initSimplePublicationItem() throws Exception { for (String author : authorsOriginalOrder) { itemService.addMetadata( - context, publicationItem, "dc", "contributor", "author", Item.ANY, author + context, publicationItem, "dc", "contributor", "author", null, author ); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java index 641f30149b73..1bf4e2f41202 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java @@ -818,7 +818,7 @@ public void addRelationshipsAndMetadataToValidatePlaceTest() throws Exception { // Make sure we grab the latest instance of the Item from the database publication1 = itemService.find(context, publication1.getID()); // Add a plain text dc.contributor.author value - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text"); itemService.update(context, publication1); List list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -884,7 +884,7 @@ public void addRelationshipsAndMetadataToValidatePlaceTest() throws Exception { // Ensure we have the latest instance of the Item from the database publication1 = itemService.find(context, publication1.getID()); // Add a fourth dc.contributor.author mdv - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text two"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text two"); itemService.update(context, publication1); context.restoreAuthSystemState(); @@ -953,7 +953,7 @@ public void addRelationshipsAndMetadataToValidatePlaceTest() throws Exception { context.turnOffAuthorisationSystem(); // The following additions of Metadata will perform the same sequence of logic and tests as described above publication1 = itemService.find(context, publication1.getID()); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text three"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text three"); itemService.update(context, publication1); context.restoreAuthSystemState(); @@ -983,10 +983,10 @@ public void addRelationshipsAndMetadataToValidatePlaceTest() throws Exception { context.turnOffAuthorisationSystem(); publication1 = itemService.find(context, publication1.getID()); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text four"); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text five"); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text six"); - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text seven"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text four"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text five"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text six"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text seven"); itemService.update(context, publication1); context.restoreAuthSystemState(); @@ -1114,7 +1114,7 @@ public void deleteMetadataValueAndValidatePlace() throws Exception { publication1 = itemService.find(context, publication1.getID()); // Add a plain text metadatavalue to the publication // After this addition, the list of authors should like like "Donald Smith", "plain text" - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text"); itemService.update(context, publication1); context.restoreAuthSystemState(); List list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1157,7 +1157,7 @@ public void deleteMetadataValueAndValidatePlace() throws Exception { // Get the publication from the DB again to ensure that we have the latest object publication1 = itemService.find(context, publication1.getID()); // Add a fourth metadata value to the publication - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text two"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text two"); itemService.update(context, publication1); context.restoreAuthSystemState(); list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1195,7 +1195,7 @@ public void deleteMetadataValueAndValidatePlace() throws Exception { context.turnOffAuthorisationSystem(); publication1 = itemService.find(context, publication1.getID()); // Create another plain text metadata value on the publication - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text three"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text three"); itemService.update(context, publication1); context.restoreAuthSystemState(); list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1323,7 +1323,7 @@ public void deleteRelationshipsAndValidatePlace() throws Exception { publication1 = itemService.find(context, publication1.getID()); // Add a plain text metadatavalue to the publication // After this addition, the list of authors should like like "Donald Smith", "plain text" - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text"); itemService.update(context, publication1); context.restoreAuthSystemState(); List list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1367,7 +1367,7 @@ public void deleteRelationshipsAndValidatePlace() throws Exception { // Get the publication from the DB again to ensure that we have the latest object publication1 = itemService.find(context, publication1.getID()); // Add a fourth metadata value to the publication - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text two"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text two"); itemService.update(context, publication1); context.restoreAuthSystemState(); list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); @@ -1405,7 +1405,7 @@ public void deleteRelationshipsAndValidatePlace() throws Exception { context.turnOffAuthorisationSystem(); publication1 = itemService.find(context, publication1.getID()); // Create another plain text metadata value on the publication - itemService.addMetadata(context, publication1, "dc", "contributor", "author", Item.ANY, "plain text three"); + itemService.addMetadata(context, publication1, "dc", "contributor", "author", null, "plain text three"); itemService.update(context, publication1); context.restoreAuthSystemState(); list = itemService.getMetadata(publication1, "dc", "contributor", "author", Item.ANY); From c7696649af8da714e7469c843fb9a2afb14cf063 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 23 Jul 2024 12:16:28 +0200 Subject: [PATCH 024/632] 116542: resolve issues after merge with latest main branch (cherry picked from commit be179bad6ab25a96d4b43d3ef73a7c065557e266) --- .../test/java/org/dspace/content/ItemTest.java | 18 +++++++++--------- .../dspace/content/service/ItemServiceIT.java | 2 +- .../app/rest/EPersonRestRepositoryIT.java | 3 +-- .../controller/LinksetRestControllerIT.java | 4 ++-- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/ItemTest.java b/dspace-api/src/test/java/org/dspace/content/ItemTest.java index 0ba1136d8f0a..00dbf2994d98 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemTest.java @@ -544,7 +544,7 @@ public void testAddMetadata_5args_no_values() throws Exception { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; String[] values = {}; itemService.addMetadata(context, it, schema, element, qualifier, lang, Arrays.asList(values)); fail("IllegalArgumentException expected"); @@ -632,7 +632,7 @@ public void testAddMetadata_7args_no_values() throws Exception { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; List values = new ArrayList(); List authorities = new ArrayList(); List confidences = new ArrayList(); @@ -645,7 +645,7 @@ public void testAddMetadata_list_with_virtual_metadata() throws Exception { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; // Create two fake virtual metadata ("virtual::[relationship-id]") values List values = new ArrayList<>(Arrays.asList("uuid-1", "uuid-2")); List authorities = new ArrayList<>(Arrays.asList(Constants.VIRTUAL_AUTHORITY_PREFIX + "relationship-1", @@ -674,7 +674,7 @@ public void testAddMetadata_list_with_virtual_metadata() throws Exception { assertEquals(1, valuesAdded.size()); // Get metadata and ensure new value is the ONLY ONE for this metadata field - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertNotNull(dc); assertEquals(1, dc.size()); assertEquals(schema, dc.get(0).getMetadataField().getMetadataSchema().getName()); @@ -693,11 +693,11 @@ public void testAddMetadata_5args_2() throws SQLException { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; String value = "value0"; itemService.addMetadata(context, it, schema, element, qualifier, lang, value); - List dc = itemService.getMetadata(it, schema, element, qualifier, lang); + List dc = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertThat("testAddMetadata_5args_2 0", dc, notNullValue()); assertTrue("testAddMetadata_5args_2 1", dc.size() == 1); assertThat("testAddMetadata_5args_2 2", dc.get(0).getMetadataField().getMetadataSchema().getName(), @@ -772,7 +772,7 @@ public void testAddMetadata_single_virtual_metadata() throws Exception { String schema = "dc"; String element = "contributor"; String qualifier = "author"; - String lang = Item.ANY; + String lang = null; // Create a single fake virtual metadata ("virtual::[relationship-id]") value String value = "uuid-1"; String authority = Constants.VIRTUAL_AUTHORITY_PREFIX + "relationship-1"; @@ -786,7 +786,7 @@ public void testAddMetadata_single_virtual_metadata() throws Exception { assertNull(valuesAdded); // Verify this metadata field does NOT exist on the item - List mv = itemService.getMetadata(it, schema, element, qualifier, lang); + List mv = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertNotNull(mv); assertTrue(mv.isEmpty()); @@ -797,7 +797,7 @@ public void testAddMetadata_single_virtual_metadata() throws Exception { assertNull(valuesAdded); // Verify this metadata field does NOT exist on the item - mv = itemService.getMetadata(it, schema, element, qualifier, lang); + mv = itemService.getMetadata(it, schema, element, qualifier, Item.ANY); assertNotNull(mv); assertTrue(mv.isEmpty()); } diff --git a/dspace-api/src/test/java/org/dspace/content/service/ItemServiceIT.java b/dspace-api/src/test/java/org/dspace/content/service/ItemServiceIT.java index 0704c2d98d1c..eee445b3334f 100644 --- a/dspace-api/src/test/java/org/dspace/content/service/ItemServiceIT.java +++ b/dspace-api/src/test/java/org/dspace/content/service/ItemServiceIT.java @@ -198,7 +198,7 @@ public void preserveMetadataOrder() throws Exception { // now just add one metadata to be the last itemService.addMetadata( - context, item, dcSchema, contributorElement, authorQualifier, Item.ANY, "test, latest", null, 0 + context, item, dcSchema, contributorElement, authorQualifier, null, "test, latest", null, 0 ); // now just remove first metadata itemService.removeMetadataValues(context, item, List.of(placeZero)); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java index dfca8b4328f8..beeef03aec47 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java @@ -72,7 +72,6 @@ import org.dspace.builder.WorkflowItemBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; -import org.dspace.content.Item; import org.dspace.core.I18nUtil; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; @@ -2120,7 +2119,7 @@ public void patchMultipleReplaceMetadataByAdmin() throws Exception { .build(); this.ePersonService - .addMetadata(context, ePerson, "eperson", "firstname", null, Item.ANY, List.of(first, second, third)); + .addMetadata(context, ePerson, "eperson", "firstname", null, null, List.of(first, second, third)); context.restoreAuthSystemState(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/signposting/controller/LinksetRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/signposting/controller/LinksetRestControllerIT.java index c5873dd53f42..cf62d5ac0861 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/signposting/controller/LinksetRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/signposting/controller/LinksetRestControllerIT.java @@ -748,7 +748,7 @@ public void findTypedLinkForBitstreamWithType() throws Exception { .withMimeType(bitstreamMimeType) .build(); } - bitstreamService.addMetadata(context, bitstream, "dc", "type", null, Item.ANY, "Article"); + bitstreamService.addMetadata(context, bitstream, "dc", "type", null, null, "Article"); context.restoreAuthSystemState(); @@ -836,7 +836,7 @@ public void findTypedLinkForBitstreamOfWorkspaceItem() throws Exception { .withTitle("Workspace Item") .build(); Item item = workspaceItem.getItem(); - itemService.addMetadata(context, item, "dc", "identifier", "doi", Item.ANY, doi); + itemService.addMetadata(context, item, "dc", "identifier", "doi", null, doi); Bitstream bitstream = null; try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) { From 24318e01b84ec7ef3c2b7081bc5a85ab10295209 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 14:12:53 +0200 Subject: [PATCH 025/632] fix invalid usage of == operator (cherry picked from commit fa0fb14a185ba8a9c593a3653df302f0446a397c) --- .../src/main/java/org/dspace/content/ItemServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index ac6c0d43d710..b2cc3e939d87 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -1788,7 +1788,7 @@ protected void moveSingleMetadataValue(Context context, Item dso, int place, Met //Retrieve the applicable relationship Relationship rs = relationshipService.find(context, ((RelationshipMetadataValue) rr).getRelationshipId()); - if (rs.getLeftItem() == dso) { + if (rs.getLeftItem().equals(dso)) { rs.setLeftPlace(place); } else { rs.setRightPlace(place); From 74d032732298cb372f6ad22cf26ac88488e49a74 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 14:12:53 +0200 Subject: [PATCH 026/632] fix invalid usage of == operator (cherry picked from commit fa0fb14a185ba8a9c593a3653df302f0446a397c) --- .../src/main/java/org/dspace/content/ItemServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index 70bdf4b7d950..cceb954ebe2f 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -1799,7 +1799,7 @@ protected void moveSingleMetadataValue(Context context, Item dso, int place, Met //Retrieve the applicable relationship Relationship rs = relationshipService.find(context, ((RelationshipMetadataValue) rr).getRelationshipId()); - if (rs.getLeftItem() == dso) { + if (rs.getLeftItem().equals(dso)) { rs.setLeftPlace(place); } else { rs.setRightPlace(place); From b8f638b3b6eff9c0138dcfe883a9083599a2ffa7 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 17:44:35 +0200 Subject: [PATCH 027/632] use equals instead of == (cherry picked from commit 80de8f6fb567ceb4497596fa714f2b357f1b8b26) --- .../src/main/java/org/dspace/content/EntityServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java index 2f34129f2e69..6049b7e6aae8 100644 --- a/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java @@ -64,7 +64,7 @@ public List getLeftRelations(Context context, Entity entity) { List fullList = entity.getRelationships(); List listToReturn = new LinkedList<>(); for (Relationship relationship : fullList) { - if (relationship.getLeftItem().getID() == entity.getItem().getID()) { + if (relationship.getLeftItem().getID().equals(entity.getItem().getID())) { listToReturn.add(relationship); } } @@ -76,7 +76,7 @@ public List getRightRelations(Context context, Entity entity) { List fullList = entity.getRelationships(); List listToReturn = new LinkedList<>(); for (Relationship relationship : fullList) { - if (relationship.getRightItem().getID() == entity.getItem().getID()) { + if (relationship.getRightItem().getID().equals(entity.getItem().getID())) { listToReturn.add(relationship); } } From dc09d06ed6eedc89249fad5230f5346a830bbe41 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 17:47:07 +0200 Subject: [PATCH 028/632] use equals instead of == (cherry picked from commit 5e3552ee3885049df34c3fcaf49bfe3028c5dbd0) --- .../java/org/dspace/authorize/ResourcePolicyServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java index 7b93b912378e..86998a2196e7 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java @@ -417,7 +417,7 @@ public boolean isMyResourcePolicy(Context context, EPerson eperson, Integer id) ResourcePolicy resourcePolicy = resourcePolicyDAO.findOneById(context, id); Group group = resourcePolicy.getGroup(); - if (resourcePolicy.getEPerson() != null && resourcePolicy.getEPerson().getID() == eperson.getID()) { + if (resourcePolicy.getEPerson() != null && resourcePolicy.getEPerson().getID().equals(eperson.getID())) { isMy = true; } else if (group != null && groupService.isMember(context, eperson, group)) { isMy = true; From 6a5236f2f93a05999bfa391887ecb22f8bfae257 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 17:48:28 +0200 Subject: [PATCH 029/632] use equals instead of == (cherry picked from commit d2ef7b01ef1a5d769d764b708be393dbb481fb65) --- .../src/main/java/org/dspace/eperson/GroupServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java index 730053e42ce2..3fb20e2f1e6f 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java @@ -147,7 +147,7 @@ public void addMember(Context context, Group group, EPerson e) { public void addMember(Context context, Group groupParent, Group groupChild) throws SQLException { // don't add if it's already a member // and don't add itself - if (groupParent.contains(groupChild) || groupParent.getID() == groupChild.getID()) { + if (groupParent.contains(groupChild) || groupParent.getID().equals(groupChild.getID())) { return; } @@ -178,7 +178,7 @@ public void removeMember(Context context, Group group, EPerson ePerson) throws S Role role = stepByName.getRole(); for (CollectionRole collectionRole : collectionRoles) { if (StringUtils.equals(collectionRole.getRoleId(), role.getId()) - && claimedTask.getWorkflowItem().getCollection() == collectionRole.getCollection()) { + && claimedTask.getWorkflowItem().getCollection().equals(collectionRole.getCollection())) { // Count number of EPersons who are *direct* members of this group int totalDirectEPersons = ePersonService.countByGroups(context, Set.of(group)); // Count number of Groups which have this groupParent as a direct parent From 36ff5ca6cbc6a8641555f9267e06884f9112badc Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 17:49:14 +0200 Subject: [PATCH 030/632] use equals instead of == (cherry picked from commit a13cc82d405c5aefe00c7bb86d89c7dc8073a39b) --- .../submit/factory/impl/ItemMetadataValueAddPatchOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java index e749c4e79328..a7cd5bfc1de3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java @@ -213,7 +213,7 @@ private Integer getRelId(String authority) { private void updateRelationshipPlace(Context context, Item dso, int place, Relationship rs) { try { - if (rs.getLeftItem() == dso) { + if (rs.getLeftItem().equals(dso)) { rs.setLeftPlace(place); } else { rs.setRightPlace(place); From 19daa72ff40cd172721776f795ff86b028b38c04 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 17:44:35 +0200 Subject: [PATCH 031/632] use equals instead of == (cherry picked from commit 80de8f6fb567ceb4497596fa714f2b357f1b8b26) --- .../src/main/java/org/dspace/content/EntityServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java index 9b28203827e0..e83178667840 100644 --- a/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java @@ -60,7 +60,7 @@ public List getLeftRelations(Context context, Entity entity) { List fullList = entity.getRelationships(); List listToReturn = new LinkedList<>(); for (Relationship relationship : fullList) { - if (relationship.getLeftItem().getID() == entity.getItem().getID()) { + if (relationship.getLeftItem().getID().equals(entity.getItem().getID())) { listToReturn.add(relationship); } } @@ -72,7 +72,7 @@ public List getRightRelations(Context context, Entity entity) { List fullList = entity.getRelationships(); List listToReturn = new LinkedList<>(); for (Relationship relationship : fullList) { - if (relationship.getRightItem().getID() == entity.getItem().getID()) { + if (relationship.getRightItem().getID().equals(entity.getItem().getID())) { listToReturn.add(relationship); } } From 7b08fdfe9e4b7c3c572fcfba3a14695f1c40164f Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 17:47:07 +0200 Subject: [PATCH 032/632] use equals instead of == (cherry picked from commit 5e3552ee3885049df34c3fcaf49bfe3028c5dbd0) --- .../java/org/dspace/authorize/ResourcePolicyServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java index 7b93b912378e..86998a2196e7 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java @@ -417,7 +417,7 @@ public boolean isMyResourcePolicy(Context context, EPerson eperson, Integer id) ResourcePolicy resourcePolicy = resourcePolicyDAO.findOneById(context, id); Group group = resourcePolicy.getGroup(); - if (resourcePolicy.getEPerson() != null && resourcePolicy.getEPerson().getID() == eperson.getID()) { + if (resourcePolicy.getEPerson() != null && resourcePolicy.getEPerson().getID().equals(eperson.getID())) { isMy = true; } else if (group != null && groupService.isMember(context, eperson, group)) { isMy = true; From f0ea00b5cd4c4c9120eb1e744ae11d0ad0977ec0 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 17:48:28 +0200 Subject: [PATCH 033/632] use equals instead of == (cherry picked from commit d2ef7b01ef1a5d769d764b708be393dbb481fb65) --- .../src/main/java/org/dspace/eperson/GroupServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java index 730053e42ce2..3fb20e2f1e6f 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java @@ -147,7 +147,7 @@ public void addMember(Context context, Group group, EPerson e) { public void addMember(Context context, Group groupParent, Group groupChild) throws SQLException { // don't add if it's already a member // and don't add itself - if (groupParent.contains(groupChild) || groupParent.getID() == groupChild.getID()) { + if (groupParent.contains(groupChild) || groupParent.getID().equals(groupChild.getID())) { return; } @@ -178,7 +178,7 @@ public void removeMember(Context context, Group group, EPerson ePerson) throws S Role role = stepByName.getRole(); for (CollectionRole collectionRole : collectionRoles) { if (StringUtils.equals(collectionRole.getRoleId(), role.getId()) - && claimedTask.getWorkflowItem().getCollection() == collectionRole.getCollection()) { + && claimedTask.getWorkflowItem().getCollection().equals(collectionRole.getCollection())) { // Count number of EPersons who are *direct* members of this group int totalDirectEPersons = ePersonService.countByGroups(context, Set.of(group)); // Count number of Groups which have this groupParent as a direct parent From ef5479d77a6f61039caf000b97c5bbceeaff30a0 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 2 Aug 2024 17:49:14 +0200 Subject: [PATCH 034/632] use equals instead of == (cherry picked from commit a13cc82d405c5aefe00c7bb86d89c7dc8073a39b) --- .../submit/factory/impl/ItemMetadataValueAddPatchOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java index 54dfa6b02c04..8ab9bb451647 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java @@ -214,7 +214,7 @@ private Integer getRelId(String authority) { private void updateRelationshipPlace(Context context, Item dso, int place, Relationship rs) { try { - if (rs.getLeftItem() == dso) { + if (rs.getLeftItem().equals(dso)) { rs.setLeftPlace(place); } else { rs.setRightPlace(place); From 408e8b608f3a5da9bd688c1bb128ecd93552b599 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 4 Aug 2024 10:56:32 +0200 Subject: [PATCH 035/632] README.md: v8 is the current release, not v7 (cherry picked from commit 2b698eff609d510c487ad2331d4e11cd28f64e9a) --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index af9158eff361..2305643fd8e1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Overview -DSpace open source software is a turnkey repository application used by more than +DSpace open-source software is a turnkey repository application used by more than 2,000 organizations and institutions worldwide to provide durable access to digital resources. For more information, visit http://www.dspace.org/ @@ -20,7 +20,7 @@ DSpace consists of both a Java-based backend and an Angular-based frontend. * The REST Contract is at https://github.com/DSpace/RestContract * Frontend (https://github.com/DSpace/dspace-angular/) is the User Interface built on the REST API -Prior versions of DSpace (v6.x and below) used two different UIs (XMLUI and JSPUI). Those UIs are no longer supported in v7 (and above). +Prior versions of DSpace (v6.x and below) used two different UIs (XMLUI and JSPUI). Those UIs are no longer supported in v7 and above. * A maintenance branch for older versions is still available, see `dspace-6_x` for 6.x maintenance. ## Downloads @@ -33,18 +33,18 @@ Prior versions of DSpace (v6.x and below) used two different UIs (XMLUI and JSPU Documentation for each release may be viewed online or downloaded via our [Documentation Wiki](https://wiki.lyrasis.org/display/DSDOC/). The latest DSpace Installation instructions are available at: -https://wiki.lyrasis.org/display/DSDOC7x/Installing+DSpace +https://wiki.lyrasis.org/display/DSDOC8x/Installing+DSpace Please be aware that, as a Java web application, DSpace requires a database (PostgreSQL) and a servlet container (usually Tomcat) in order to function. More information about these and all other prerequisites can be found in the Installation instructions above. -## Running DSpace 7 in Docker +## Running DSpace 8 in Docker NOTE: At this time, we do not have production-ready Docker images for DSpace. That said, we do have quick-start Docker Compose scripts for development or testing purposes. -See [Running DSpace 7 with Docker Compose](dspace/src/main/docker-compose/README.md) +See [Running DSpace 8 with Docker Compose](dspace/src/main/docker-compose/README.md) ## Contributing @@ -64,7 +64,7 @@ Great Q&A is also available under the [DSpace tag on Stackoverflow](http://stack Additional support options are at https://wiki.lyrasis.org/display/DSPACE/Support DSpace also has an active service provider network. If you'd rather hire a service provider to -install, upgrade, customize or host DSpace, then we recommend getting in touch with one of our +install, upgrade, customize, or host DSpace, then we recommend getting in touch with one of our [Registered Service Providers](http://www.dspace.org/service-providers). ## Issue Tracker @@ -112,7 +112,7 @@ run automatically by [GitHub Actions](https://github.com/DSpace/DSpace/actions?q ``` * How to run only tests of a specific DSpace module ``` - # Before you can run only one module's tests, other modules may need installing into your ~/.m2 + # Before you can run only one module's tests, other modules may need to be installed into your ~/.m2 cd [dspace-src] mvn clean install From 98dee8c2fcdc89263b95b1bacf56a947bdeb93c9 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 4 Aug 2024 11:04:12 +0200 Subject: [PATCH 036/632] Update README.md (cherry picked from commit 671234b08f909810d798dd950f87d1818b098363) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2305643fd8e1..1d93abe49948 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Overview -DSpace open-source software is a turnkey repository application used by more than +DSpace open source software is a turnkey repository application used by more than 2,000 organizations and institutions worldwide to provide durable access to digital resources. For more information, visit http://www.dspace.org/ From f1dc25195f025919aa18cc390ad81459c3698169 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 18 Jun 2024 13:52:38 +0200 Subject: [PATCH 037/632] 115693: data-cite xsl targetting dc.identifier.uri fixes doi registration error (cherry picked from commit c5d08f037cb56111b8ef047279f323c06b11a864) --- .../main/java/org/dspace/identifier/DOIIdentifierProvider.java | 1 + dspace/config/crosswalks/DIM2DataCite.xsl | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java index b70eda960d35..8d71ac92f9d1 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java @@ -70,6 +70,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider { static final char SLASH = '/'; // Metadata field name elements + // Warning: If this metadata field is changed for whatever reason, DIM2DataCite.xsl's template needs to reflect this // TODO: move these to MetadataSchema or some such? public static final String MD_SCHEMA = "dc"; public static final String DOI_ELEMENT = "identifier"; diff --git a/dspace/config/crosswalks/DIM2DataCite.xsl b/dspace/config/crosswalks/DIM2DataCite.xsl index a97d127694ef..d57996e6d8cf 100644 --- a/dspace/config/crosswalks/DIM2DataCite.xsl +++ b/dspace/config/crosswalks/DIM2DataCite.xsl @@ -333,7 +333,8 @@ company as well. We have to ensure to use URIs of our prefix as primary identifiers only. --> - + + From d240a16b051326b0357cd8476928f899207ddc4c Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 27 Jun 2024 10:59:36 +0200 Subject: [PATCH 038/632] 115693: DataCiteConnector fallback for blank metadata doi (cherry picked from commit 021e42434731e505245b3aa149eaf59a5fbccb94) --- .../main/java/org/dspace/identifier/doi/DataCiteConnector.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index 57136d6143bb..fc4e2652ac2f 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -15,6 +15,7 @@ import java.util.Iterator; import java.util.Map; +import org.apache.commons.lang.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; @@ -412,7 +413,7 @@ public void reserveDOI(Context context, DSpaceObject dso, String doi) } String metadataDOI = extractDOI(root); - if (null == metadataDOI) { + if (StringUtils.isBlank(metadataDOI)) { // The DOI will be saved as metadata of dso after successful // registration. To register a doi it has to be part of the metadata // sent to DataCite. So we add it to the XML we'll send to DataCite From c1be5f8e4ed9577e22ce7b33bca3c171b84083cb Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 19 Jul 2024 13:42:09 +0200 Subject: [PATCH 039/632] 115693: Pass doi metadatafield with xsl parameters (cherry picked from commit 9e11e1f9ae69f19e506618d1d0b1fec0059ba165) --- .../identifier/DOIIdentifierProvider.java | 1 - .../identifier/doi/DataCiteConnector.java | 8 ++++++ dspace/config/crosswalks/DIM2DataCite.xsl | 25 +++++++++++-------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java index 8d71ac92f9d1..b70eda960d35 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java @@ -70,7 +70,6 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider { static final char SLASH = '/'; // Metadata field name elements - // Warning: If this metadata field is changed for whatever reason, DIM2DataCite.xsl's template needs to reflect this // TODO: move these to MetadataSchema or some such? public static final String MD_SCHEMA = "dc"; public static final String DOI_ELEMENT = "identifier"; diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index fc4e2652ac2f..a15e3f7fdbfe 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -7,6 +7,10 @@ */ package org.dspace.identifier.doi; +import static org.dspace.identifier.DOIIdentifierProvider.DOI_ELEMENT; +import static org.dspace.identifier.DOIIdentifierProvider.DOI_QUALIFIER; +import static org.dspace.identifier.DOIIdentifierProvider.MD_SCHEMA; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.URISyntaxException; @@ -386,6 +390,10 @@ public void reserveDOI(Context context, DSpaceObject dso, String doi) parameters.put("hostinginstitution", configurationService.getProperty(CFG_HOSTINGINSTITUTION)); } + parameters.put("mdSchema", MD_SCHEMA); + parameters.put("mdElement", DOI_ELEMENT); + // Pass an empty string for qualifier if the metadata field doesn't have any + parameters.put("mdQualifier", DOI_QUALIFIER); Element root = null; try { diff --git a/dspace/config/crosswalks/DIM2DataCite.xsl b/dspace/config/crosswalks/DIM2DataCite.xsl index d57996e6d8cf..d4d8cbe6417a 100644 --- a/dspace/config/crosswalks/DIM2DataCite.xsl +++ b/dspace/config/crosswalks/DIM2DataCite.xsl @@ -36,6 +36,10 @@ + + dc + identifier + uri @@ -333,16 +337,17 @@ company as well. We have to ensure to use URIs of our prefix as primary identifiers only. --> - - - - - - - - - - + + + + + + + + + + + From d35946af0a9abbc5dd0bc17f783d376a7fa66f96 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 18 Jun 2024 13:52:38 +0200 Subject: [PATCH 040/632] 115693: data-cite xsl targetting dc.identifier.uri fixes doi registration error (cherry picked from commit c5d08f037cb56111b8ef047279f323c06b11a864) --- .../main/java/org/dspace/identifier/DOIIdentifierProvider.java | 1 + dspace/config/crosswalks/DIM2DataCite.xsl | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java index ae31e54f7e96..aff4666fff4b 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java @@ -70,6 +70,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider { static final char SLASH = '/'; // Metadata field name elements + // Warning: If this metadata field is changed for whatever reason, DIM2DataCite.xsl's template needs to reflect this // TODO: move these to MetadataSchema or some such? public static final String MD_SCHEMA = "dc"; public static final String DOI_ELEMENT = "identifier"; diff --git a/dspace/config/crosswalks/DIM2DataCite.xsl b/dspace/config/crosswalks/DIM2DataCite.xsl index a97d127694ef..d57996e6d8cf 100644 --- a/dspace/config/crosswalks/DIM2DataCite.xsl +++ b/dspace/config/crosswalks/DIM2DataCite.xsl @@ -333,7 +333,8 @@ company as well. We have to ensure to use URIs of our prefix as primary identifiers only. --> - + + From acec968e940ca69c4eb28afe9512493a0690a4e3 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 27 Jun 2024 10:59:36 +0200 Subject: [PATCH 041/632] 115693: DataCiteConnector fallback for blank metadata doi (cherry picked from commit 021e42434731e505245b3aa149eaf59a5fbccb94) --- .../main/java/org/dspace/identifier/doi/DataCiteConnector.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index 931f1538583e..0fbac1a9f52b 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -15,6 +15,7 @@ import java.util.Iterator; import java.util.Map; +import org.apache.commons.lang.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; @@ -410,7 +411,7 @@ public void reserveDOI(Context context, DSpaceObject dso, String doi) } String metadataDOI = extractDOI(root); - if (null == metadataDOI) { + if (StringUtils.isBlank(metadataDOI)) { // The DOI will be saved as metadata of dso after successful // registration. To register a doi it has to be part of the metadata // sent to DataCite. So we add it to the XML we'll send to DataCite From cd8961bc0573edaf788fcc45aba8bcc2c38d91e2 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 19 Jul 2024 13:42:09 +0200 Subject: [PATCH 042/632] 115693: Pass doi metadatafield with xsl parameters (cherry picked from commit 9e11e1f9ae69f19e506618d1d0b1fec0059ba165) --- .../identifier/DOIIdentifierProvider.java | 1 - .../identifier/doi/DataCiteConnector.java | 8 ++++++ dspace/config/crosswalks/DIM2DataCite.xsl | 25 +++++++++++-------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java index aff4666fff4b..ae31e54f7e96 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java @@ -70,7 +70,6 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider { static final char SLASH = '/'; // Metadata field name elements - // Warning: If this metadata field is changed for whatever reason, DIM2DataCite.xsl's template needs to reflect this // TODO: move these to MetadataSchema or some such? public static final String MD_SCHEMA = "dc"; public static final String DOI_ELEMENT = "identifier"; diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index 0fbac1a9f52b..b4cdac96303a 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -7,6 +7,10 @@ */ package org.dspace.identifier.doi; +import static org.dspace.identifier.DOIIdentifierProvider.DOI_ELEMENT; +import static org.dspace.identifier.DOIIdentifierProvider.DOI_QUALIFIER; +import static org.dspace.identifier.DOIIdentifierProvider.MD_SCHEMA; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.URISyntaxException; @@ -384,6 +388,10 @@ public void reserveDOI(Context context, DSpaceObject dso, String doi) parameters.put("hostinginstitution", configurationService.getProperty(CFG_HOSTINGINSTITUTION)); } + parameters.put("mdSchema", MD_SCHEMA); + parameters.put("mdElement", DOI_ELEMENT); + // Pass an empty string for qualifier if the metadata field doesn't have any + parameters.put("mdQualifier", DOI_QUALIFIER); Element root = null; try { diff --git a/dspace/config/crosswalks/DIM2DataCite.xsl b/dspace/config/crosswalks/DIM2DataCite.xsl index d57996e6d8cf..d4d8cbe6417a 100644 --- a/dspace/config/crosswalks/DIM2DataCite.xsl +++ b/dspace/config/crosswalks/DIM2DataCite.xsl @@ -36,6 +36,10 @@ + + dc + identifier + uri @@ -333,16 +337,17 @@ company as well. We have to ensure to use URIs of our prefix as primary identifiers only. --> - - - - - - - - - - + + + + + + + + + + + From f61c45bdc6533f7328e84af9c59e908bc1b3e6e2 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 8 Jul 2024 19:26:11 +0200 Subject: [PATCH 043/632] change order of name parts: familyName, givenName (cherry picked from commit 076f1f233ea0eef1a37ed4087f34008d1e92e40a) --- .../external/crossref/CrossRefAuthorMetadataProcessor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAuthorMetadataProcessor.java b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAuthorMetadataProcessor.java index abf84f52d058..b9b384f8ed77 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAuthorMetadataProcessor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAuthorMetadataProcessor.java @@ -42,8 +42,8 @@ public Collection processMetadata(String json) { JsonNode author = authors.next(); String givenName = author.at("/given").textValue(); String familyName = author.at("/family").textValue(); - if (StringUtils.isNoneBlank(givenName) && StringUtils.isNoneBlank(familyName)) { - values.add(givenName + " " + familyName); + if (StringUtils.isNotBlank(givenName) && StringUtils.isNotBlank(familyName)) { + values.add(familyName.trim() + ", " + givenName.trim()); } } return values; @@ -64,4 +64,4 @@ public void setPathToArray(String pathToArray) { this.pathToArray = pathToArray; } -} \ No newline at end of file +} From 7e87d57672640e72c432f432fd07ad8a6f6aedc8 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 10:53:23 +0200 Subject: [PATCH 044/632] fix broken unit tests (cherry picked from commit 1712b9f07875c67141b67da96fa93f0deaff4090) --- .../app/rest/CrossRefImportMetadataSourceServiceIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java index 31c22692f008..f61a81140ddc 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java @@ -162,7 +162,7 @@ private ArrayList getRecords() { MetadatumDTO title = createMetadatumDTO("dc", "title", null, "State of Awareness of Freshers’ Groups Chortkiv State" + " Medical College of Prevention of Iodine Deficiency Diseases"); - MetadatumDTO author = createMetadatumDTO("dc", "contributor", "author", "L.V. Senyuk"); + MetadatumDTO author = createMetadatumDTO("dc", "contributor", "author", "Senyuk, L.V."); MetadatumDTO type = createMetadatumDTO("dc", "type", null, "journal-article"); MetadatumDTO date = createMetadatumDTO("dc", "date", "issued", "2016-05-19"); MetadatumDTO ispartof = createMetadatumDTO("dc", "relation", "ispartof", @@ -191,7 +191,7 @@ private ArrayList getRecords() { List metadatums2 = new ArrayList(); MetadatumDTO title2 = createMetadatumDTO("dc", "title", null, "Ischemic Heart Disease and Role of Nurse of Cardiology Department"); - MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "K. І. Kozak"); + MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "Kozak, K. І."); MetadatumDTO type2 = createMetadatumDTO("dc", "type", null, "journal-article"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2016-05-19"); MetadatumDTO ispartof2 = createMetadatumDTO("dc", "relation", "ispartof", From 65c452d3ef067cb1e28b68881ebcdf44a56e7ccf Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 8 Jul 2024 19:26:11 +0200 Subject: [PATCH 045/632] change order of name parts: familyName, givenName (cherry picked from commit 076f1f233ea0eef1a37ed4087f34008d1e92e40a) --- .../external/crossref/CrossRefAuthorMetadataProcessor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAuthorMetadataProcessor.java b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAuthorMetadataProcessor.java index abf84f52d058..b9b384f8ed77 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAuthorMetadataProcessor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAuthorMetadataProcessor.java @@ -42,8 +42,8 @@ public Collection processMetadata(String json) { JsonNode author = authors.next(); String givenName = author.at("/given").textValue(); String familyName = author.at("/family").textValue(); - if (StringUtils.isNoneBlank(givenName) && StringUtils.isNoneBlank(familyName)) { - values.add(givenName + " " + familyName); + if (StringUtils.isNotBlank(givenName) && StringUtils.isNotBlank(familyName)) { + values.add(familyName.trim() + ", " + givenName.trim()); } } return values; @@ -64,4 +64,4 @@ public void setPathToArray(String pathToArray) { this.pathToArray = pathToArray; } -} \ No newline at end of file +} From b6e1bcb30654d657958b766764319a4f1edfd1f7 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 10:53:23 +0200 Subject: [PATCH 046/632] fix broken unit tests (cherry picked from commit 1712b9f07875c67141b67da96fa93f0deaff4090) --- .../app/rest/CrossRefImportMetadataSourceServiceIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java index 863fd1f753d1..37bd3a90eeda 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java @@ -162,7 +162,7 @@ private ArrayList getRecords() { MetadatumDTO title = createMetadatumDTO("dc", "title", null, "State of Awareness of Freshers’ Groups Chortkiv State" + " Medical College of Prevention of Iodine Deficiency Diseases"); - MetadatumDTO author = createMetadatumDTO("dc", "contributor", "author", "L.V. Senyuk"); + MetadatumDTO author = createMetadatumDTO("dc", "contributor", "author", "Senyuk, L.V."); MetadatumDTO type = createMetadatumDTO("dc", "type", null, "journal-article"); MetadatumDTO date = createMetadatumDTO("dc", "date", "issued", "2016-05-19"); MetadatumDTO ispartof = createMetadatumDTO("dc", "relation", "ispartof", @@ -191,7 +191,7 @@ private ArrayList getRecords() { List metadatums2 = new ArrayList(); MetadatumDTO title2 = createMetadatumDTO("dc", "title", null, "Ischemic Heart Disease and Role of Nurse of Cardiology Department"); - MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "K. І. Kozak"); + MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "Kozak, K. І."); MetadatumDTO type2 = createMetadatumDTO("dc", "type", null, "journal-article"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2016-05-19"); MetadatumDTO ispartof2 = createMetadatumDTO("dc", "relation", "ispartof", From ffc99d06a1fc301109df664c3b126137410e1e95 Mon Sep 17 00:00:00 2001 From: autavares-dev Date: Mon, 12 Aug 2024 15:08:26 -0300 Subject: [PATCH 047/632] Fix index-discovery process when using handle (cherry picked from commit 077aed38dc55172ed70d8bfb9c44fd369d966a6d) --- dspace-api/src/main/java/org/dspace/discovery/IndexClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java b/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java index 661c48d91cfc..867359a949c6 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java @@ -21,6 +21,7 @@ import org.dspace.content.Item; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; +import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.discovery.indexobject.IndexableCollection; import org.dspace.discovery.indexobject.IndexableCommunity; @@ -92,7 +93,7 @@ public void internalRun() throws Exception { .getHandleService().resolveToObject(context, param); if (dso != null) { final IndexFactory indexableObjectService = IndexObjectFactoryFactory.getInstance(). - getIndexFactoryByType(String.valueOf(dso.getType())); + getIndexFactoryByType(Constants.typeText[dso.getType()]); indexableObject = indexableObjectService.findIndexableObject(context, dso.getID().toString()); } } From b98704ea4cc10d70ab34c6c2b557f0e85d696170 Mon Sep 17 00:00:00 2001 From: autavares-dev Date: Mon, 12 Aug 2024 15:08:26 -0300 Subject: [PATCH 048/632] Fix index-discovery process when using handle (cherry picked from commit 077aed38dc55172ed70d8bfb9c44fd369d966a6d) --- dspace-api/src/main/java/org/dspace/discovery/IndexClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java b/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java index b70e9162f7a1..3479c25bf367 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java @@ -27,6 +27,7 @@ import org.dspace.content.Item; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; +import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.discovery.indexobject.IndexableCollection; import org.dspace.discovery.indexobject.IndexableCommunity; @@ -109,7 +110,7 @@ public void internalRun() throws Exception { .getHandleService().resolveToObject(context, param); if (dso != null) { final IndexFactory indexableObjectService = IndexObjectFactoryFactory.getInstance(). - getIndexFactoryByType(String.valueOf(dso.getType())); + getIndexFactoryByType(Constants.typeText[dso.getType()]); indexableObject = indexableObjectService.findIndexableObject(context, dso.getID().toString()); } } From d1f837b2ba3177c13271a311cfd6b117d9fb30d6 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 23 Apr 2024 13:33:01 -0400 Subject: [PATCH 049/632] Separate task-list building from execution. The old code would curate the object once for each task, meaning that all but one task would be executed N times up to the length of the list. (cherry picked from commit c43948bf3d190d68e2c2840c5beee9268764ad2a) --- .../curate/XmlWorkflowCuratorServiceImpl.java | 29 ++++++++++--------- .../java/org/dspace/curate/package-info.java | 12 ++++++++ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/curate/XmlWorkflowCuratorServiceImpl.java b/dspace-api/src/main/java/org/dspace/curate/XmlWorkflowCuratorServiceImpl.java index 00e91ee1fb40..ec32ff92f9a2 100644 --- a/dspace-api/src/main/java/org/dspace/curate/XmlWorkflowCuratorServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/curate/XmlWorkflowCuratorServiceImpl.java @@ -140,13 +140,14 @@ public boolean curate(Curator curator, Context c, XmlWorkflowItem wfi) item.setOwningCollection(wfi.getCollection()); for (Task task : step.tasks) { curator.addTask(task.name); - // Check whether the task is configured to be queued rather than automatically run - if (StringUtils.isNotEmpty(step.queue)) { - // queue attribute has been set in the FlowStep configuration: add task to configured queue - curator.queue(c, item.getID().toString(), step.queue); - } else { - // Task is configured to be run automatically - curator.curate(c, item); + } + + if (StringUtils.isNotEmpty(step.queue)) { // Step's tasks are to be queued. + curator.queue(c, item.getID().toString(), step.queue); + } else { // Step's tasks are to be run now. + curator.curate(c, item); + + for (Task task : step.tasks) { int status = curator.getStatus(task.name); String result = curator.getResult(task.name); String action = "none"; @@ -183,14 +184,14 @@ public boolean curate(Curator curator, Context c, XmlWorkflowItem wfi) } } curator.clear(); - } - // Record any reporting done by the tasks. - if (reporter.length() > 0) { - LOG.info("Curation tasks over item {} for step {} report:%n{}", - () -> wfi.getItem().getID(), - () -> step.step, - () -> reporter.toString()); + // Record any reporting done by the tasks. + if (reporter.length() > 0) { + LOG.info("Curation tasks over item {} for step {} report:\n{}", + () -> wfi.getItem().getID(), + () -> step.step, + () -> reporter.toString()); + } } } return true; diff --git a/dspace-api/src/main/java/org/dspace/curate/package-info.java b/dspace-api/src/main/java/org/dspace/curate/package-info.java index 492642f60c57..1168bbd283d2 100644 --- a/dspace-api/src/main/java/org/dspace/curate/package-info.java +++ b/dspace-api/src/main/java/org/dspace/curate/package-info.java @@ -20,6 +20,8 @@ * * *

    Curation requests may be run immediately or queued for batch processing. + * See {@link TaskQueue} and its relatives, {@link Curation} and its relatives + * for more on queued curation. * *

    Tasks may also be attached to a workflow step, so that a set of tasks is * applied to each uninstalled Item which passes through that step. See @@ -27,5 +29,15 @@ * *

    A task may return to the Curator a status code, a final status message, * and an optional report character stream. + * + *

    The {@link Reporter} classes absorb strings of text and preserve it in + * various ways. A Reporter is a simple {@link Appendable} and makes no + * assumptions about e.g. whether a string represents a complete line. If you + * want your report formatted, insert appropriate newlines and other whitespace + * as needed. Your tasks can emit marked-up text if you wish, but the stock + * Reporter implementations make no attempt to render it. + * + *

    Tasks may be annotated to inform the Curator of special properties. See + * {@link Distributive}, {@link Mutative}, {@link Suspendable} etc. */ package org.dspace.curate; From 0d74bd9f185f2036ca68853576545f09e32d23fb Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 23 Apr 2024 13:33:01 -0400 Subject: [PATCH 050/632] Separate task-list building from execution. The old code would curate the object once for each task, meaning that all but one task would be executed N times up to the length of the list. --- .../curate/XmlWorkflowCuratorServiceImpl.java | 28 +++++++++---------- .../java/org/dspace/curate/package-info.java | 12 ++++++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/curate/XmlWorkflowCuratorServiceImpl.java b/dspace-api/src/main/java/org/dspace/curate/XmlWorkflowCuratorServiceImpl.java index 27a162d543c2..ec32ff92f9a2 100644 --- a/dspace-api/src/main/java/org/dspace/curate/XmlWorkflowCuratorServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/curate/XmlWorkflowCuratorServiceImpl.java @@ -140,14 +140,14 @@ public boolean curate(Curator curator, Context c, XmlWorkflowItem wfi) item.setOwningCollection(wfi.getCollection()); for (Task task : step.tasks) { curator.addTask(task.name); + } - // Check whether the task is configured to be queued rather than automatically run - if (StringUtils.isNotEmpty(step.queue)) { - // queue attribute has been set in the FlowStep configuration: add task to configured queue - curator.queue(c, item.getID().toString(), step.queue); - } else { - // Task is configured to be run automatically - curator.curate(c, item); + if (StringUtils.isNotEmpty(step.queue)) { // Step's tasks are to be queued. + curator.queue(c, item.getID().toString(), step.queue); + } else { // Step's tasks are to be run now. + curator.curate(c, item); + + for (Task task : step.tasks) { int status = curator.getStatus(task.name); String result = curator.getResult(task.name); String action = "none"; @@ -184,14 +184,14 @@ public boolean curate(Curator curator, Context c, XmlWorkflowItem wfi) } } curator.clear(); - } - // Record any reporting done by the tasks. - if (reporter.length() > 0) { - LOG.info("Curation tasks over item {} for step {} report:%n{}", - () -> wfi.getItem().getID(), - () -> step.step, - () -> reporter.toString()); + // Record any reporting done by the tasks. + if (reporter.length() > 0) { + LOG.info("Curation tasks over item {} for step {} report:\n{}", + () -> wfi.getItem().getID(), + () -> step.step, + () -> reporter.toString()); + } } } return true; diff --git a/dspace-api/src/main/java/org/dspace/curate/package-info.java b/dspace-api/src/main/java/org/dspace/curate/package-info.java index 492642f60c57..1168bbd283d2 100644 --- a/dspace-api/src/main/java/org/dspace/curate/package-info.java +++ b/dspace-api/src/main/java/org/dspace/curate/package-info.java @@ -20,6 +20,8 @@ * * *

    Curation requests may be run immediately or queued for batch processing. + * See {@link TaskQueue} and its relatives, {@link Curation} and its relatives + * for more on queued curation. * *

    Tasks may also be attached to a workflow step, so that a set of tasks is * applied to each uninstalled Item which passes through that step. See @@ -27,5 +29,15 @@ * *

    A task may return to the Curator a status code, a final status message, * and an optional report character stream. + * + *

    The {@link Reporter} classes absorb strings of text and preserve it in + * various ways. A Reporter is a simple {@link Appendable} and makes no + * assumptions about e.g. whether a string represents a complete line. If you + * want your report formatted, insert appropriate newlines and other whitespace + * as needed. Your tasks can emit marked-up text if you wish, but the stock + * Reporter implementations make no attempt to render it. + * + *

    Tasks may be annotated to inform the Curator of special properties. See + * {@link Distributive}, {@link Mutative}, {@link Suspendable} etc. */ package org.dspace.curate; From 41312eec6e4e7d86574428f03425c54117ea267c Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Mon, 26 Aug 2024 15:02:31 -0400 Subject: [PATCH 051/632] Make statistics autocommit much more frequent. (cherry picked from commit 5c9af9764e2485b26398ec06446cb8f0edd9cab2) --- dspace/solr/statistics/conf/solrconfig.xml | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/dspace/solr/statistics/conf/solrconfig.xml b/dspace/solr/statistics/conf/solrconfig.xml index 2b1cff45373d..c3f023ff2eee 100644 --- a/dspace/solr/statistics/conf/solrconfig.xml +++ b/dspace/solr/statistics/conf/solrconfig.xml @@ -32,14 +32,16 @@ - + 32 1000 ${solr.lock.type:native} - + false @@ -48,7 +50,7 @@ 10000 - ${solr.autoCommit.maxTime:900000} + ${solr.autoCommit.maxTime:10000} true @@ -62,14 +64,16 @@ ${solr.max.booleanClauses:1024} + unordered sets of *all* documents that match a + query. Caches results of 'fq' search param. --> - + 1000 - + - + uuid @@ -126,7 +132,8 @@ - + uid From da4cc4cb3137a620e00df8c586c138b60c1bed2b Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Mon, 26 Aug 2024 15:02:31 -0400 Subject: [PATCH 052/632] Make statistics autocommit much more frequent. (cherry picked from commit 5c9af9764e2485b26398ec06446cb8f0edd9cab2) --- dspace/solr/statistics/conf/solrconfig.xml | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/dspace/solr/statistics/conf/solrconfig.xml b/dspace/solr/statistics/conf/solrconfig.xml index 2b1cff45373d..c3f023ff2eee 100644 --- a/dspace/solr/statistics/conf/solrconfig.xml +++ b/dspace/solr/statistics/conf/solrconfig.xml @@ -32,14 +32,16 @@ - + 32 1000 ${solr.lock.type:native} - + false @@ -48,7 +50,7 @@ 10000 - ${solr.autoCommit.maxTime:900000} + ${solr.autoCommit.maxTime:10000} true @@ -62,14 +64,16 @@ ${solr.max.booleanClauses:1024} + unordered sets of *all* documents that match a + query. Caches results of 'fq' search param. --> - + 1000 - + - + uuid @@ -126,7 +132,8 @@ - + uid From e15f60abd3120b81b4b982cc9cb5344e3e2b2951 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 3 Sep 2024 17:13:01 +0200 Subject: [PATCH 053/632] Translate underscores to dashes in xml:lang attr for DIM2DataCite.xsl Modified the DataCite crosswalk to ensure that the xml:lang attribute translates any underscores in the value of @lang to dashes. This change aligns the attribute formatting with standard language code conventions. (cherry picked from commit a898afd5acbd6dc51a88b837cab2a1c56cc33967) --- dspace/config/crosswalks/DIM2DataCite.xsl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/dspace/config/crosswalks/DIM2DataCite.xsl b/dspace/config/crosswalks/DIM2DataCite.xsl index d4d8cbe6417a..935b3dc4038a 100644 --- a/dspace/config/crosswalks/DIM2DataCite.xsl +++ b/dspace/config/crosswalks/DIM2DataCite.xsl @@ -25,6 +25,10 @@ to register DOIs anymore. Please follow and reuse the examples included in this file. For more information on the DataCite Schema, see https://schema.datacite.org. --> + 10.5072/dspace- @@ -362,20 +366,20 @@ - + - + AlternativeTitle - - + Subtitle - + TranslatedTitle @@ -394,7 +398,7 @@ --> - + @@ -626,7 +630,7 @@ --> - + Abstract From 175c3d54cd5b3a6b66950b374e0bb35caf52897c Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 3 Sep 2024 17:13:01 +0200 Subject: [PATCH 054/632] Translate underscores to dashes in xml:lang attr for DIM2DataCite.xsl Modified the DataCite crosswalk to ensure that the xml:lang attribute translates any underscores in the value of @lang to dashes. This change aligns the attribute formatting with standard language code conventions. (cherry picked from commit a898afd5acbd6dc51a88b837cab2a1c56cc33967) --- dspace/config/crosswalks/DIM2DataCite.xsl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/dspace/config/crosswalks/DIM2DataCite.xsl b/dspace/config/crosswalks/DIM2DataCite.xsl index d4d8cbe6417a..935b3dc4038a 100644 --- a/dspace/config/crosswalks/DIM2DataCite.xsl +++ b/dspace/config/crosswalks/DIM2DataCite.xsl @@ -25,6 +25,10 @@ to register DOIs anymore. Please follow and reuse the examples included in this file. For more information on the DataCite Schema, see https://schema.datacite.org. --> + 10.5072/dspace- @@ -362,20 +366,20 @@ - + - + AlternativeTitle - - + Subtitle - + TranslatedTitle @@ -394,7 +398,7 @@ --> - + @@ -626,7 +630,7 @@ --> - + Abstract From 5ca9fee2be64d4fc4512d1f121ecc47e84a5827f Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 25 Jun 2024 13:45:31 +0200 Subject: [PATCH 055/632] Fix request a copy link token generation Ensure DSpace URLs with extra segments are included fully in the generated link (cherry picked from commit 52702a23df37f087058c7837a2dfcbbcf4306382) --- .../rest/repository/RequestItemRepository.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 6bfae8ed3515..1bb3ddbc9aed 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.validator.routines.EmailValidator; import org.apache.http.client.utils.URIBuilder; import org.apache.logging.log4j.LogManager; @@ -287,19 +288,17 @@ public Class getDomainClass() { * Generate a link back to DSpace, to act on a request. * * @param token identifies the request. - * @return URL to the item request API, with the token as request parameter - * "token". + * @return URL to the item request API, with /request-a-copy/{token} as the last URL segments * @throws URISyntaxException passed through. * @throws MalformedURLException passed through. */ private String getLinkTokenEmail(String token) throws URISyntaxException, MalformedURLException { final String base = configurationService.getProperty("dspace.ui.url"); - - URI link = new URIBuilder(base) - .setPathSegments("request-a-copy", token) - .build(); - - return link.toURL().toExternalForm(); + URIBuilder uriBuilder = new URIBuilder(base); + // Add request-a-copy/token to the existing path (without breaking /sub/dir dspace URLs) + URI uri = uriBuilder.setPath(StringUtils.stripEnd(uriBuilder.getPath(), "") + + "/request-a-copy/" + token).build(); + return uri.toURL().toExternalForm(); } } From 083f7b45e0b23a76a41fedd6e7c560f7278a3ef6 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 25 Jun 2024 14:36:17 +0200 Subject: [PATCH 056/632] Make RequestItemRepository#getLinkTokenEmail public, write test (cherry picked from commit 3646a54df3d540e7dc7603cd7013961df8d9a404) --- .../repository/RequestItemRepository.java | 2 +- .../app/rest/RequestItemRepositoryIT.java | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 1bb3ddbc9aed..0698567dcbc6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -292,7 +292,7 @@ public Class getDomainClass() { * @throws URISyntaxException passed through. * @throws MalformedURLException passed through. */ - private String getLinkTokenEmail(String token) + public String getLinkTokenEmail(String token) throws URISyntaxException, MalformedURLException { final String base = configurationService.getProperty("dspace.ui.url"); URIBuilder uriBuilder = new URIBuilder(base); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java index ea61db514504..a43e458207cf 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java @@ -28,6 +28,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.sql.SQLException; import java.time.temporal.ChronoUnit; import java.util.Date; @@ -55,10 +57,12 @@ import org.dspace.content.Bitstream; import org.dspace.content.Collection; import org.dspace.content.Item; +import org.dspace.services.ConfigurationService; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; /** * @@ -81,6 +85,12 @@ public class RequestItemRepositoryIT @Autowired(required = true) RequestItemService requestItemService; + @Autowired + ApplicationContext applicationContext; + + @Autowired + private ConfigurationService configurationService; + private Collection collection; private Item item; @@ -594,4 +604,23 @@ public void testGetDomainClass() { Class instanceClass = instance.getDomainClass(); assertEquals("Wrong domain class", RequestItemRest.class, instanceClass); } + + /** + * Test that generated links include the correct base URL, even if it has extra URL segments + */ + @Test + public void testGetLinkTokenEmail() throws MalformedURLException, URISyntaxException { + RequestItemRepository instance = applicationContext.getBean( + RequestItemRest.CATEGORY + '.' + RequestItemRest.PLURAL_NAME, + RequestItemRepository.class); + String currentDspaceUrl = configurationService.getProperty("dspace.ui.url"); + String newDspaceUrl = currentDspaceUrl + "/subdir"; + // Add a /subdir to the url for this test + configurationService.setProperty("dspace.ui.url", newDspaceUrl); + String expectedUrl = newDspaceUrl + "/request-a-copy/token"; + String generatedLink = instance.getLinkTokenEmail("token"); + // The URLs should match + assertEquals(expectedUrl, generatedLink); + configurationService.reloadConfig(); + } } From 6f1bc3bb6aa7c4c8069435c3d219637269aabb46 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 10 Jul 2024 16:04:34 +0200 Subject: [PATCH 057/632] #9668: Ensure proper handling of non-subpath URLs in link tokens (cherry picked from commit 6eb3271fa320b9d7d32ef3c59f7b83467bd2b03a) --- .../repository/RequestItemRepository.java | 5 +++-- .../app/rest/RequestItemRepositoryIT.java | 20 +++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 0698567dcbc6..35bd21489543 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -297,8 +297,9 @@ public String getLinkTokenEmail(String token) final String base = configurationService.getProperty("dspace.ui.url"); URIBuilder uriBuilder = new URIBuilder(base); // Add request-a-copy/token to the existing path (without breaking /sub/dir dspace URLs) - URI uri = uriBuilder.setPath(StringUtils.stripEnd(uriBuilder.getPath(), "") - + "/request-a-copy/" + token).build(); + URI uri = uriBuilder.setPath( + (uriBuilder.getPath() == null ? "" : StringUtils.stripEnd(uriBuilder.getPath(), "")) + + "/request-a-copy/" + token).build(); return uri.toURL().toExternalForm(); } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java index a43e458207cf..56409d18d738 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java @@ -606,10 +606,10 @@ public void testGetDomainClass() { } /** - * Test that generated links include the correct base URL, even if it has extra URL segments + * Test that generated links include the correct base URL, where the UI URL has a subpath like /subdir */ @Test - public void testGetLinkTokenEmail() throws MalformedURLException, URISyntaxException { + public void testGetLinkTokenEmailWithSubPath() throws MalformedURLException, URISyntaxException { RequestItemRepository instance = applicationContext.getBean( RequestItemRest.CATEGORY + '.' + RequestItemRest.PLURAL_NAME, RequestItemRepository.class); @@ -623,4 +623,20 @@ public void testGetLinkTokenEmail() throws MalformedURLException, URISyntaxExcep assertEquals(expectedUrl, generatedLink); configurationService.reloadConfig(); } + + /** + * Test that generated links include the correct base URL, with NO subpath elements + */ + @Test + public void testGetLinkTokenEmailWithoutSubPath() throws MalformedURLException, URISyntaxException { + RequestItemRepository instance = applicationContext.getBean( + RequestItemRest.CATEGORY + '.' + RequestItemRest.PLURAL_NAME, + RequestItemRepository.class); + String currentDspaceUrl = configurationService.getProperty("dspace.ui.url"); + String expectedUrl = currentDspaceUrl + "/request-a-copy/token"; + String generatedLink = instance.getLinkTokenEmail("token"); + // The URLs should match + assertEquals(expectedUrl, generatedLink); + configurationService.reloadConfig(); + } } From 67873075a90f6effe63b5bc0429c9508eb076a1b Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Sun, 1 Sep 2024 12:53:04 +0200 Subject: [PATCH 058/632] Improved URI build method as per review (cherry picked from commit a9f6d771121087f120c0a82710bde864b73b5e10) --- .../rest/repository/RequestItemRepository.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 35bd21489543..3de3dbef9c5a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -15,7 +15,11 @@ import java.net.URI; import java.net.URISyntaxException; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; import java.util.Date; +import java.util.LinkedList; +import java.util.List; import java.util.UUID; import com.fasterxml.jackson.databind.JsonNode; @@ -295,11 +299,16 @@ public Class getDomainClass() { public String getLinkTokenEmail(String token) throws URISyntaxException, MalformedURLException { final String base = configurationService.getProperty("dspace.ui.url"); + URIBuilder uriBuilder = new URIBuilder(base); - // Add request-a-copy/token to the existing path (without breaking /sub/dir dspace URLs) - URI uri = uriBuilder.setPath( - (uriBuilder.getPath() == null ? "" : StringUtils.stripEnd(uriBuilder.getPath(), "")) - + "/request-a-copy/" + token).build(); + List segments = new LinkedList<>(); + if (StringUtils.isNotBlank(uriBuilder.getPath())) { + segments.add(StringUtils.strip(uriBuilder.getPath(), "/")); + } + segments.add("request-a-copy"); + segments.add(token); + URI uri = uriBuilder.setPathSegments(segments).build(); + return uri.toURL().toExternalForm(); } } From 24199cf6f26dd30183f5d5f698eb939f97c780be Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 4 Sep 2024 14:04:20 +0200 Subject: [PATCH 059/632] Tidy implementation of link token generation (cherry picked from commit 74a6dc218787b77ed03aa36900be6bd070be043c) --- .../dspace/app/rest/repository/RequestItemRepository.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 3de3dbef9c5a..59645aaf1d57 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -300,6 +300,7 @@ public String getLinkTokenEmail(String token) throws URISyntaxException, MalformedURLException { final String base = configurationService.getProperty("dspace.ui.url"); + // Construct the link, making sure to support sub-paths URIBuilder uriBuilder = new URIBuilder(base); List segments = new LinkedList<>(); if (StringUtils.isNotBlank(uriBuilder.getPath())) { @@ -307,8 +308,8 @@ public String getLinkTokenEmail(String token) } segments.add("request-a-copy"); segments.add(token); - URI uri = uriBuilder.setPathSegments(segments).build(); - return uri.toURL().toExternalForm(); + // Build and return the URL from segments (or throw exception) + return uriBuilder.setPathSegments(segments).build().toURL().toExternalForm(); } } From 8656c5051d8919df88ea0016a2d0a05316f767fb Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 4 Sep 2024 15:19:34 +0200 Subject: [PATCH 060/632] lint fixes (RequestItemRepository) (cherry picked from commit 185a6fdf91c33eb5e100fd28b881f714b3a0a3be) --- .../org/dspace/app/rest/repository/RequestItemRepository.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 59645aaf1d57..eaae877f283e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -12,11 +12,8 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.LinkedList; import java.util.List; From 404039ade6796f9abfb5dbf420ab83f87057a033 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:25:18 +0200 Subject: [PATCH 061/632] #9806: Add new create methods to group builder Now supports admin groups, default read, workflow role (cherry picked from commit cdb167e55aac9916618dcfee7222105f4456dbd8) --- .../java/org/dspace/builder/GroupBuilder.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/dspace-api/src/test/java/org/dspace/builder/GroupBuilder.java b/dspace-api/src/test/java/org/dspace/builder/GroupBuilder.java index b3447dd8bd9a..c16fb696b0c3 100644 --- a/dspace-api/src/test/java/org/dspace/builder/GroupBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/GroupBuilder.java @@ -12,6 +12,9 @@ import java.util.UUID; import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Context; import org.dspace.eperson.EPerson; @@ -51,6 +54,33 @@ public static GroupBuilder createGroup(final Context context) { return builder.create(context); } + public static GroupBuilder createCollectionAdminGroup(final Context context, Collection collection) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createAdminGroup(context, collection); + } + + public static GroupBuilder createCollectionSubmitterGroup(final Context context, Collection collection) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createSubmitterGroup(context, collection); + } + + public static GroupBuilder createCollectionDefaultReadGroup(final Context context, Collection collection, + String typeOfGroupString, int defaultRead) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createDefaultReadGroup(context, collection, typeOfGroupString, defaultRead); + } + + public static GroupBuilder createCollectionWorkflowRoleGroup(final Context context, Collection collection, + String roleName) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createWorkflowRoleGroup(context, collection, roleName); + } + + public static GroupBuilder createCommunityAdminGroup(final Context context, Community community) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createAdminGroup(context, community); + } + private GroupBuilder create(final Context context) { this.context = context; try { @@ -61,6 +91,54 @@ private GroupBuilder create(final Context context) { return this; } + private GroupBuilder createAdminGroup(final Context context, DSpaceObject container) { + this.context = context; + try { + if (container instanceof Collection) { + group = collectionService.createAdministrators(context, (Collection) container); + } else if (container instanceof Community) { + group = communityService.createAdministrators(context, (Community) container); + } else { + handleException(new IllegalArgumentException("DSpaceObject must be collection or community. " + + "Type: " + container.getType())); + } + } catch (Exception e) { + return handleException(e); + } + return this; + } + + private GroupBuilder createSubmitterGroup(final Context context, Collection collection) { + this.context = context; + try { + group = collectionService.createSubmitters(context, collection); + } catch (Exception e) { + return handleException(e); + } + return this; + } + + private GroupBuilder createDefaultReadGroup(final Context context, Collection collection, + String typeOfGroupString, int defaultRead) { + this.context = context; + try { + group = collectionService.createDefaultReadGroup(context, collection, typeOfGroupString, defaultRead); + } catch (Exception e) { + return handleException(e); + } + return this; + } + + private GroupBuilder createWorkflowRoleGroup(final Context context, Collection collection, String roleName) { + this.context = context; + try { + group = workflowService.createWorkflowRoleGroup(context, collection, roleName); + } catch (Exception e) { + return handleException(e); + } + return this; + } + @Override protected DSpaceObjectService getService() { return groupService; From 2ff2297b1fdd90b6f7c595c34b1167df3f91c036 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:28:27 +0200 Subject: [PATCH 062/632] #9806: Use builders for coll, comm, group creation in BitstreamRestRepositoryIT (cherry picked from commit b13abac7539944358711a381548fbaedd9dcbd92) --- .../app/rest/BitstreamRestRepositoryIT.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java index bd79dc2f2b89..ecfe933fd921 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java @@ -49,6 +49,7 @@ import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EPersonBuilder; +import org.dspace.builder.GroupBuilder; import org.dspace.builder.ItemBuilder; import org.dspace.builder.ResourcePolicyBuilder; import org.dspace.content.Bitstream; @@ -2767,10 +2768,12 @@ public void deleteBitstreamsInBulk_collectionAdmin() throws Exception { .withEmail("col2admin@test.com") .withPassword(password) .build(); - Group col1_AdminGroup = collectionService.createAdministrators(context, col1); - Group col2_AdminGroup = collectionService.createAdministrators(context, col2); - groupService.addMember(context, col1_AdminGroup, col1Admin); - groupService.addMember(context, col2_AdminGroup, col2Admin); + Group col1_AdminGroup = GroupBuilder.createCollectionAdminGroup(context, col1) + .addMember(col1Admin) + .build(); + Group col2_AdminGroup = GroupBuilder.createCollectionAdminGroup(context, col2) + .addMember(col2Admin) + .build(); Item publicItem1 = ItemBuilder.createItem(context, col1) .withTitle("Test item 1") .build(); @@ -2871,8 +2874,9 @@ public void deleteBitstreamsInBulk_communityAdmin() throws Exception { .withEmail("parentComAdmin@test.com") .withPassword(password) .build(); - Group parentComAdminGroup = communityService.createAdministrators(context, parentCommunity); - groupService.addMember(context, parentComAdminGroup, parentCommunityAdmin); + Group parentComAdminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity) + .addMember(parentCommunityAdmin) + .build(); Item publicItem1 = ItemBuilder.createItem(context, col1) .withTitle("Test item 1") .build(); From b9b135163f5f261065aa272b3af41b92ac17cea7 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:29:48 +0200 Subject: [PATCH 063/632] #9806: Use builders for coll, comm, group creation in GroupRestRepositoryIT (cherry picked from commit 9205773802a8d22820b074e18409e245c63f5609) --- .../app/rest/GroupRestRepositoryIT.java | 202 ++++++++++-------- 1 file changed, 107 insertions(+), 95 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java index 2999b89d934f..92e53d922d25 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java @@ -85,9 +85,6 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest { ResourcePolicyService resourcePolicyService; @Autowired private ConfigurationService configurationService; - @Autowired - private CollectionService collectionService; - @Autowired private AuthorizeService authorizeService; @@ -773,12 +770,13 @@ public void addChildGroupCommunityAdminTest() throws Exception { try { context.turnOffAuthorisationSystem(); - community = communityService.create(null, context); - parentGroup = communityService.createAdministrators(context, community); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); + community = CommunityBuilder.createCommunity(context).build(); + parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + childGroup1 = GroupBuilder.createGroup(context).build(); + childGroup2 = GroupBuilder.createGroup(context).build(); - groupService.addMember(context, parentGroup, eperson); groupService.update(context, parentGroup); context.commit(); @@ -810,6 +808,7 @@ public void addChildGroupCommunityAdminTest() throws Exception { ); } finally { + // TODO: Can we remove these lines now that we are creating them with the builder? if (community != null) { CommunityBuilder.deleteCommunity(community.getID()); } @@ -837,9 +836,9 @@ public void addChildGroupForbiddenTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup1 = GroupBuilder.createGroup(context).build(); + childGroup2 = GroupBuilder.createGroup(context).build(); context.commit(); @@ -882,9 +881,9 @@ public void addChildGroupUnauthorizedTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup1 = GroupBuilder.createGroup(context).build(); + childGroup2 = GroupBuilder.createGroup(context).build(); context.commit(); @@ -926,9 +925,9 @@ public void addChildGroupNotFoundTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup1 = GroupBuilder.createGroup(context).build(); + childGroup2 = GroupBuilder.createGroup(context).build(); context.commit(); @@ -971,18 +970,18 @@ public void addChildGroupUnprocessableTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); - - groupService.addMember(context, childGroup1, parentGroup); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup1 = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); + childGroup2 = GroupBuilder.createGroup(context).build(); groupService.update(context, childGroup1); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); +// context.commit(); +// +// parentGroup = context.reloadEntity(parentGroup); +// childGroup1 = context.reloadEntity(childGroup1); +// childGroup2 = context.reloadEntity(childGroup2); context.restoreAuthSystemState(); String authToken = getAuthToken(admin.getEmail(), password); @@ -995,13 +994,15 @@ public void addChildGroupUnprocessableTest() throws Exception { ) ).andExpect(status().isUnprocessableEntity()); + // TODO - confirm with reviewers that this is a mistake - it actually should be No Content + // (see AddMember test) but was incorrectly expecting 422? getClient(authToken).perform( post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() ) - ).andExpect(status().isUnprocessableEntity()); + ).andExpect(status().isNoContent()); } finally { if (parentGroup != null) { @@ -1093,13 +1094,12 @@ public void addMemberCommunityAdminTest() throws Exception { try { context.turnOffAuthorisationSystem(); - community = communityService.create(null, context); - parentGroup = communityService.createAdministrators(context, community); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); - - groupService.addMember(context, parentGroup, eperson); - groupService.update(context, parentGroup); + community = CommunityBuilder.createCommunity(context).build(); + parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1158,9 +1158,9 @@ public void addMemberForbiddenTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1204,9 +1204,9 @@ public void addMemberUnauthorizedTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1249,9 +1249,9 @@ public void addMemberNotFoundTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1295,9 +1295,9 @@ public void addMemberUnprocessableTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1389,13 +1389,13 @@ public void removeChildGroupCommunityAdminTest() throws Exception { try { context.turnOffAuthorisationSystem(); - community = communityService.create(null, context); - parentGroup = communityService.createAdministrators(context, community); - childGroup = groupService.create(context); - - groupService.addMember(context, parentGroup, childGroup); - groupService.addMember(context, parentGroup, eperson); - groupService.update(context, parentGroup); + community = CommunityBuilder.createCommunity(context).build(); + parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); context.commit(); @@ -1439,8 +1439,8 @@ public void removeChildGroupForbiddenTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup = GroupBuilder.createGroup(context).build(); context.commit(); @@ -1474,8 +1474,8 @@ public void removeChildGroupUnauthorizedTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup = GroupBuilder.createGroup(context).build(); context.commit(); @@ -1508,10 +1508,10 @@ public void removeChildGroupNotFoundTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup = groupService.create(context); - - groupService.addMember(context, childGroup, parentGroup); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); context.commit(); @@ -1546,10 +1546,10 @@ public void removeChildGroupUnprocessableTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup = groupService.create(context); - - groupService.addMember(context, childGroup, parentGroup); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); context.commit(); @@ -1625,13 +1625,12 @@ public void removeMemberCommunityAdminTest() throws Exception { try { context.turnOffAuthorisationSystem(); - community = communityService.create(null, context); - parentGroup = communityService.createAdministrators(context, community); - member = ePersonService.create(context); - - groupService.addMember(context, parentGroup, member); - groupService.addMember(context, parentGroup, eperson); - groupService.update(context, parentGroup); + community = CommunityBuilder.createCommunity(context).build(); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(member) + .addMember(eperson) + .build(); assertTrue(groupService.isMember(context, member, parentGroup)); @@ -1678,9 +1677,10 @@ public void removeMemberForbiddenTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member = ePersonService.create(context); - groupService.addMember(context, parentGroup, member); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); context.commit(); @@ -1715,9 +1715,10 @@ public void removeMemberUnauthorizedTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member = ePersonService.create(context); - groupService.addMember(context, parentGroup, member); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); context.commit(); @@ -1751,9 +1752,10 @@ public void removeMemberNotFoundTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member = ePersonService.create(context); - groupService.addMember(context, parentGroup, member); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); context.commit(); @@ -1789,9 +1791,10 @@ public void removeMemberUnprocessableTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member = ePersonService.create(context); - groupService.addMember(context, parentGroup, member); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); context.commit(); @@ -2586,7 +2589,8 @@ public void commAdminAndColAdminCanManageItemReadGroupTest() throws Exception { String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group itemReadGroup = collectionService.createDefaultReadGroup(context, col1, itemGroupString, defaultItemRead); + Group itemReadGroup = GroupBuilder.createCollectionDefaultReadGroup(context, + col1, itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); @@ -2670,8 +2674,9 @@ public void commAdminAndColAdminCanManageBitstreamReadGroupTest() throws Excepti String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group bitstreamReadGroup = collectionService.createDefaultReadGroup(context, col1, bitstreamGroupString, - defaultBitstreamRead); + Group bitstreamReadGroup = GroupBuilder.createCollectionDefaultReadGroup(context, col1, bitstreamGroupString, + defaultBitstreamRead) + .build(); context.restoreAuthSystemState(); @@ -2792,7 +2797,8 @@ public void commAdminAndColAdminCanManageWorkflowGroupsTest() throws Exception { public void collectionAdminRemoveMembersFromCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); context.restoreAuthSystemState(); @@ -2827,7 +2833,8 @@ public void collectionAdminRemoveMembersFromCollectionAdminGroupSuccess() throws public void collectionAdminAddChildGroupToCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -2853,7 +2860,8 @@ public void collectionAdminAddChildGroupToCollectionAdminGroupSuccess() throws E public void collectionAdminRemoveChildGroupFromCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -2889,7 +2897,8 @@ public void collectionAdminRemoveChildGroupFromCollectionAdminGroupSuccess() thr public void collectionAdminAddMembersToCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false); @@ -2923,7 +2932,8 @@ public void collectionAdminAddMembersToCollectionAdminGroupPropertySetToFalse() public void collectionAdminRemoveMembersFromCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); context.restoreAuthSystemState(); @@ -2961,7 +2971,8 @@ public void collectionAdminRemoveMembersFromCollectionAdminGroupPropertySetToFal public void collectionAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false); @@ -2990,7 +3001,8 @@ public void collectionAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse public void collectionAdminRemoveChildGroupFromCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); From 690dfa0809dc0c1829898c5f2a4d8bdbc2de0095 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:30:52 +0200 Subject: [PATCH 064/632] #9806: Tidy imports for GroupRestRepositoryIT (cherry picked from commit 80328eaca5f2ad36e006d32ea06aa3b89e2ada92) --- .../src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java index 92e53d922d25..2d191b2fe7c7 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java @@ -60,7 +60,6 @@ import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.core.I18nUtil; From 67fa262b83cf89d3645959bd466b1efb5d8b3736 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:31:31 +0200 Subject: [PATCH 065/632] #9806: Use builders for group, comm, coll creation in PackagerIT (cherry picked from commit 1f475aa731bbe42ad523f1056e6b56796ea8a2ee) --- .../src/test/java/org/dspace/app/packager/PackagerIT.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java b/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java index 2cddbb511f91..aeda97f818c2 100644 --- a/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java +++ b/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java @@ -24,6 +24,7 @@ import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; +import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.Item; @@ -159,7 +160,7 @@ public void packagerUUIDAlreadyExistWithoutForceTest() throws Exception { performExportScript(article.getHandle(), tempFile); UUID id = article.getID(); itemService.delete(context, article); - WorkspaceItem workspaceItem = workspaceItemService.create(context, col1, id, false, false); + WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, col1, id).build(); installItemService.installItem(context, workspaceItem, "123456789/0100"); performImportNoForceScript(tempFile); Iterator items = itemService.findByCollection(context, col1); From 8d576f83002d9a2f7df39717d2af61f744b9d78c Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:32:08 +0200 Subject: [PATCH 066/632] #9806: Use builders for group, comm, coll creation in StructBuilderIT (cherry picked from commit 2ef69045d15ae49a4d447227e8080860eecc61cd) --- .../dspace/administer/StructBuilderIT.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/administer/StructBuilderIT.java b/dspace-api/src/test/java/org/dspace/administer/StructBuilderIT.java index 63340698ac00..ead338bc8e70 100644 --- a/dspace-api/src/test/java/org/dspace/administer/StructBuilderIT.java +++ b/dspace-api/src/test/java/org/dspace/administer/StructBuilderIT.java @@ -23,11 +23,12 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.dspace.AbstractIntegrationTest; +import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.authorize.AuthorizeException; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; @@ -38,7 +39,6 @@ import org.junit.Test; import org.w3c.dom.Attr; import org.w3c.dom.Node; -import org.xml.sax.SAXException; import org.xmlunit.builder.DiffBuilder; import org.xmlunit.diff.Comparison; import org.xmlunit.diff.ComparisonFormatter; @@ -52,7 +52,7 @@ * @author Mark H. Wood */ public class StructBuilderIT - extends AbstractIntegrationTest { + extends AbstractIntegrationTestWithDatabase { private static final Logger log = LogManager.getLogger(); private static final CommunityService communityService @@ -79,7 +79,8 @@ public static void tearDownClass() { * @throws IOException passed through. */ @Before - public void setUp() throws SQLException, AuthorizeException, IOException { + public void setUp() throws Exception { + super.setUp(); // Clear out all communities and collections. context.turnOffAuthorisationSystem(); for (Community community : communityService.findAllTop(context)) { @@ -285,19 +286,15 @@ public void testImportStructureWithHandles() * @throws org.dspace.authorize.AuthorizeException passed through. */ @Test - public void testExportStructure() - throws ParserConfigurationException, SAXException, IOException, - SQLException, AuthorizeException { + public void testExportStructure() { // Create some structure to test. context.turnOffAuthorisationSystem(); - Community community0 = communityService.create(null, context); - communityService.setMetadataSingleValue(context, community0, - MetadataSchemaEnum.DC.getName(), "title", null, - null, "Top Community 0"); - Collection collection0_0 = collectionService.create(context, community0); - collectionService.setMetadataSingleValue(context, collection0_0, - MetadataSchemaEnum.DC.getName(), "title", null, - null, "Collection 0.0"); + // Top level community + Community community0 = CommunityBuilder.createCommunity(context) + .withName("Top Community 0").build(); + // Collection below top level community + Collection collection0_0 = CollectionBuilder.createCollection(context, community0) + .withName("Collection 0.0").build(); // Export the current structure. System.out.println("exportStructure"); From ffc807205f8faecf380c99c7cc43479a5d474803 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:33:30 +0200 Subject: [PATCH 067/632] #9806: Refactor WorkspaceItemBuilder to support specific item uuid (cherry picked from commit b99b1eec29c5a0b6e92998b072282b03cfedc080) --- .../dspace/builder/WorkspaceItemBuilder.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java b/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java index 9d786d4761f0..06bdb82bd76e 100644 --- a/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.InputStream; import java.sql.SQLException; +import java.util.UUID; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; @@ -41,14 +42,31 @@ protected WorkspaceItemBuilder(Context context) { public static WorkspaceItemBuilder createWorkspaceItem(final Context context, final Collection col) { WorkspaceItemBuilder builder = new WorkspaceItemBuilder(context); - return builder.create(context, col); + return builder.create(context, col, null); } - private WorkspaceItemBuilder create(final Context context, final Collection col) { + public static WorkspaceItemBuilder createWorkspaceItem(final Context context, final Collection col, UUID uuid) { + WorkspaceItemBuilder builder = new WorkspaceItemBuilder(context); + return builder.create(context, col, uuid); + } + + /** + * Create with a specific UUID (e.g. restoring items with Packager import) + * + * @param context DSpace context + * @param col Parent collection + * @param uuid Item UUID + * @return WorkspaceItemBuilder + */ + private WorkspaceItemBuilder create(final Context context, final Collection col, UUID uuid) { this.context = context; try { - workspaceItem = workspaceItemService.create(context, col, false); + if (uuid == null) { + workspaceItem = workspaceItemService.create(context, col, false); + } else { + workspaceItem = workspaceItemService.create(context, col, uuid, false, false); + } item = workspaceItem.getItem(); } catch (Exception e) { return handleException(e); From b9278cbf33bf5fa9efd607bd1976fda33b03ce46 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:34:05 +0200 Subject: [PATCH 068/632] #9806: Use builders for comm, coll, group creation in SupervisionOrderServiceIT (cherry picked from commit 6e9181e3f7cd502b345af7d5879fa25654176c25) --- .../SupervisionOrderServiceIT.java | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/supervision/SupervisionOrderServiceIT.java b/dspace-api/src/test/java/org/dspace/supervision/SupervisionOrderServiceIT.java index 60407823485b..aa4cd8bd4e49 100644 --- a/dspace-api/src/test/java/org/dspace/supervision/SupervisionOrderServiceIT.java +++ b/dspace-api/src/test/java/org/dspace/supervision/SupervisionOrderServiceIT.java @@ -18,6 +18,7 @@ import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EPersonBuilder; import org.dspace.builder.GroupBuilder; +import org.dspace.builder.SupervisionOrderBuilder; import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; import org.dspace.content.Item; @@ -85,10 +86,10 @@ public void createSupervisionOrderTest() throws Exception { .build(); SupervisionOrder supervisionOrderOne = - supervisionOrderService.create(context, item, groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, item, groupA).build(); SupervisionOrder supervisionOrderTwo = - supervisionOrderService.create(context, item, groupB); + SupervisionOrderBuilder.createSupervisionOrder(context, item, groupB).build(); context.restoreAuthSystemState(); @@ -136,7 +137,8 @@ public void findSupervisionOrderTest() throws Exception { .build(); SupervisionOrder supervisionOrderOne = - supervisionOrderService.create(context, workspaceItem.getItem(), groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupA) + .build(); context.restoreAuthSystemState(); @@ -205,9 +207,12 @@ public void findAllSupervisionOrdersTest() throws Exception { .addMember(userB) .build(); - supervisionOrderService.create(context, workspaceItem.getItem(), groupA); - supervisionOrderService.create(context, workspaceItem.getItem(), groupB); - supervisionOrderService.create(context, workspaceItemTwo.getItem(), groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupA) + .build(); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupB) + .build(); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItemTwo.getItem(), groupA) + .build(); context.restoreAuthSystemState(); @@ -259,9 +264,12 @@ public void findSupervisionOrderByItemTest() throws Exception { .addMember(eperson) .build(); - supervisionOrderService.create(context, workspaceItem.getItem(), groupA); - supervisionOrderService.create(context, workspaceItem.getItem(), groupB); - supervisionOrderService.create(context, workspaceItemTwo.getItem(), groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupA) + .build(); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupB) + .build(); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItemTwo.getItem(), groupA) + .build(); context.restoreAuthSystemState(); @@ -310,7 +318,8 @@ public void findSupervisionOrderByItemAndGroupTest() throws Exception { .addMember(eperson) .build(); - supervisionOrderService.create(context, item, groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, item, groupA) + .build(); context.restoreAuthSystemState(); @@ -370,7 +379,8 @@ public void isSupervisorTest() throws Exception { .addMember(userB) .build(); - supervisionOrderService.create(context, workspaceItem.getItem(), groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupA) + .build(); context.restoreAuthSystemState(); From 968559bbafcafc1c6e67f03778e35094df648a21 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:35:14 +0200 Subject: [PATCH 069/632] #9806: Use builders for comm, coll, group creation in CollectionGroupRestControllerIT (cherry picked from commit f4629d8351b70ca945ffeebdf928cebfb868c349) --- .../rest/CollectionGroupRestControllerIT.java | 151 +++++++++--------- 1 file changed, 77 insertions(+), 74 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionGroupRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionGroupRestControllerIT.java index f6ab10c087ad..8d490109220d 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionGroupRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionGroupRestControllerIT.java @@ -28,9 +28,9 @@ import org.dspace.authorize.service.AuthorizeService; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.GroupBuilder; import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; -import org.dspace.content.service.CollectionService; import org.dspace.core.Constants; import org.dspace.eperson.Group; import org.dspace.eperson.service.GroupService; @@ -41,10 +41,6 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrationTest { - - @Autowired - private CollectionService collectionService; - @Autowired private GroupService groupService; @@ -68,7 +64,7 @@ public void setup() { @Test public void getCollectionAdminGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -81,7 +77,7 @@ public void getCollectionAdminGroupTest() throws Exception { @Test public void getCollectionAdminGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -95,7 +91,7 @@ public void getCollectionAdminGroupTestParentCommunityAdmin() throws Exception { @Test public void getCollectionAdminGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -109,7 +105,7 @@ public void getCollectionAdminGroupTestCollectionAdmin() throws Exception { @Test public void getCollectionAdminGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/adminGroup")) @@ -119,7 +115,7 @@ public void getCollectionAdminGroupUnAuthorizedTest() throws Exception { @Test public void getCollectionAdminGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -413,7 +409,7 @@ public void postCollectionAdminGroupCreateAdminGroupUnProcessablePermanent() thr @Test public void deleteCollectionAdminGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -428,7 +424,7 @@ public void deleteCollectionAdminGroupTest() throws Exception { @Test public void deleteCollectionAdminGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -443,7 +439,7 @@ public void deleteCollectionAdminGroupTestParentCommunityAdmin() throws Exceptio @Test public void deleteCollectionAdminGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -458,7 +454,7 @@ public void deleteCollectionAdminGroupTestCollectionAdmin() throws Exception { @Test public void deleteCollectionAdminGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/adminGroup")) @@ -474,7 +470,7 @@ public void deleteCollectionAdminGroupUnAuthorizedTest() throws Exception { @Test public void deleteCollectionAdminGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -493,7 +489,7 @@ public void deleteCollectionAdminGroupForbiddenTest() throws Exception { @Test public void deleteCollectionAdminGroupNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -512,7 +508,7 @@ public void deleteCollectionAdminGroupNotFoundTest() throws Exception { @Test public void getCollectionSubmittersGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submitters = collectionService.createSubmitters(context, collection); + Group submitters = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -525,7 +521,7 @@ public void getCollectionSubmittersGroupTest() throws Exception { @Test public void getCollectionSubmittersGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group submitters = collectionService.createSubmitters(context, collection); + Group submitters = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -539,7 +535,7 @@ public void getCollectionSubmittersGroupTestParentCommunityAdmin() throws Except @Test public void getCollectionSubmittersGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group submitters = collectionService.createSubmitters(context, collection); + Group submitters = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -553,7 +549,7 @@ public void getCollectionSubmittersGroupTestCollectionAdmin() throws Exception { @Test public void getCollectionSubmittersGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/submittersGroup")) @@ -563,7 +559,7 @@ public void getCollectionSubmittersGroupUnAuthorizedTest() throws Exception { @Test public void getCollectionSubmittersGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -860,7 +856,7 @@ public void postCollectionSubmittersGroupCreateSubmittersGroupUnProcessablePerma @Test public void deleteCollectionSubmitterGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -875,7 +871,7 @@ public void deleteCollectionSubmitterGroupTest() throws Exception { @Test public void deleteCollectionSubmittersGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -890,7 +886,7 @@ public void deleteCollectionSubmittersGroupTestParentCommunityAdmin() throws Exc @Test public void deleteCollectionSubmittersGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -905,7 +901,7 @@ public void deleteCollectionSubmittersGroupTestCollectionAdmin() throws Exceptio @Test public void deleteCollectionSubmittersGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + Group submittersGroup = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/submittersGroup")) @@ -924,7 +920,7 @@ public void deleteCollectionSubmittersGroupUnAuthorizedTest() throws Exception { @Test public void deleteCollectionSubmittersGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + Group submittersGroup = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -945,7 +941,7 @@ public void deleteCollectionSubmittersGroupForbiddenTest() throws Exception { @Test public void deleteCollectionSubmittersGroupNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -961,7 +957,8 @@ public void getCollectionItemReadGroupTest() throws Exception { String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -977,7 +974,8 @@ public void getCollectionDefaultItemReadGroupTestParentCommunityAdmin() throws E String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -995,7 +993,8 @@ public void getCollectionDefaultItemReadGroupTestCollectionAdmin() throws Except String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1012,7 +1011,8 @@ public void getCollectionDefaultItemReadGroupUnAuthorizedTest() throws Exception String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/itemReadGroup")) @@ -1025,7 +1025,8 @@ public void getCollectionDefaultItemReadGroupForbiddenTest() throws Exception { String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1321,7 +1322,7 @@ public void deleteCollectionDefaultItemReadGroupTest() throws Exception { String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -1345,7 +1346,7 @@ public void deleteCollectionDefaultItemReadGroupTestParentCommunityAdmin() throw String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, itemGroupString, defaultItemRead).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1367,7 +1368,7 @@ public void deleteCollectionDefaultItemReadGroupTestCollectionAdmin() throws Exc String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, itemGroupString, defaultItemRead).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1389,7 +1390,8 @@ public void deleteCollectionDefaultItemReadGroupUnAuthorizedTest() throws Except String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/itemReadGroup")) @@ -1408,7 +1410,8 @@ public void deleteCollectionDefaultItemReadGroupForbiddenTest() throws Exception String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1430,7 +1433,7 @@ public void deleteCollectionDefaultItemReadGroupNotFoundTest() throws Exception String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1445,8 +1448,8 @@ public void getCollectionBitstreamReadGroupTest() throws Exception { String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -1462,8 +1465,8 @@ public void getCollectionDefaultBitstreamReadGroupTestParentCommunityAdmin() thr String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1480,8 +1483,8 @@ public void getCollectionDefaultBitstreamReadGroupTestCollectionAdmin() throws E String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1498,8 +1501,8 @@ public void getCollectionDefaultBitstreamReadGroupUnAuthorizedTest() throws Exce String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/bitstreamReadGroup")) @@ -1512,8 +1515,8 @@ public void getCollectionDefaultBitstreamReadGroupForbiddenTest() throws Excepti String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1811,8 +1814,8 @@ public void deleteCollectionDefaultBitstreamReadGroupTest() throws Exception { String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -1835,8 +1838,8 @@ public void deleteCollectionDefaultBitstreamReadGroupTestParentCommunityAdmin() String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1859,8 +1862,8 @@ public void deleteCollectionDefaultBitstreamReadGroupTestCollectionAdmin() throw String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1882,8 +1885,8 @@ public void deleteCollectionDefaultBitstreamReadGroupUnAuthorizedTest() throws E String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/bitstreamReadGroup")) @@ -1902,8 +1905,8 @@ public void deleteCollectionDefaultBitstreamReadGroupForbiddenTest() throws Exce String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1918,8 +1921,8 @@ public void deleteCollectionDefaultBitstreamReadGroupNotFoundTest() throws Excep String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1931,7 +1934,7 @@ public void deleteCollectionDefaultBitstreamReadGroupNotFoundTest() throws Excep public void getWorkflowGroupForCollectionAndRole() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -1944,7 +1947,7 @@ public void getWorkflowGroupForCollectionAndRole() throws Exception { @Test public void getWorkflowGroupForCollectionAndRoleParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1958,7 +1961,7 @@ public void getWorkflowGroupForCollectionAndRoleParentCommunityAdmin() throws Ex @Test public void getWorkflowGroupForCollectionAndRoleWrongUUIDCollectionNotFound() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1979,7 +1982,7 @@ public void getWorkflowGroupForCollectionAndRoleWrongRoleNotFound() throws Excep public void getWorkflowGroupCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1994,7 +1997,7 @@ public void getWorkflowGroupCommunityAdmin() throws Exception { @Test public void getWorkflowGroupCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -2009,7 +2012,7 @@ public void getWorkflowGroupCollectionAdmin() throws Exception { @Test public void getWorkflowGroupUnAuthorized() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer")) @@ -2019,7 +2022,7 @@ public void getWorkflowGroupUnAuthorized() throws Exception { @Test public void getWorkflowGroupForbidden() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -2324,7 +2327,7 @@ public void postCollectionWorkflowGroupCreateWorkflowGroupUnProcessablePermanent @Test public void deleteCollectionWorkflowGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -2339,7 +2342,7 @@ public void deleteCollectionWorkflowGroupTest() throws Exception { @Test public void deleteCollectionWorkflowGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -2355,7 +2358,7 @@ public void deleteCollectionWorkflowGroupTestParentCommunityAdmin() throws Excep @Test public void deleteCollectionWorkflowGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -2371,7 +2374,7 @@ public void deleteCollectionWorkflowGroupTestCollectionAdmin() throws Exception @Test public void deleteCollectionWorkflowGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer")) @@ -2387,7 +2390,7 @@ public void deleteCollectionWorkflowGroupUnAuthorizedTest() throws Exception { @Test public void deleteCollectionWorkflowGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -2406,7 +2409,7 @@ public void deleteCollectionWorkflowGroupForbiddenTest() throws Exception { @Test public void deleteCollectionWorkflowGroupNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -2418,7 +2421,7 @@ public void deleteCollectionWorkflowGroupNotFoundTest() throws Exception { @Test public void deleteCollectionWorkflowGroupWithPooledTaskTest() throws Exception { context.turnOffAuthorisationSystem(); - Group reviewer = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group reviewer = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); // Submit an Item into the workflow -> moves to the "reviewer" step's pool. // The role must have at least one EPerson, otherwise the WSI gets archived immediately From e6a0bb8943a1022f22e3fe2bc2aa6be51ed95a44 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:35:43 +0200 Subject: [PATCH 070/632] #9806: Builders for comm, coll, group in CommunityAdminGroupRestControllerIT (cherry picked from commit 2d9988f77c52537f46888f27e35dbc0360299835) --- .../CommunityAdminGroupRestControllerIT.java | 52 +++++++++---------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityAdminGroupRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityAdminGroupRestControllerIT.java index 37548553b143..074a7e6a3557 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityAdminGroupRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityAdminGroupRestControllerIT.java @@ -34,8 +34,6 @@ import org.dspace.builder.GroupBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; -import org.dspace.content.service.CollectionService; -import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; @@ -49,19 +47,12 @@ public class CommunityAdminGroupRestControllerIT extends AbstractControllerIntegrationTest { - - @Autowired - private CommunityService communityService; - @Autowired private GroupService groupService; @Autowired private AuthorizeService authorizeService; - @Autowired - private CollectionService collectionService; - @Autowired private ConfigurationService configurationService; @@ -78,7 +69,7 @@ public void setup() { @Test public void getCommunityAdminGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -91,7 +82,8 @@ public void getCommunityAdminGroupTest() throws Exception { @Test public void getCommunityAdminGroupTestCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); + // TODO: this should actually be "add member", not directly setting a policy, right? authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -106,7 +98,7 @@ public void getCommunityAdminGroupTestCommunityAdmin() throws Exception { @Test public void getCommunityAdminGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - communityService.createAdministrators(context, parentCommunity); + GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/communities/" + parentCommunity.getID() + "/adminGroup")) @@ -116,7 +108,7 @@ public void getCommunityAdminGroupUnAuthorizedTest() throws Exception { @Test public void getCommunityAdminGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - communityService.createAdministrators(context, parentCommunity); + GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); getClient(token).perform(get("/api/core/communities/" + parentCommunity.getID() + "/adminGroup")) @@ -379,7 +371,7 @@ public void postCommunityAdminGroupCreateAdminGroupUnProcessablePermanent() thro @Test public void deleteCommunityAdminGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -397,7 +389,7 @@ public void deleteCommunityAdminGroupTestCommunityAdmin() throws Exception { Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) .withName("Sub Community") .build(); - Group adminGroup = communityService.createAdministrators(context, child1); + GroupBuilder.createCommunityAdminGroup(context, child1).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -412,7 +404,7 @@ public void deleteCommunityAdminGroupTestCommunityAdmin() throws Exception { @Test public void deleteCommunityAdminGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/communities/" + parentCommunity.getID() + "/adminGroup")) @@ -429,7 +421,7 @@ public void deleteCommunityAdminGroupUnAuthorizedTest() throws Exception { @Test public void deleteCommunityAdminGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -449,7 +441,7 @@ public void deleteCommunityAdminGroupForbiddenTest() throws Exception { @Test public void deleteCommunityAdminGroupNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -462,7 +454,7 @@ public void deleteCommunityAdminGroupNotFoundTest() throws Exception { public void communityAdminAddMembersToCommunityAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); configurationService.setProperty("core.authorization.community-admin.admin-group", false); @@ -489,7 +481,7 @@ public void communityAdminAddMembersToCommunityAdminGroupPropertySetToFalse() th public void communityAdminRemoveMembersFromCommunityAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); context.restoreAuthSystemState(); @@ -526,7 +518,7 @@ public void communityAdminRemoveMembersFromCommunityAdminGroupPropertySetToFalse public void communityAdminAddChildGroupToCommunityAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); configurationService.setProperty("core.authorization.community-admin.admin-group", false); @@ -554,7 +546,7 @@ public void communityAdminAddChildGroupToCommunityAdminGroupPropertySetToFalse() public void communityAdminRemoveChildGroupFromCommunityAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -591,7 +583,9 @@ public void communityAdminRemoveChildGroupFromCommunityAdminGroupPropertySetToFa public void communityAdminAddChildGroupToCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + // TODO: Why is this test in CommunityAdmin? it seems to purely be a collection group test? + // copy paste gone wrong and we should actually be testing for community admin group sub? + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -617,7 +611,9 @@ public void communityAdminAddChildGroupToCollectionAdminGroupSuccess() throws Ex public void communityAdminRemoveChildGroupFromCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + // TODO: Why is this test in CommunityAdmin? it seems to purely be a collection group test? + // copy paste gone wrong and we should actually be testing for community admin group sub? + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -653,7 +649,7 @@ public void communityAdminRemoveChildGroupFromCollectionAdminGroupSuccess() thro public void communityAdminAddMembersToCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false); @@ -681,7 +677,7 @@ public void communityAdminAddMembersToCollectionAdminGroupPropertySetToFalse() t public void communityAdminRemoveMembersFromCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); context.restoreAuthSystemState(); @@ -719,7 +715,7 @@ public void communityAdminRemoveMembersFromCollectionAdminGroupPropertySetToFals public void communityAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false); @@ -748,7 +744,7 @@ public void communityAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse( public void communityAdminRemoveChildGroupFromCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); From 5fd99d8b14f022c72508b34fe19957d1dd4896a4 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:58:59 +0200 Subject: [PATCH 071/632] #9806: Update object cleanup in GroupRestRepositoryIT (cherry picked from commit 8cfb433c40ad01f348461a2c656665d1891de398) --- .../app/rest/GroupRestRepositoryIT.java | 952 +++++------------- 1 file changed, 239 insertions(+), 713 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java index 2d191b2fe7c7..a711c6c8be16 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java @@ -59,14 +59,11 @@ import org.dspace.content.Community; import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; -import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.core.I18nUtil; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.eperson.factory.EPersonServiceFactory; -import org.dspace.eperson.service.EPersonService; import org.dspace.eperson.service.GroupService; import org.dspace.services.ConfigurationService; import org.hamcrest.Matchers; @@ -757,263 +754,136 @@ public void addChildGroupTest() throws Exception { @Test public void addChildGroupCommunityAdminTest() throws Exception { - CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - Community community = null; - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - community = CommunityBuilder.createCommunity(context).build(); - parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) - .addMember(eperson) - .build(); - childGroup1 = GroupBuilder.createGroup(context).build(); - childGroup2 = GroupBuilder.createGroup(context).build(); - - groupService.update(context, parentGroup); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isNoContent()); + Community community = CommunityBuilder.createCommunity(context).build(); + Group parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + Group childGroup1 = GroupBuilder.createGroup(context).build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isNoContent()); - assertTrue( - groupService.isMember(parentGroup, childGroup1) - ); + parentGroup = context.reloadEntity(parentGroup); + childGroup1 = context.reloadEntity(childGroup1); + childGroup2 = context.reloadEntity(childGroup2); - assertTrue( - groupService.isMember(parentGroup, childGroup2) - ); + assertTrue( + groupService.isMember(parentGroup, childGroup1) + ); - } finally { - // TODO: Can we remove these lines now that we are creating them with the builder? - if (community != null) { - CommunityBuilder.deleteCommunity(community.getID()); - } - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + assertTrue( + groupService.isMember(parentGroup, childGroup2) + ); } @Test public void addChildGroupForbiddenTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup1 = GroupBuilder.createGroup(context).build(); - childGroup2 = GroupBuilder.createGroup(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isForbidden()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup1 = GroupBuilder.createGroup(context).build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isForbidden()); } @Test public void addChildGroupUnauthorizedTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup1 = GroupBuilder.createGroup(context).build(); - childGroup2 = GroupBuilder.createGroup(context).build(); + context.turnOffAuthorisationSystem(); - context.commit(); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup1 = GroupBuilder.createGroup(context).build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.commit(); - context.restoreAuthSystemState(); - getClient().perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isUnauthorized()); + parentGroup = context.reloadEntity(parentGroup); + childGroup1 = context.reloadEntity(childGroup1); + childGroup2 = context.reloadEntity(childGroup2); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + context.restoreAuthSystemState(); + getClient().perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isUnauthorized()); } @Test public void addChildGroupNotFoundTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup1 = GroupBuilder.createGroup(context).build(); - childGroup2 = GroupBuilder.createGroup(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isNotFound()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup1 = GroupBuilder.createGroup(context).build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isNotFound()); } @Test public void addChildGroupUnprocessableTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup1 = GroupBuilder.createGroup(context) - .withParent(parentGroup) - .build(); - childGroup2 = GroupBuilder.createGroup(context).build(); - groupService.update(context, childGroup1); - -// context.commit(); -// -// parentGroup = context.reloadEntity(parentGroup); -// childGroup1 = context.reloadEntity(childGroup1); -// childGroup2 = context.reloadEntity(childGroup2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup1 = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/123456789\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isUnprocessableEntity()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - // TODO - confirm with reviewers that this is a mistake - it actually should be No Content - // (see AddMember test) but was incorrectly expecting 422? - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isNoContent()); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/123456789\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isUnprocessableEntity()); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + // TODO - confirm with reviewers that this is a mistake - it actually should be No Content + // (see AddMember test) but was incorrectly expecting 422? + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isNoContent()); } @Test @@ -1081,251 +951,118 @@ public void addMemberTest() throws Exception { @Test public void addMemberCommunityAdminTest() throws Exception { - CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Community community = null; - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - community = CommunityBuilder.createCommunity(context).build(); - parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) - .addMember(eperson) - .build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isNoContent()); + Community community = CommunityBuilder.createCommunity(context).build(); + Group parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isNoContent()); - assertTrue( - groupService.isMember(context, member1, parentGroup) - ); + parentGroup = context.reloadEntity(parentGroup); + member1 = context.reloadEntity(member1); + member2 = context.reloadEntity(member2); - assertTrue( - groupService.isMember(context, member2, parentGroup) - ); + assertTrue( + groupService.isMember(context, member1, parentGroup) + ); - } finally { - if (community != null) { - CommunityBuilder.deleteCommunity(community.getID()); - } - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + assertTrue( + groupService.isMember(context, member2, parentGroup) + ); } @Test public void addMemberForbiddenTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isForbidden()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isForbidden()); } @Test public void addMemberUnauthorizedTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - getClient().perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isUnauthorized()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + context.restoreAuthSystemState(); + getClient().perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isUnauthorized()); } @Test public void addMemberNotFoundTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + UUID.randomUUID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isNotFound()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + UUID.randomUUID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isNotFound()); } @Test public void addMemberUnprocessableTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + Group parentGroup = GroupBuilder.createGroup(context).build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/123456789\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isUnprocessableEntity()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/123456789\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isUnprocessableEntity()); } @Test @@ -1378,29 +1115,18 @@ public void removeChildGroupTest() throws Exception { @Test public void removeChildGroupCommunityAdminTest() throws Exception { - CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - Community community = null; - Group parentGroup = null; - Group childGroup = null; - - try { context.turnOffAuthorisationSystem(); - community = CommunityBuilder.createCommunity(context).build(); - parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + Community community = CommunityBuilder.createCommunity(context).build(); + Group parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) .addMember(eperson) .build(); - childGroup = GroupBuilder.createGroup(context) + Group childGroup = GroupBuilder.createGroup(context) .withParent(parentGroup) .build(); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); - context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); getClient(authToken).perform( @@ -1413,163 +1139,71 @@ public void removeChildGroupCommunityAdminTest() throws Exception { assertFalse( groupService.isMember(parentGroup, childGroup) ); - - } finally { - if (community != null) { - CommunityBuilder.deleteCommunity(community.getID()); - } - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } } @Test public void removeChildGroupForbiddenTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup = GroupBuilder.createGroup(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID()) - ).andExpect(status().isForbidden()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup = GroupBuilder.createGroup(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID()) + ).andExpect(status().isForbidden()); } @Test public void removeChildGroupUnauthorizedTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup = GroupBuilder.createGroup(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - getClient().perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID()) - ).andExpect(status().isUnauthorized()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup = GroupBuilder.createGroup(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } + context.restoreAuthSystemState(); + getClient().perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID()) + ).andExpect(status().isUnauthorized()); } @Test public void removeChildGroupNotFoundTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup = GroupBuilder.createGroup(context) - .withParent(parentGroup) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); - getClient(authToken).perform( - delete("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups/" + childGroup.getID()) - ).andExpect(status().isNotFound()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } + getClient(authToken).perform( + delete("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups/" + childGroup.getID()) + ).andExpect(status().isNotFound()); } @Test public void removeChildGroupUnprocessableTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup = GroupBuilder.createGroup(context) - .withParent(parentGroup) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); - getClient(authToken).perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + UUID.randomUUID()) - ).andExpect(status().isUnprocessableEntity()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } + getClient(authToken).perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + UUID.randomUUID()) + ).andExpect(status().isUnprocessableEntity()); } @Test @@ -1613,31 +1247,19 @@ public void removeMemberTest() throws Exception { @Test public void removeMemberCommunityAdminTest() throws Exception { - CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Community community = null; - Group parentGroup = null; - EPerson member = null; - try { context.turnOffAuthorisationSystem(); - community = CommunityBuilder.createCommunity(context).build(); - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + Community community = CommunityBuilder.createCommunity(context).build(); + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) .addMember(member) .addMember(eperson) .build(); assertTrue(groupService.isMember(context, member, parentGroup)); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); - context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); getClient(authToken).perform( @@ -1650,171 +1272,75 @@ public void removeMemberCommunityAdminTest() throws Exception { assertFalse( groupService.isMember(context, member, parentGroup) ); - - } finally { - if (community != null) { - CommunityBuilder.deleteCommunity(community.getID()); - } - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } } @Test public void removeMemberForbiddenTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member = null; - - try { - context.turnOffAuthorisationSystem(); - - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createGroup(context) - .addMember(member) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID()) - ).andExpect(status().isForbidden()); + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID()) + ).andExpect(status().isForbidden()); } @Test public void removeMemberUnauthorizedTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member = null; - - try { - context.turnOffAuthorisationSystem(); - - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createGroup(context) - .addMember(member) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - getClient().perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID()) - ).andExpect(status().isUnauthorized()); + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } + context.restoreAuthSystemState(); + getClient().perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID()) + ).andExpect(status().isUnauthorized()); } @Test public void removeMemberNotFoundTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member = null; - - try { - context.turnOffAuthorisationSystem(); - - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createGroup(context) - .addMember(member) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); - getClient(authToken).perform( - delete("/api/eperson/groups/" + UUID.randomUUID() + "/epersons/" + member.getID()) - ).andExpect(status().isNotFound()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } + getClient(authToken).perform( + delete("/api/eperson/groups/" + UUID.randomUUID() + "/epersons/" + member.getID()) + ).andExpect(status().isNotFound()); } @Test public void removeMemberUnprocessableTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member = null; - - try { context.turnOffAuthorisationSystem(); - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createGroup(context) + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createGroup(context) .addMember(member) .build(); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); - context.restoreAuthSystemState(); String authToken = getAuthToken(admin.getEmail(), password); getClient(authToken).perform( delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + UUID.randomUUID()) ).andExpect(status().isUnprocessableEntity()); - - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } } @Test From 282d4db36bebb3e159a09f222e2aa13160a99468 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 16:43:36 +0200 Subject: [PATCH 072/632] #9806: Align provider reg in CreateMissingIdentifiersIT with other tests VersionedHandlerIdentifierProviderIT uses this registerProvider method which looks more reliable and doesn't do a refresh/reload of applicationContext after (which I suspected might have an odd interaction with VersioningWithRelationshipsIT and its createBean() calls?) (cherry picked from commit 90536e443b7fedef0481a34326cafc58fb334396) --- .../general/CreateMissingIdentifiersIT.java | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java index 2a07799deee5..8038a7153325 100644 --- a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java +++ b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java @@ -10,6 +10,8 @@ import static org.junit.Assert.assertEquals; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; @@ -19,7 +21,10 @@ import org.dspace.content.Item; import org.dspace.core.factory.CoreServiceFactory; import org.dspace.curate.Curator; +import org.dspace.identifier.IdentifierProvider; +import org.dspace.identifier.IdentifierServiceImpl; import org.dspace.identifier.VersionedHandleIdentifierProviderWithCanonicalHandles; +import org.dspace.kernel.ServiceManager; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; import org.junit.After; @@ -32,10 +37,23 @@ */ public class CreateMissingIdentifiersIT extends AbstractIntegrationTestWithDatabase { + private ServiceManager serviceManager; + private IdentifierServiceImpl identifierService; private static final String P_TASK_DEF = "plugin.named.org.dspace.curate.CurationTask"; private static final String TASK_NAME = "test"; + @Override + public void setUp() throws Exception { + super.setUp(); + context.turnOffAuthorisationSystem(); + + serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); + identifierService = serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0); + // Clean out providers to avoid any being used for creation of community and collection + identifierService.setProviders(new ArrayList<>()); + } + @Test public void testPerform() throws IOException { @@ -67,11 +85,7 @@ public void testPerform() /* * Now install an incompatible provider to make the task fail. */ - DSpaceServicesFactory.getInstance() - .getServiceManager() - .registerServiceClass( - VersionedHandleIdentifierProviderWithCanonicalHandles.class.getCanonicalName(), - VersionedHandleIdentifierProviderWithCanonicalHandles.class); + registerProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); curator.curate(context, item); System.out.format("With incompatible provider, result is '%s'.\n", @@ -86,4 +100,14 @@ public void destroy() throws Exception { super.destroy(); DSpaceServicesFactory.getInstance().getServiceManager().getApplicationContext().refresh(); } + + private void registerProvider(Class type) { + // Register our new provider + serviceManager.registerServiceClass(type.getName(), type); + IdentifierProvider identifierProvider = + (IdentifierProvider) serviceManager.getServiceByName(type.getName(), type); + + // Overwrite the identifier-service's providers with the new one to ensure only this provider is used + identifierService.setProviders(List.of(identifierProvider)); + } } From 48c8848fc21ed739c99045b5e3e2b690297ba3da Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 16:45:05 +0200 Subject: [PATCH 073/632] #9806: Use builders for creation in VersioningWithRelationshipsIT I am a bit uncertain about the createBean() calls here, why do we not simply *get* the configured beans using the service manager instead, but will look at that in a separate change (cherry picked from commit 3521ab6d3598e716cc9fe8e938e883b302006580) --- .../VersioningWithRelationshipsIT.java | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java index 44653300e0de..accc52d0d830 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java @@ -49,6 +49,7 @@ import org.dspace.builder.ItemBuilder; import org.dspace.builder.RelationshipBuilder; import org.dspace.builder.RelationshipTypeBuilder; +import org.dspace.builder.VersionBuilder; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; @@ -62,8 +63,6 @@ import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.Version; -import org.dspace.versioning.factory.VersionServiceFactory; -import org.dspace.versioning.service.VersioningService; import org.hamcrest.Matcher; import org.junit.Assert; import org.junit.Before; @@ -74,8 +73,6 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa private final RelationshipService relationshipService = ContentServiceFactory.getInstance().getRelationshipService(); - private final VersioningService versioningService = - VersionServiceFactory.getInstance().getVersionService(); private final WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService(); private final InstallItemService installItemService = @@ -291,7 +288,7 @@ public void test_createNewVersionOfItemOnLeftSideOfRelationships() throws Except // create a new version of the publication // ///////////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPublication); + Version newVersion = VersionBuilder.createVersion(context, originalPublication, "test").build(); Item newPublication = newVersion.getItem(); assertNotSame(originalPublication, newPublication); @@ -567,7 +564,7 @@ public void test_createNewVersionOfItemAndModifyRelationships() throws Exception // create a new version of the publication // ///////////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPublication); + Version newVersion = VersionBuilder.createVersion(context, originalPublication, "test").build(); Item newPublication = newVersion.getItem(); assertNotSame(originalPublication, newPublication); @@ -927,7 +924,7 @@ public void test_createNewVersionOfItemOnRightSideOfRelationships() throws Excep // create a new version of the person // //////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPerson); + Version newVersion = VersionBuilder.createVersion(context, originalPerson, "test").build(); Item newPerson = newVersion.getItem(); assertNotSame(originalPerson, newPerson); @@ -1300,7 +1297,7 @@ public void test_createNewVersionOfItemAndVerifyMetadataOrder() throws Exception // create new version of publication // /////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPublication); + Version newVersion = VersionBuilder.createVersion(context, originalPublication, "test").build(); Item newPublication = newVersion.getItem(); assertNotSame(originalPublication, newPublication); @@ -1463,7 +1460,7 @@ public void test_createNewVersionOfItemWithAddRemoveMove() throws Exception { // create a new version of the publication // ///////////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPublication); + Version newVersion = VersionBuilder.createVersion(context, originalPublication, "test").build(); Item newPublication = newVersion.getItem(); assertNotSame(originalPublication, newPublication); @@ -1782,7 +1779,7 @@ public void test_placeRecalculationAfterDelete() throws Exception { // create new version - volume 1.2 // ///////////////////////////////////// - Item v1_2 = versioningService.createNewVersion(context, v1_1).getItem(); + Item v1_2 = VersionBuilder.createVersion(context, v1_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, v1_2)); context.commit(); @@ -1790,7 +1787,7 @@ public void test_placeRecalculationAfterDelete() throws Exception { // create new version - issue 3.2 // //////////////////////////////////// - Item i3_2 = versioningService.createNewVersion(context, i3_1).getItem(); + Item i3_2 = VersionBuilder.createVersion(context, i3_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, i3_2)); context.commit(); @@ -2316,7 +2313,7 @@ public void test_placeRecalculationAfterDelete_complex() throws Exception { // create new version - person 3.2 // ///////////////////////////////////// - Item pe3_2 = versioningService.createNewVersion(context, pe3_1).getItem(); + Item pe3_2 = VersionBuilder.createVersion(context, pe3_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, pe3_2)); context.commit(); @@ -2324,7 +2321,7 @@ public void test_placeRecalculationAfterDelete_complex() throws Exception { // create new version - project 3.2 // ////////////////////////////////////// - Item pr3_2 = versioningService.createNewVersion(context, pr3_1).getItem(); + Item pr3_2 = VersionBuilder.createVersion(context, pr3_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, pr3_2)); context.commit(); @@ -3056,7 +3053,7 @@ public void test_placeRecalculationNoUseForPlace() throws Exception { // create new version - volume 1.2 // ///////////////////////////////////// - Item v1_2 = versioningService.createNewVersion(context, v1_1).getItem(); + Item v1_2 = VersionBuilder.createVersion(context, v1_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, v1_2)); context.commit(); @@ -3064,7 +3061,7 @@ public void test_placeRecalculationNoUseForPlace() throws Exception { // create new version - issue 3.2 // //////////////////////////////////// - Item i3_2 = versioningService.createNewVersion(context, i3_1).getItem(); + Item i3_2 = VersionBuilder.createVersion(context, i3_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, i3_2)); context.commit(); @@ -3509,7 +3506,7 @@ public void test_virtualMetadataPreserved() throws Exception { // create a new version of publication 1 and archive // /////////////////////////////////////////////////////// - Item publication1V2 = versioningService.createNewVersion(context, publication1V1).getItem(); + Item publication1V2 = VersionBuilder.createVersion(context, publication1V1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, publication1V2)); context.dispatchEvents(); @@ -3517,7 +3514,7 @@ public void test_virtualMetadataPreserved() throws Exception { // create new version of person 1 // //////////////////////////////////// - Item person1V2 = versioningService.createNewVersion(context, person1V1).getItem(); + Item person1V2 = VersionBuilder.createVersion(context, person1V1, "test").build().getItem(); // update "Smith, Donald" to "Smith, D." itemService.replaceMetadata( context, person1V2, "person", "givenName", null, null, "D.", @@ -3853,7 +3850,7 @@ public void test_virtualMetadataPreserved() throws Exception { // create new version of person 2 // //////////////////////////////////// - Item person2V2 = versioningService.createNewVersion(context, person2V1).getItem(); + Item person2V2 = VersionBuilder.createVersion(context, person2V1, "test").build().getItem(); Relationship rel1 = getRelationship(publication1V2, isAuthorOfPublication, person2V2); assertNotNull(rel1); rel1.setRightwardValue("Doe, Jane Jr"); From 89796ece6b4e7ad3401c02ecab54e1f33926263c Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 17:15:15 +0200 Subject: [PATCH 074/632] #9806: Set explicit id provider before VersioningWithRelationshipsIT (cherry picked from commit 4af690065038d9cb401d0fa1fc5fbfe0fa1fe2c7) --- .../VersioningWithRelationshipsIT.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java index accc52d0d830..10cb30cd52b9 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java @@ -60,6 +60,9 @@ import org.dspace.content.virtual.VirtualMetadataPopulator; import org.dspace.core.Constants; import org.dspace.discovery.SolrSearchCore; +import org.dspace.identifier.IdentifierProvider; +import org.dspace.identifier.IdentifierServiceImpl; +import org.dspace.identifier.VersionedHandleIdentifierProvider; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.Version; @@ -81,7 +84,7 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa ContentServiceFactory.getInstance().getItemService(); private final SolrSearchCore solrSearchCore = DSpaceServicesFactory.getInstance().getServiceManager().getServicesByType(SolrSearchCore.class).get(0); - + private IdentifierServiceImpl identifierService; protected Community community; protected Collection collection; protected EntityType publicationEntityType; @@ -98,6 +101,22 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa protected RelationshipType isIssueOfJournalVolume; protected RelationshipType isProjectOfPerson; + private void registerProvider(Class type) { + // Register our new provider + IdentifierProvider identifierProvider = + (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(type.getName(), type); + if (identifierProvider == null) { + DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); + identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(type.getName(), type); + } + + // Overwrite the identifier-service's providers with the new one to ensure only this provider is used + identifierService = DSpaceServicesFactory.getInstance().getServiceManager() + .getServicesByType(IdentifierServiceImpl.class).get(0); + identifierService.setProviders(new ArrayList<>()); + identifierService.setProviders(List.of(identifierProvider)); + } + @Override @Before public void setUp() throws Exception { @@ -105,6 +124,9 @@ public void setUp() throws Exception { context.turnOffAuthorisationSystem(); + + registerProvider(VersionedHandleIdentifierProvider.class); + community = CommunityBuilder.createCommunity(context) .withName("community") .build(); From 123aedde04b0e05419d18767a59f6008126589a9 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 17:58:23 +0200 Subject: [PATCH 075/632] #9806: Move cleanup of handle provider to destroy in VersionedHandleIdentifierProviderIT (cherry picked from commit f6cabe648dfcda786afdf7d5411dc3d7ad85c405) --- .../VersioningWithRelationshipsIT.java | 23 ------------------- .../VersionedHandleIdentifierProviderIT.java | 22 ++++++++++++++++-- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java index 10cb30cd52b9..3acc4ca146ee 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java @@ -60,9 +60,6 @@ import org.dspace.content.virtual.VirtualMetadataPopulator; import org.dspace.core.Constants; import org.dspace.discovery.SolrSearchCore; -import org.dspace.identifier.IdentifierProvider; -import org.dspace.identifier.IdentifierServiceImpl; -import org.dspace.identifier.VersionedHandleIdentifierProvider; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.Version; @@ -84,7 +81,6 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa ContentServiceFactory.getInstance().getItemService(); private final SolrSearchCore solrSearchCore = DSpaceServicesFactory.getInstance().getServiceManager().getServicesByType(SolrSearchCore.class).get(0); - private IdentifierServiceImpl identifierService; protected Community community; protected Collection collection; protected EntityType publicationEntityType; @@ -101,22 +97,6 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa protected RelationshipType isIssueOfJournalVolume; protected RelationshipType isProjectOfPerson; - private void registerProvider(Class type) { - // Register our new provider - IdentifierProvider identifierProvider = - (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(type.getName(), type); - if (identifierProvider == null) { - DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); - identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(type.getName(), type); - } - - // Overwrite the identifier-service's providers with the new one to ensure only this provider is used - identifierService = DSpaceServicesFactory.getInstance().getServiceManager() - .getServicesByType(IdentifierServiceImpl.class).get(0); - identifierService.setProviders(new ArrayList<>()); - identifierService.setProviders(List.of(identifierProvider)); - } - @Override @Before public void setUp() throws Exception { @@ -124,9 +104,6 @@ public void setUp() throws Exception { context.turnOffAuthorisationSystem(); - - registerProvider(VersionedHandleIdentifierProvider.class); - community = CommunityBuilder.createCommunity(context) .withName("community") .build(); diff --git a/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java b/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java index 7e549f6cae33..57acf1f1c453 100644 --- a/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java +++ b/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java @@ -24,6 +24,7 @@ import org.dspace.content.Item; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; +import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -57,13 +58,30 @@ public void setUp() throws Exception { .build(); } + @After + @Override + public void destroy() throws Exception { + super.destroy(); + // After this test has finished running, refresh application context and + // set the expected 'default' versioned handle provider back to ensure other tests don't fail + DSpaceServicesFactory.getInstance().getServiceManager().getApplicationContext().refresh(); + } + private void registerProvider(Class type) { // Register our new provider - serviceManager.registerServiceClass(type.getName(), type); IdentifierProvider identifierProvider = - (IdentifierProvider) serviceManager.getServiceByName(type.getName(), type); + (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + if (identifierProvider == null) { + DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); + identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + } // Overwrite the identifier-service's providers with the new one to ensure only this provider is used + identifierService = DSpaceServicesFactory.getInstance().getServiceManager() + .getServicesByType(IdentifierServiceImpl.class).get(0); + identifierService.setProviders(new ArrayList<>()); identifierService.setProviders(List.of(identifierProvider)); } From e57e91c2fd3419528b533946e8d75b3898abb121 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:25:18 +0200 Subject: [PATCH 076/632] #9806: Add new create methods to group builder Now supports admin groups, default read, workflow role (cherry picked from commit cdb167e55aac9916618dcfee7222105f4456dbd8) --- .../java/org/dspace/builder/GroupBuilder.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/dspace-api/src/test/java/org/dspace/builder/GroupBuilder.java b/dspace-api/src/test/java/org/dspace/builder/GroupBuilder.java index b3447dd8bd9a..c16fb696b0c3 100644 --- a/dspace-api/src/test/java/org/dspace/builder/GroupBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/GroupBuilder.java @@ -12,6 +12,9 @@ import java.util.UUID; import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Context; import org.dspace.eperson.EPerson; @@ -51,6 +54,33 @@ public static GroupBuilder createGroup(final Context context) { return builder.create(context); } + public static GroupBuilder createCollectionAdminGroup(final Context context, Collection collection) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createAdminGroup(context, collection); + } + + public static GroupBuilder createCollectionSubmitterGroup(final Context context, Collection collection) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createSubmitterGroup(context, collection); + } + + public static GroupBuilder createCollectionDefaultReadGroup(final Context context, Collection collection, + String typeOfGroupString, int defaultRead) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createDefaultReadGroup(context, collection, typeOfGroupString, defaultRead); + } + + public static GroupBuilder createCollectionWorkflowRoleGroup(final Context context, Collection collection, + String roleName) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createWorkflowRoleGroup(context, collection, roleName); + } + + public static GroupBuilder createCommunityAdminGroup(final Context context, Community community) { + GroupBuilder builder = new GroupBuilder(context); + return builder.createAdminGroup(context, community); + } + private GroupBuilder create(final Context context) { this.context = context; try { @@ -61,6 +91,54 @@ private GroupBuilder create(final Context context) { return this; } + private GroupBuilder createAdminGroup(final Context context, DSpaceObject container) { + this.context = context; + try { + if (container instanceof Collection) { + group = collectionService.createAdministrators(context, (Collection) container); + } else if (container instanceof Community) { + group = communityService.createAdministrators(context, (Community) container); + } else { + handleException(new IllegalArgumentException("DSpaceObject must be collection or community. " + + "Type: " + container.getType())); + } + } catch (Exception e) { + return handleException(e); + } + return this; + } + + private GroupBuilder createSubmitterGroup(final Context context, Collection collection) { + this.context = context; + try { + group = collectionService.createSubmitters(context, collection); + } catch (Exception e) { + return handleException(e); + } + return this; + } + + private GroupBuilder createDefaultReadGroup(final Context context, Collection collection, + String typeOfGroupString, int defaultRead) { + this.context = context; + try { + group = collectionService.createDefaultReadGroup(context, collection, typeOfGroupString, defaultRead); + } catch (Exception e) { + return handleException(e); + } + return this; + } + + private GroupBuilder createWorkflowRoleGroup(final Context context, Collection collection, String roleName) { + this.context = context; + try { + group = workflowService.createWorkflowRoleGroup(context, collection, roleName); + } catch (Exception e) { + return handleException(e); + } + return this; + } + @Override protected DSpaceObjectService getService() { return groupService; From 16374d6edb10ec97ffca890f6da62e7955bacb32 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:28:27 +0200 Subject: [PATCH 077/632] #9806: Use builders for coll, comm, group creation in BitstreamRestRepositoryIT (cherry picked from commit b13abac7539944358711a381548fbaedd9dcbd92) --- .../app/rest/BitstreamRestRepositoryIT.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java index af2b14759c63..a18dde701b47 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java @@ -50,6 +50,7 @@ import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EPersonBuilder; +import org.dspace.builder.GroupBuilder; import org.dspace.builder.ItemBuilder; import org.dspace.builder.ResourcePolicyBuilder; import org.dspace.content.Bitstream; @@ -2768,10 +2769,12 @@ public void deleteBitstreamsInBulk_collectionAdmin() throws Exception { .withEmail("col2admin@test.com") .withPassword(password) .build(); - Group col1_AdminGroup = collectionService.createAdministrators(context, col1); - Group col2_AdminGroup = collectionService.createAdministrators(context, col2); - groupService.addMember(context, col1_AdminGroup, col1Admin); - groupService.addMember(context, col2_AdminGroup, col2Admin); + Group col1_AdminGroup = GroupBuilder.createCollectionAdminGroup(context, col1) + .addMember(col1Admin) + .build(); + Group col2_AdminGroup = GroupBuilder.createCollectionAdminGroup(context, col2) + .addMember(col2Admin) + .build(); Item publicItem1 = ItemBuilder.createItem(context, col1) .withTitle("Test item 1") .build(); @@ -2872,8 +2875,9 @@ public void deleteBitstreamsInBulk_communityAdmin() throws Exception { .withEmail("parentComAdmin@test.com") .withPassword(password) .build(); - Group parentComAdminGroup = communityService.createAdministrators(context, parentCommunity); - groupService.addMember(context, parentComAdminGroup, parentCommunityAdmin); + Group parentComAdminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity) + .addMember(parentCommunityAdmin) + .build(); Item publicItem1 = ItemBuilder.createItem(context, col1) .withTitle("Test item 1") .build(); From 592df88d05c9ccca6926448abc169f66709a276b Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:29:48 +0200 Subject: [PATCH 078/632] #9806: Use builders for coll, comm, group creation in GroupRestRepositoryIT (cherry picked from commit 9205773802a8d22820b074e18409e245c63f5609) --- .../app/rest/GroupRestRepositoryIT.java | 202 ++++++++++-------- 1 file changed, 107 insertions(+), 95 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java index 83259aa09e99..6f9d418f7f43 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java @@ -85,9 +85,6 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest { ResourcePolicyService resourcePolicyService; @Autowired private ConfigurationService configurationService; - @Autowired - private CollectionService collectionService; - @Autowired private AuthorizeService authorizeService; @@ -773,12 +770,13 @@ public void addChildGroupCommunityAdminTest() throws Exception { try { context.turnOffAuthorisationSystem(); - community = communityService.create(null, context); - parentGroup = communityService.createAdministrators(context, community); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); + community = CommunityBuilder.createCommunity(context).build(); + parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + childGroup1 = GroupBuilder.createGroup(context).build(); + childGroup2 = GroupBuilder.createGroup(context).build(); - groupService.addMember(context, parentGroup, eperson); groupService.update(context, parentGroup); context.commit(); @@ -810,6 +808,7 @@ public void addChildGroupCommunityAdminTest() throws Exception { ); } finally { + // TODO: Can we remove these lines now that we are creating them with the builder? if (community != null) { CommunityBuilder.deleteCommunity(community.getID()); } @@ -837,9 +836,9 @@ public void addChildGroupForbiddenTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup1 = GroupBuilder.createGroup(context).build(); + childGroup2 = GroupBuilder.createGroup(context).build(); context.commit(); @@ -882,9 +881,9 @@ public void addChildGroupUnauthorizedTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup1 = GroupBuilder.createGroup(context).build(); + childGroup2 = GroupBuilder.createGroup(context).build(); context.commit(); @@ -926,9 +925,9 @@ public void addChildGroupNotFoundTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup1 = GroupBuilder.createGroup(context).build(); + childGroup2 = GroupBuilder.createGroup(context).build(); context.commit(); @@ -971,18 +970,18 @@ public void addChildGroupUnprocessableTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup1 = groupService.create(context); - childGroup2 = groupService.create(context); - - groupService.addMember(context, childGroup1, parentGroup); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup1 = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); + childGroup2 = GroupBuilder.createGroup(context).build(); groupService.update(context, childGroup1); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); +// context.commit(); +// +// parentGroup = context.reloadEntity(parentGroup); +// childGroup1 = context.reloadEntity(childGroup1); +// childGroup2 = context.reloadEntity(childGroup2); context.restoreAuthSystemState(); String authToken = getAuthToken(admin.getEmail(), password); @@ -995,13 +994,15 @@ public void addChildGroupUnprocessableTest() throws Exception { ) ).andExpect(status().isUnprocessableEntity()); + // TODO - confirm with reviewers that this is a mistake - it actually should be No Content + // (see AddMember test) but was incorrectly expecting 422? getClient(authToken).perform( post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() ) - ).andExpect(status().isUnprocessableEntity()); + ).andExpect(status().isNoContent()); } finally { if (parentGroup != null) { @@ -1093,13 +1094,12 @@ public void addMemberCommunityAdminTest() throws Exception { try { context.turnOffAuthorisationSystem(); - community = communityService.create(null, context); - parentGroup = communityService.createAdministrators(context, community); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); - - groupService.addMember(context, parentGroup, eperson); - groupService.update(context, parentGroup); + community = CommunityBuilder.createCommunity(context).build(); + parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1158,9 +1158,9 @@ public void addMemberForbiddenTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1204,9 +1204,9 @@ public void addMemberUnauthorizedTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1249,9 +1249,9 @@ public void addMemberNotFoundTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1295,9 +1295,9 @@ public void addMemberUnprocessableTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member1 = ePersonService.create(context); - member2 = ePersonService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + member1 = EPersonBuilder.createEPerson(context).build(); + member2 = EPersonBuilder.createEPerson(context).build(); context.commit(); @@ -1389,13 +1389,13 @@ public void removeChildGroupCommunityAdminTest() throws Exception { try { context.turnOffAuthorisationSystem(); - community = communityService.create(null, context); - parentGroup = communityService.createAdministrators(context, community); - childGroup = groupService.create(context); - - groupService.addMember(context, parentGroup, childGroup); - groupService.addMember(context, parentGroup, eperson); - groupService.update(context, parentGroup); + community = CommunityBuilder.createCommunity(context).build(); + parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); context.commit(); @@ -1439,8 +1439,8 @@ public void removeChildGroupForbiddenTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup = GroupBuilder.createGroup(context).build(); context.commit(); @@ -1474,8 +1474,8 @@ public void removeChildGroupUnauthorizedTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup = groupService.create(context); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup = GroupBuilder.createGroup(context).build(); context.commit(); @@ -1508,10 +1508,10 @@ public void removeChildGroupNotFoundTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup = groupService.create(context); - - groupService.addMember(context, childGroup, parentGroup); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); context.commit(); @@ -1546,10 +1546,10 @@ public void removeChildGroupUnprocessableTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - childGroup = groupService.create(context); - - groupService.addMember(context, childGroup, parentGroup); + parentGroup = GroupBuilder.createGroup(context).build(); + childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); context.commit(); @@ -1625,13 +1625,12 @@ public void removeMemberCommunityAdminTest() throws Exception { try { context.turnOffAuthorisationSystem(); - community = communityService.create(null, context); - parentGroup = communityService.createAdministrators(context, community); - member = ePersonService.create(context); - - groupService.addMember(context, parentGroup, member); - groupService.addMember(context, parentGroup, eperson); - groupService.update(context, parentGroup); + community = CommunityBuilder.createCommunity(context).build(); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(member) + .addMember(eperson) + .build(); assertTrue(groupService.isMember(context, member, parentGroup)); @@ -1678,9 +1677,10 @@ public void removeMemberForbiddenTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member = ePersonService.create(context); - groupService.addMember(context, parentGroup, member); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); context.commit(); @@ -1715,9 +1715,10 @@ public void removeMemberUnauthorizedTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member = ePersonService.create(context); - groupService.addMember(context, parentGroup, member); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); context.commit(); @@ -1751,9 +1752,10 @@ public void removeMemberNotFoundTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member = ePersonService.create(context); - groupService.addMember(context, parentGroup, member); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); context.commit(); @@ -1789,9 +1791,10 @@ public void removeMemberUnprocessableTest() throws Exception { try { context.turnOffAuthorisationSystem(); - parentGroup = groupService.create(context); - member = ePersonService.create(context); - groupService.addMember(context, parentGroup, member); + member = EPersonBuilder.createEPerson(context).build(); + parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); context.commit(); @@ -2586,7 +2589,8 @@ public void commAdminAndColAdminCanManageItemReadGroupTest() throws Exception { String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group itemReadGroup = collectionService.createDefaultReadGroup(context, col1, itemGroupString, defaultItemRead); + Group itemReadGroup = GroupBuilder.createCollectionDefaultReadGroup(context, + col1, itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); @@ -2670,8 +2674,9 @@ public void commAdminAndColAdminCanManageBitstreamReadGroupTest() throws Excepti String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group bitstreamReadGroup = collectionService.createDefaultReadGroup(context, col1, bitstreamGroupString, - defaultBitstreamRead); + Group bitstreamReadGroup = GroupBuilder.createCollectionDefaultReadGroup(context, col1, bitstreamGroupString, + defaultBitstreamRead) + .build(); context.restoreAuthSystemState(); @@ -2792,7 +2797,8 @@ public void commAdminAndColAdminCanManageWorkflowGroupsTest() throws Exception { public void collectionAdminRemoveMembersFromCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); context.restoreAuthSystemState(); @@ -2827,7 +2833,8 @@ public void collectionAdminRemoveMembersFromCollectionAdminGroupSuccess() throws public void collectionAdminAddChildGroupToCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -2853,7 +2860,8 @@ public void collectionAdminAddChildGroupToCollectionAdminGroupSuccess() throws E public void collectionAdminRemoveChildGroupFromCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -2889,7 +2897,8 @@ public void collectionAdminRemoveChildGroupFromCollectionAdminGroupSuccess() thr public void collectionAdminAddMembersToCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false); @@ -2923,7 +2932,8 @@ public void collectionAdminAddMembersToCollectionAdminGroupPropertySetToFalse() public void collectionAdminRemoveMembersFromCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); context.restoreAuthSystemState(); @@ -2961,7 +2971,8 @@ public void collectionAdminRemoveMembersFromCollectionAdminGroupPropertySetToFal public void collectionAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false); @@ -2990,7 +3001,8 @@ public void collectionAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse public void collectionAdminRemoveChildGroupFromCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection) + .build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); From f66a35a1e1d02a86a59ef3f557cb5c2b59cd7d7c Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:30:52 +0200 Subject: [PATCH 079/632] #9806: Tidy imports for GroupRestRepositoryIT (cherry picked from commit 80328eaca5f2ad36e006d32ea06aa3b89e2ada92) --- .../src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java index 6f9d418f7f43..bdd13b97ff79 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java @@ -60,7 +60,6 @@ import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.core.I18nUtil; From a6788700783212e99944c90e033bf4c33b9241f9 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:31:31 +0200 Subject: [PATCH 080/632] #9806: Use builders for group, comm, coll creation in PackagerIT (cherry picked from commit 1f475aa731bbe42ad523f1056e6b56796ea8a2ee) --- .../src/test/java/org/dspace/app/packager/PackagerIT.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java b/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java index 2cddbb511f91..aeda97f818c2 100644 --- a/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java +++ b/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java @@ -24,6 +24,7 @@ import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; +import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.Item; @@ -159,7 +160,7 @@ public void packagerUUIDAlreadyExistWithoutForceTest() throws Exception { performExportScript(article.getHandle(), tempFile); UUID id = article.getID(); itemService.delete(context, article); - WorkspaceItem workspaceItem = workspaceItemService.create(context, col1, id, false, false); + WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, col1, id).build(); installItemService.installItem(context, workspaceItem, "123456789/0100"); performImportNoForceScript(tempFile); Iterator items = itemService.findByCollection(context, col1); From ba8385117c58b6d200aa310a87e8d1f7e23a4d81 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:32:08 +0200 Subject: [PATCH 081/632] #9806: Use builders for group, comm, coll creation in StructBuilderIT (cherry picked from commit 2ef69045d15ae49a4d447227e8080860eecc61cd) --- .../dspace/administer/StructBuilderIT.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/administer/StructBuilderIT.java b/dspace-api/src/test/java/org/dspace/administer/StructBuilderIT.java index 63340698ac00..ead338bc8e70 100644 --- a/dspace-api/src/test/java/org/dspace/administer/StructBuilderIT.java +++ b/dspace-api/src/test/java/org/dspace/administer/StructBuilderIT.java @@ -23,11 +23,12 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.dspace.AbstractIntegrationTest; +import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.authorize.AuthorizeException; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; @@ -38,7 +39,6 @@ import org.junit.Test; import org.w3c.dom.Attr; import org.w3c.dom.Node; -import org.xml.sax.SAXException; import org.xmlunit.builder.DiffBuilder; import org.xmlunit.diff.Comparison; import org.xmlunit.diff.ComparisonFormatter; @@ -52,7 +52,7 @@ * @author Mark H. Wood */ public class StructBuilderIT - extends AbstractIntegrationTest { + extends AbstractIntegrationTestWithDatabase { private static final Logger log = LogManager.getLogger(); private static final CommunityService communityService @@ -79,7 +79,8 @@ public static void tearDownClass() { * @throws IOException passed through. */ @Before - public void setUp() throws SQLException, AuthorizeException, IOException { + public void setUp() throws Exception { + super.setUp(); // Clear out all communities and collections. context.turnOffAuthorisationSystem(); for (Community community : communityService.findAllTop(context)) { @@ -285,19 +286,15 @@ public void testImportStructureWithHandles() * @throws org.dspace.authorize.AuthorizeException passed through. */ @Test - public void testExportStructure() - throws ParserConfigurationException, SAXException, IOException, - SQLException, AuthorizeException { + public void testExportStructure() { // Create some structure to test. context.turnOffAuthorisationSystem(); - Community community0 = communityService.create(null, context); - communityService.setMetadataSingleValue(context, community0, - MetadataSchemaEnum.DC.getName(), "title", null, - null, "Top Community 0"); - Collection collection0_0 = collectionService.create(context, community0); - collectionService.setMetadataSingleValue(context, collection0_0, - MetadataSchemaEnum.DC.getName(), "title", null, - null, "Collection 0.0"); + // Top level community + Community community0 = CommunityBuilder.createCommunity(context) + .withName("Top Community 0").build(); + // Collection below top level community + Collection collection0_0 = CollectionBuilder.createCollection(context, community0) + .withName("Collection 0.0").build(); // Export the current structure. System.out.println("exportStructure"); From dcb567ead6d30f385cdb09a893f3e651f25ad374 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:33:30 +0200 Subject: [PATCH 082/632] #9806: Refactor WorkspaceItemBuilder to support specific item uuid (cherry picked from commit b99b1eec29c5a0b6e92998b072282b03cfedc080) --- .../dspace/builder/WorkspaceItemBuilder.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java b/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java index 8b82149cdf7f..67d8894338eb 100644 --- a/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.InputStream; import java.sql.SQLException; +import java.util.UUID; import org.dspace.app.ldn.NotifyPatternToTrigger; import org.dspace.app.ldn.NotifyServiceEntity; @@ -43,14 +44,31 @@ protected WorkspaceItemBuilder(Context context) { public static WorkspaceItemBuilder createWorkspaceItem(final Context context, final Collection col) { WorkspaceItemBuilder builder = new WorkspaceItemBuilder(context); - return builder.create(context, col); + return builder.create(context, col, null); } - private WorkspaceItemBuilder create(final Context context, final Collection col) { + public static WorkspaceItemBuilder createWorkspaceItem(final Context context, final Collection col, UUID uuid) { + WorkspaceItemBuilder builder = new WorkspaceItemBuilder(context); + return builder.create(context, col, uuid); + } + + /** + * Create with a specific UUID (e.g. restoring items with Packager import) + * + * @param context DSpace context + * @param col Parent collection + * @param uuid Item UUID + * @return WorkspaceItemBuilder + */ + private WorkspaceItemBuilder create(final Context context, final Collection col, UUID uuid) { this.context = context; try { - workspaceItem = workspaceItemService.create(context, col, false); + if (uuid == null) { + workspaceItem = workspaceItemService.create(context, col, false); + } else { + workspaceItem = workspaceItemService.create(context, col, uuid, false, false); + } item = workspaceItem.getItem(); } catch (Exception e) { return handleException(e); From a591357f56da47aa322a319658889b501a88bb19 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:34:05 +0200 Subject: [PATCH 083/632] #9806: Use builders for comm, coll, group creation in SupervisionOrderServiceIT (cherry picked from commit 6e9181e3f7cd502b345af7d5879fa25654176c25) --- .../SupervisionOrderServiceIT.java | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/supervision/SupervisionOrderServiceIT.java b/dspace-api/src/test/java/org/dspace/supervision/SupervisionOrderServiceIT.java index 60407823485b..aa4cd8bd4e49 100644 --- a/dspace-api/src/test/java/org/dspace/supervision/SupervisionOrderServiceIT.java +++ b/dspace-api/src/test/java/org/dspace/supervision/SupervisionOrderServiceIT.java @@ -18,6 +18,7 @@ import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EPersonBuilder; import org.dspace.builder.GroupBuilder; +import org.dspace.builder.SupervisionOrderBuilder; import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; import org.dspace.content.Item; @@ -85,10 +86,10 @@ public void createSupervisionOrderTest() throws Exception { .build(); SupervisionOrder supervisionOrderOne = - supervisionOrderService.create(context, item, groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, item, groupA).build(); SupervisionOrder supervisionOrderTwo = - supervisionOrderService.create(context, item, groupB); + SupervisionOrderBuilder.createSupervisionOrder(context, item, groupB).build(); context.restoreAuthSystemState(); @@ -136,7 +137,8 @@ public void findSupervisionOrderTest() throws Exception { .build(); SupervisionOrder supervisionOrderOne = - supervisionOrderService.create(context, workspaceItem.getItem(), groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupA) + .build(); context.restoreAuthSystemState(); @@ -205,9 +207,12 @@ public void findAllSupervisionOrdersTest() throws Exception { .addMember(userB) .build(); - supervisionOrderService.create(context, workspaceItem.getItem(), groupA); - supervisionOrderService.create(context, workspaceItem.getItem(), groupB); - supervisionOrderService.create(context, workspaceItemTwo.getItem(), groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupA) + .build(); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupB) + .build(); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItemTwo.getItem(), groupA) + .build(); context.restoreAuthSystemState(); @@ -259,9 +264,12 @@ public void findSupervisionOrderByItemTest() throws Exception { .addMember(eperson) .build(); - supervisionOrderService.create(context, workspaceItem.getItem(), groupA); - supervisionOrderService.create(context, workspaceItem.getItem(), groupB); - supervisionOrderService.create(context, workspaceItemTwo.getItem(), groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupA) + .build(); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupB) + .build(); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItemTwo.getItem(), groupA) + .build(); context.restoreAuthSystemState(); @@ -310,7 +318,8 @@ public void findSupervisionOrderByItemAndGroupTest() throws Exception { .addMember(eperson) .build(); - supervisionOrderService.create(context, item, groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, item, groupA) + .build(); context.restoreAuthSystemState(); @@ -370,7 +379,8 @@ public void isSupervisorTest() throws Exception { .addMember(userB) .build(); - supervisionOrderService.create(context, workspaceItem.getItem(), groupA); + SupervisionOrderBuilder.createSupervisionOrder(context, workspaceItem.getItem(), groupA) + .build(); context.restoreAuthSystemState(); From 2616c0b59129a950d15106f442535d3d59590e67 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:35:14 +0200 Subject: [PATCH 084/632] #9806: Use builders for comm, coll, group creation in CollectionGroupRestControllerIT (cherry picked from commit f4629d8351b70ca945ffeebdf928cebfb868c349) --- .../rest/CollectionGroupRestControllerIT.java | 151 +++++++++--------- 1 file changed, 77 insertions(+), 74 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionGroupRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionGroupRestControllerIT.java index f6ab10c087ad..8d490109220d 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionGroupRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionGroupRestControllerIT.java @@ -28,9 +28,9 @@ import org.dspace.authorize.service.AuthorizeService; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.GroupBuilder; import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; -import org.dspace.content.service.CollectionService; import org.dspace.core.Constants; import org.dspace.eperson.Group; import org.dspace.eperson.service.GroupService; @@ -41,10 +41,6 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrationTest { - - @Autowired - private CollectionService collectionService; - @Autowired private GroupService groupService; @@ -68,7 +64,7 @@ public void setup() { @Test public void getCollectionAdminGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -81,7 +77,7 @@ public void getCollectionAdminGroupTest() throws Exception { @Test public void getCollectionAdminGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -95,7 +91,7 @@ public void getCollectionAdminGroupTestParentCommunityAdmin() throws Exception { @Test public void getCollectionAdminGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -109,7 +105,7 @@ public void getCollectionAdminGroupTestCollectionAdmin() throws Exception { @Test public void getCollectionAdminGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/adminGroup")) @@ -119,7 +115,7 @@ public void getCollectionAdminGroupUnAuthorizedTest() throws Exception { @Test public void getCollectionAdminGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -413,7 +409,7 @@ public void postCollectionAdminGroupCreateAdminGroupUnProcessablePermanent() thr @Test public void deleteCollectionAdminGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -428,7 +424,7 @@ public void deleteCollectionAdminGroupTest() throws Exception { @Test public void deleteCollectionAdminGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -443,7 +439,7 @@ public void deleteCollectionAdminGroupTestParentCommunityAdmin() throws Exceptio @Test public void deleteCollectionAdminGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -458,7 +454,7 @@ public void deleteCollectionAdminGroupTestCollectionAdmin() throws Exception { @Test public void deleteCollectionAdminGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/adminGroup")) @@ -474,7 +470,7 @@ public void deleteCollectionAdminGroupUnAuthorizedTest() throws Exception { @Test public void deleteCollectionAdminGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -493,7 +489,7 @@ public void deleteCollectionAdminGroupForbiddenTest() throws Exception { @Test public void deleteCollectionAdminGroupNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -512,7 +508,7 @@ public void deleteCollectionAdminGroupNotFoundTest() throws Exception { @Test public void getCollectionSubmittersGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submitters = collectionService.createSubmitters(context, collection); + Group submitters = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -525,7 +521,7 @@ public void getCollectionSubmittersGroupTest() throws Exception { @Test public void getCollectionSubmittersGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group submitters = collectionService.createSubmitters(context, collection); + Group submitters = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -539,7 +535,7 @@ public void getCollectionSubmittersGroupTestParentCommunityAdmin() throws Except @Test public void getCollectionSubmittersGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group submitters = collectionService.createSubmitters(context, collection); + Group submitters = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -553,7 +549,7 @@ public void getCollectionSubmittersGroupTestCollectionAdmin() throws Exception { @Test public void getCollectionSubmittersGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/submittersGroup")) @@ -563,7 +559,7 @@ public void getCollectionSubmittersGroupUnAuthorizedTest() throws Exception { @Test public void getCollectionSubmittersGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -860,7 +856,7 @@ public void postCollectionSubmittersGroupCreateSubmittersGroupUnProcessablePerma @Test public void deleteCollectionSubmitterGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -875,7 +871,7 @@ public void deleteCollectionSubmitterGroupTest() throws Exception { @Test public void deleteCollectionSubmittersGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -890,7 +886,7 @@ public void deleteCollectionSubmittersGroupTestParentCommunityAdmin() throws Exc @Test public void deleteCollectionSubmittersGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -905,7 +901,7 @@ public void deleteCollectionSubmittersGroupTestCollectionAdmin() throws Exceptio @Test public void deleteCollectionSubmittersGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + Group submittersGroup = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/submittersGroup")) @@ -924,7 +920,7 @@ public void deleteCollectionSubmittersGroupUnAuthorizedTest() throws Exception { @Test public void deleteCollectionSubmittersGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + Group submittersGroup = GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -945,7 +941,7 @@ public void deleteCollectionSubmittersGroupForbiddenTest() throws Exception { @Test public void deleteCollectionSubmittersGroupNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); - Group submittersGroup = collectionService.createSubmitters(context, collection); + GroupBuilder.createCollectionSubmitterGroup(context, collection).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -961,7 +957,8 @@ public void getCollectionItemReadGroupTest() throws Exception { String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -977,7 +974,8 @@ public void getCollectionDefaultItemReadGroupTestParentCommunityAdmin() throws E String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -995,7 +993,8 @@ public void getCollectionDefaultItemReadGroupTestCollectionAdmin() throws Except String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1012,7 +1011,8 @@ public void getCollectionDefaultItemReadGroupUnAuthorizedTest() throws Exception String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/itemReadGroup")) @@ -1025,7 +1025,8 @@ public void getCollectionDefaultItemReadGroupForbiddenTest() throws Exception { String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1321,7 +1322,7 @@ public void deleteCollectionDefaultItemReadGroupTest() throws Exception { String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -1345,7 +1346,7 @@ public void deleteCollectionDefaultItemReadGroupTestParentCommunityAdmin() throw String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, itemGroupString, defaultItemRead).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1367,7 +1368,7 @@ public void deleteCollectionDefaultItemReadGroupTestCollectionAdmin() throws Exc String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, itemGroupString, defaultItemRead).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1389,7 +1390,8 @@ public void deleteCollectionDefaultItemReadGroupUnAuthorizedTest() throws Except String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/itemReadGroup")) @@ -1408,7 +1410,8 @@ public void deleteCollectionDefaultItemReadGroupForbiddenTest() throws Exception String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1430,7 +1433,7 @@ public void deleteCollectionDefaultItemReadGroupNotFoundTest() throws Exception String itemGroupString = "ITEM"; int defaultItemRead = Constants.DEFAULT_ITEM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, itemGroupString, defaultItemRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, itemGroupString, defaultItemRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1445,8 +1448,8 @@ public void getCollectionBitstreamReadGroupTest() throws Exception { String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -1462,8 +1465,8 @@ public void getCollectionDefaultBitstreamReadGroupTestParentCommunityAdmin() thr String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1480,8 +1483,8 @@ public void getCollectionDefaultBitstreamReadGroupTestCollectionAdmin() throws E String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1498,8 +1501,8 @@ public void getCollectionDefaultBitstreamReadGroupUnAuthorizedTest() throws Exce String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/bitstreamReadGroup")) @@ -1512,8 +1515,8 @@ public void getCollectionDefaultBitstreamReadGroupForbiddenTest() throws Excepti String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1811,8 +1814,8 @@ public void deleteCollectionDefaultBitstreamReadGroupTest() throws Exception { String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -1835,8 +1838,8 @@ public void deleteCollectionDefaultBitstreamReadGroupTestParentCommunityAdmin() String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1859,8 +1862,8 @@ public void deleteCollectionDefaultBitstreamReadGroupTestCollectionAdmin() throw String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1882,8 +1885,8 @@ public void deleteCollectionDefaultBitstreamReadGroupUnAuthorizedTest() throws E String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + Group role = GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/bitstreamReadGroup")) @@ -1902,8 +1905,8 @@ public void deleteCollectionDefaultBitstreamReadGroupForbiddenTest() throws Exce String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1918,8 +1921,8 @@ public void deleteCollectionDefaultBitstreamReadGroupNotFoundTest() throws Excep String bitstreamGroupString = "BITSTREAM"; int defaultBitstreamRead = Constants.DEFAULT_BITSTREAM_READ; - Group role = collectionService.createDefaultReadGroup(context, collection, bitstreamGroupString, - defaultBitstreamRead); + GroupBuilder.createCollectionDefaultReadGroup(context, collection, + bitstreamGroupString, defaultBitstreamRead).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1931,7 +1934,7 @@ public void deleteCollectionDefaultBitstreamReadGroupNotFoundTest() throws Excep public void getWorkflowGroupForCollectionAndRole() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -1944,7 +1947,7 @@ public void getWorkflowGroupForCollectionAndRole() throws Exception { @Test public void getWorkflowGroupForCollectionAndRoleParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1958,7 +1961,7 @@ public void getWorkflowGroupForCollectionAndRoleParentCommunityAdmin() throws Ex @Test public void getWorkflowGroupForCollectionAndRoleWrongUUIDCollectionNotFound() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -1979,7 +1982,7 @@ public void getWorkflowGroupForCollectionAndRoleWrongRoleNotFound() throws Excep public void getWorkflowGroupCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -1994,7 +1997,7 @@ public void getWorkflowGroupCommunityAdmin() throws Exception { @Test public void getWorkflowGroupCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -2009,7 +2012,7 @@ public void getWorkflowGroupCollectionAdmin() throws Exception { @Test public void getWorkflowGroupUnAuthorized() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer")) @@ -2019,7 +2022,7 @@ public void getWorkflowGroupUnAuthorized() throws Exception { @Test public void getWorkflowGroupForbidden() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -2324,7 +2327,7 @@ public void postCollectionWorkflowGroupCreateWorkflowGroupUnProcessablePermanent @Test public void deleteCollectionWorkflowGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -2339,7 +2342,7 @@ public void deleteCollectionWorkflowGroupTest() throws Exception { @Test public void deleteCollectionWorkflowGroupTestParentCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -2355,7 +2358,7 @@ public void deleteCollectionWorkflowGroupTestParentCommunityAdmin() throws Excep @Test public void deleteCollectionWorkflowGroupTestCollectionAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -2371,7 +2374,7 @@ public void deleteCollectionWorkflowGroupTestCollectionAdmin() throws Exception @Test public void deleteCollectionWorkflowGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer")) @@ -2387,7 +2390,7 @@ public void deleteCollectionWorkflowGroupUnAuthorizedTest() throws Exception { @Test public void deleteCollectionWorkflowGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group group = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -2406,7 +2409,7 @@ public void deleteCollectionWorkflowGroupForbiddenTest() throws Exception { @Test public void deleteCollectionWorkflowGroupNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); - Group group = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -2418,7 +2421,7 @@ public void deleteCollectionWorkflowGroupNotFoundTest() throws Exception { @Test public void deleteCollectionWorkflowGroupWithPooledTaskTest() throws Exception { context.turnOffAuthorisationSystem(); - Group reviewer = workflowService.createWorkflowRoleGroup(context, collection, "reviewer"); + Group reviewer = GroupBuilder.createCollectionWorkflowRoleGroup(context, collection, "reviewer").build(); // Submit an Item into the workflow -> moves to the "reviewer" step's pool. // The role must have at least one EPerson, otherwise the WSI gets archived immediately From 365987456164b58ed508e6aaed9816b0dda27efb Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:35:43 +0200 Subject: [PATCH 085/632] #9806: Builders for comm, coll, group in CommunityAdminGroupRestControllerIT (cherry picked from commit 2d9988f77c52537f46888f27e35dbc0360299835) --- .../CommunityAdminGroupRestControllerIT.java | 52 +++++++++---------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityAdminGroupRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityAdminGroupRestControllerIT.java index 37548553b143..074a7e6a3557 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityAdminGroupRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityAdminGroupRestControllerIT.java @@ -34,8 +34,6 @@ import org.dspace.builder.GroupBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; -import org.dspace.content.service.CollectionService; -import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; @@ -49,19 +47,12 @@ public class CommunityAdminGroupRestControllerIT extends AbstractControllerIntegrationTest { - - @Autowired - private CommunityService communityService; - @Autowired private GroupService groupService; @Autowired private AuthorizeService authorizeService; - @Autowired - private CollectionService collectionService; - @Autowired private ConfigurationService configurationService; @@ -78,7 +69,7 @@ public void setup() { @Test public void getCommunityAdminGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -91,7 +82,8 @@ public void getCommunityAdminGroupTest() throws Exception { @Test public void getCommunityAdminGroupTestCommunityAdmin() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); + // TODO: this should actually be "add member", not directly setting a policy, right? authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -106,7 +98,7 @@ public void getCommunityAdminGroupTestCommunityAdmin() throws Exception { @Test public void getCommunityAdminGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - communityService.createAdministrators(context, parentCommunity); + GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); getClient().perform(get("/api/core/communities/" + parentCommunity.getID() + "/adminGroup")) @@ -116,7 +108,7 @@ public void getCommunityAdminGroupUnAuthorizedTest() throws Exception { @Test public void getCommunityAdminGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - communityService.createAdministrators(context, parentCommunity); + GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); getClient(token).perform(get("/api/core/communities/" + parentCommunity.getID() + "/adminGroup")) @@ -379,7 +371,7 @@ public void postCommunityAdminGroupCreateAdminGroupUnProcessablePermanent() thro @Test public void deleteCommunityAdminGroupTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); @@ -397,7 +389,7 @@ public void deleteCommunityAdminGroupTestCommunityAdmin() throws Exception { Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) .withName("Sub Community") .build(); - Group adminGroup = communityService.createAdministrators(context, child1); + GroupBuilder.createCommunityAdminGroup(context, child1).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); context.restoreAuthSystemState(); @@ -412,7 +404,7 @@ public void deleteCommunityAdminGroupTestCommunityAdmin() throws Exception { @Test public void deleteCommunityAdminGroupUnAuthorizedTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); getClient().perform(delete("/api/core/communities/" + parentCommunity.getID() + "/adminGroup")) @@ -429,7 +421,7 @@ public void deleteCommunityAdminGroupUnAuthorizedTest() throws Exception { @Test public void deleteCommunityAdminGroupForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -449,7 +441,7 @@ public void deleteCommunityAdminGroupForbiddenTest() throws Exception { @Test public void deleteCommunityAdminGroupNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); context.restoreAuthSystemState(); String token = getAuthToken(eperson.getEmail(), password); @@ -462,7 +454,7 @@ public void deleteCommunityAdminGroupNotFoundTest() throws Exception { public void communityAdminAddMembersToCommunityAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); configurationService.setProperty("core.authorization.community-admin.admin-group", false); @@ -489,7 +481,7 @@ public void communityAdminAddMembersToCommunityAdminGroupPropertySetToFalse() th public void communityAdminRemoveMembersFromCommunityAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); context.restoreAuthSystemState(); @@ -526,7 +518,7 @@ public void communityAdminRemoveMembersFromCommunityAdminGroupPropertySetToFalse public void communityAdminAddChildGroupToCommunityAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); configurationService.setProperty("core.authorization.community-admin.admin-group", false); @@ -554,7 +546,7 @@ public void communityAdminAddChildGroupToCommunityAdminGroupPropertySetToFalse() public void communityAdminRemoveChildGroupFromCommunityAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = communityService.createAdministrators(context, parentCommunity); + Group adminGroup = GroupBuilder.createCommunityAdminGroup(context, parentCommunity).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -591,7 +583,9 @@ public void communityAdminRemoveChildGroupFromCommunityAdminGroupPropertySetToFa public void communityAdminAddChildGroupToCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + // TODO: Why is this test in CommunityAdmin? it seems to purely be a collection group test? + // copy paste gone wrong and we should actually be testing for community admin group sub? + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -617,7 +611,9 @@ public void communityAdminAddChildGroupToCollectionAdminGroupSuccess() throws Ex public void communityAdminRemoveChildGroupFromCollectionAdminGroupSuccess() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + // TODO: Why is this test in CommunityAdmin? it seems to purely be a collection group test? + // copy paste gone wrong and we should actually be testing for community admin group sub? + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); @@ -653,7 +649,7 @@ public void communityAdminRemoveChildGroupFromCollectionAdminGroupSuccess() thro public void communityAdminAddMembersToCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false); @@ -681,7 +677,7 @@ public void communityAdminAddMembersToCollectionAdminGroupPropertySetToFalse() t public void communityAdminRemoveMembersFromCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build(); context.restoreAuthSystemState(); @@ -719,7 +715,7 @@ public void communityAdminRemoveMembersFromCollectionAdminGroupPropertySetToFals public void communityAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false); @@ -748,7 +744,7 @@ public void communityAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse( public void communityAdminRemoveChildGroupFromCollectionAdminGroupPropertySetToFalse() throws Exception { context.turnOffAuthorisationSystem(); - Group adminGroup = collectionService.createAdministrators(context, collection); + Group adminGroup = GroupBuilder.createCollectionAdminGroup(context, collection).build(); authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson); Group group = GroupBuilder.createGroup(context).withName("testGroup").build(); context.restoreAuthSystemState(); From 76719f73f2e8e01aba9ad750fa6f1b5a2f34c4d3 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 15:58:59 +0200 Subject: [PATCH 086/632] #9806: Update object cleanup in GroupRestRepositoryIT (cherry picked from commit 8cfb433c40ad01f348461a2c656665d1891de398) --- .../app/rest/GroupRestRepositoryIT.java | 952 +++++------------- 1 file changed, 239 insertions(+), 713 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java index bdd13b97ff79..ff8aea493aef 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java @@ -59,14 +59,11 @@ import org.dspace.content.Community; import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; -import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.core.I18nUtil; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.eperson.factory.EPersonServiceFactory; -import org.dspace.eperson.service.EPersonService; import org.dspace.eperson.service.GroupService; import org.dspace.services.ConfigurationService; import org.hamcrest.Matchers; @@ -757,263 +754,136 @@ public void addChildGroupTest() throws Exception { @Test public void addChildGroupCommunityAdminTest() throws Exception { - CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - Community community = null; - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - community = CommunityBuilder.createCommunity(context).build(); - parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) - .addMember(eperson) - .build(); - childGroup1 = GroupBuilder.createGroup(context).build(); - childGroup2 = GroupBuilder.createGroup(context).build(); - - groupService.update(context, parentGroup); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isNoContent()); + Community community = CommunityBuilder.createCommunity(context).build(); + Group parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + Group childGroup1 = GroupBuilder.createGroup(context).build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isNoContent()); - assertTrue( - groupService.isMember(parentGroup, childGroup1) - ); + parentGroup = context.reloadEntity(parentGroup); + childGroup1 = context.reloadEntity(childGroup1); + childGroup2 = context.reloadEntity(childGroup2); - assertTrue( - groupService.isMember(parentGroup, childGroup2) - ); + assertTrue( + groupService.isMember(parentGroup, childGroup1) + ); - } finally { - // TODO: Can we remove these lines now that we are creating them with the builder? - if (community != null) { - CommunityBuilder.deleteCommunity(community.getID()); - } - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + assertTrue( + groupService.isMember(parentGroup, childGroup2) + ); } @Test public void addChildGroupForbiddenTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup1 = GroupBuilder.createGroup(context).build(); - childGroup2 = GroupBuilder.createGroup(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isForbidden()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup1 = GroupBuilder.createGroup(context).build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isForbidden()); } @Test public void addChildGroupUnauthorizedTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup1 = GroupBuilder.createGroup(context).build(); - childGroup2 = GroupBuilder.createGroup(context).build(); + context.turnOffAuthorisationSystem(); - context.commit(); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup1 = GroupBuilder.createGroup(context).build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.commit(); - context.restoreAuthSystemState(); - getClient().perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isUnauthorized()); + parentGroup = context.reloadEntity(parentGroup); + childGroup1 = context.reloadEntity(childGroup1); + childGroup2 = context.reloadEntity(childGroup2); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + context.restoreAuthSystemState(); + getClient().perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isUnauthorized()); } @Test public void addChildGroupNotFoundTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup1 = GroupBuilder.createGroup(context).build(); - childGroup2 = GroupBuilder.createGroup(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup1 = context.reloadEntity(childGroup1); - childGroup2 = context.reloadEntity(childGroup2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isNotFound()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup1 = GroupBuilder.createGroup(context).build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isNotFound()); } @Test public void addChildGroupUnprocessableTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup1 = null; - Group childGroup2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup1 = GroupBuilder.createGroup(context) - .withParent(parentGroup) - .build(); - childGroup2 = GroupBuilder.createGroup(context).build(); - groupService.update(context, childGroup1); - -// context.commit(); -// -// parentGroup = context.reloadEntity(parentGroup); -// childGroup1 = context.reloadEntity(childGroup1); -// childGroup2 = context.reloadEntity(childGroup2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup1 = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); + Group childGroup2 = GroupBuilder.createGroup(context).build(); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/123456789\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isUnprocessableEntity()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - // TODO - confirm with reviewers that this is a mistake - it actually should be No Content - // (see AddMember test) but was incorrectly expecting 422? - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() - ) - ).andExpect(status().isNoContent()); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/123456789\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isUnprocessableEntity()); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup1 != null) { - GroupBuilder.deleteGroup(childGroup1.getID()); - } - if (childGroup2 != null) { - GroupBuilder.deleteGroup(childGroup2.getID()); - } - } + // TODO - confirm with reviewers that this is a mistake - it actually should be No Content + // (see AddMember test) but was incorrectly expecting 422? + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + childGroup1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + childGroup2.getID() + ) + ).andExpect(status().isNoContent()); } @Test @@ -1081,251 +951,118 @@ public void addMemberTest() throws Exception { @Test public void addMemberCommunityAdminTest() throws Exception { - CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Community community = null; - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - community = CommunityBuilder.createCommunity(context).build(); - parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) - .addMember(eperson) - .build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isNoContent()); + Community community = CommunityBuilder.createCommunity(context).build(); + Group parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + .addMember(eperson) + .build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isNoContent()); - assertTrue( - groupService.isMember(context, member1, parentGroup) - ); + parentGroup = context.reloadEntity(parentGroup); + member1 = context.reloadEntity(member1); + member2 = context.reloadEntity(member2); - assertTrue( - groupService.isMember(context, member2, parentGroup) - ); + assertTrue( + groupService.isMember(context, member1, parentGroup) + ); - } finally { - if (community != null) { - CommunityBuilder.deleteCommunity(community.getID()); - } - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + assertTrue( + groupService.isMember(context, member2, parentGroup) + ); } @Test public void addMemberForbiddenTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isForbidden()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isForbidden()); } @Test public void addMemberUnauthorizedTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - getClient().perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isUnauthorized()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + context.restoreAuthSystemState(); + getClient().perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isUnauthorized()); } @Test public void addMemberNotFoundTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); - getClient(authToken).perform( - post("/api/eperson/groups/" + UUID.randomUUID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isNotFound()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken).perform( + post("/api/eperson/groups/" + UUID.randomUUID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/" + member1.getID() + "/\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isNotFound()); } @Test public void addMemberUnprocessableTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member1 = null; - EPerson member2 = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - member1 = EPersonBuilder.createEPerson(context).build(); - member2 = EPersonBuilder.createEPerson(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member1 = context.reloadEntity(member1); - member2 = context.reloadEntity(member2); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + Group parentGroup = GroupBuilder.createGroup(context).build(); + EPerson member1 = EPersonBuilder.createEPerson(context).build(); + EPerson member2 = EPersonBuilder.createEPerson(context).build(); - getClient(authToken).perform( - post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") - .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) - .content(REST_SERVER_URL + "eperson/groups/123456789\n" - + REST_SERVER_URL + "eperson/groups/" + member2.getID() - ) - ).andExpect(status().isUnprocessableEntity()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member1 != null) { - EPersonBuilder.deleteEPerson(member1.getID()); - } - if (member2 != null) { - EPersonBuilder.deleteEPerson(member2.getID()); - } - } + getClient(authToken).perform( + post("/api/eperson/groups/" + parentGroup.getID() + "/epersons") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content(REST_SERVER_URL + "eperson/groups/123456789\n" + + REST_SERVER_URL + "eperson/groups/" + member2.getID() + ) + ).andExpect(status().isUnprocessableEntity()); } @Test @@ -1378,29 +1115,18 @@ public void removeChildGroupTest() throws Exception { @Test public void removeChildGroupCommunityAdminTest() throws Exception { - CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - Community community = null; - Group parentGroup = null; - Group childGroup = null; - - try { context.turnOffAuthorisationSystem(); - community = CommunityBuilder.createCommunity(context).build(); - parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + Community community = CommunityBuilder.createCommunity(context).build(); + Group parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) .addMember(eperson) .build(); - childGroup = GroupBuilder.createGroup(context) + Group childGroup = GroupBuilder.createGroup(context) .withParent(parentGroup) .build(); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); - context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); getClient(authToken).perform( @@ -1413,163 +1139,71 @@ public void removeChildGroupCommunityAdminTest() throws Exception { assertFalse( groupService.isMember(parentGroup, childGroup) ); - - } finally { - if (community != null) { - CommunityBuilder.deleteCommunity(community.getID()); - } - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } } @Test public void removeChildGroupForbiddenTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup = GroupBuilder.createGroup(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID()) - ).andExpect(status().isForbidden()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup = GroupBuilder.createGroup(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID()) + ).andExpect(status().isForbidden()); } @Test public void removeChildGroupUnauthorizedTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup = GroupBuilder.createGroup(context).build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - getClient().perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID()) - ).andExpect(status().isUnauthorized()); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup = GroupBuilder.createGroup(context).build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } + context.restoreAuthSystemState(); + getClient().perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID()) + ).andExpect(status().isUnauthorized()); } @Test public void removeChildGroupNotFoundTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup = GroupBuilder.createGroup(context) - .withParent(parentGroup) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); - getClient(authToken).perform( - delete("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups/" + childGroup.getID()) - ).andExpect(status().isNotFound()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } + getClient(authToken).perform( + delete("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups/" + childGroup.getID()) + ).andExpect(status().isNotFound()); } @Test public void removeChildGroupUnprocessableTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - - Group parentGroup = null; - Group childGroup = null; - - try { - context.turnOffAuthorisationSystem(); - - parentGroup = GroupBuilder.createGroup(context).build(); - childGroup = GroupBuilder.createGroup(context) - .withParent(parentGroup) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - childGroup = context.reloadEntity(childGroup); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + Group parentGroup = GroupBuilder.createGroup(context).build(); + Group childGroup = GroupBuilder.createGroup(context) + .withParent(parentGroup) + .build(); - getClient(authToken).perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + UUID.randomUUID()) - ).andExpect(status().isUnprocessableEntity()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (childGroup != null) { - GroupBuilder.deleteGroup(childGroup.getID()); - } - } + getClient(authToken).perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + UUID.randomUUID()) + ).andExpect(status().isUnprocessableEntity()); } @Test @@ -1613,31 +1247,19 @@ public void removeMemberTest() throws Exception { @Test public void removeMemberCommunityAdminTest() throws Exception { - CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Community community = null; - Group parentGroup = null; - EPerson member = null; - try { context.turnOffAuthorisationSystem(); - community = CommunityBuilder.createCommunity(context).build(); - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) + Community community = CommunityBuilder.createCommunity(context).build(); + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createCommunityAdminGroup(context, community) .addMember(member) .addMember(eperson) .build(); assertTrue(groupService.isMember(context, member, parentGroup)); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); - context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); getClient(authToken).perform( @@ -1650,171 +1272,75 @@ public void removeMemberCommunityAdminTest() throws Exception { assertFalse( groupService.isMember(context, member, parentGroup) ); - - } finally { - if (community != null) { - CommunityBuilder.deleteCommunity(community.getID()); - } - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } } @Test public void removeMemberForbiddenTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member = null; - - try { - context.turnOffAuthorisationSystem(); - - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createGroup(context) - .addMember(member) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - getClient(authToken).perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID()) - ).andExpect(status().isForbidden()); + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } + context.restoreAuthSystemState(); + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID()) + ).andExpect(status().isForbidden()); } @Test public void removeMemberUnauthorizedTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member = null; - - try { - context.turnOffAuthorisationSystem(); - - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createGroup(context) - .addMember(member) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - getClient().perform( - delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID()) - ).andExpect(status().isUnauthorized()); + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } + context.restoreAuthSystemState(); + getClient().perform( + delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID()) + ).andExpect(status().isUnauthorized()); } @Test public void removeMemberNotFoundTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member = null; - - try { - context.turnOffAuthorisationSystem(); - - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createGroup(context) - .addMember(member) - .build(); - - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); + context.turnOffAuthorisationSystem(); - context.restoreAuthSystemState(); - String authToken = getAuthToken(admin.getEmail(), password); + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createGroup(context) + .addMember(member) + .build(); - getClient(authToken).perform( - delete("/api/eperson/groups/" + UUID.randomUUID() + "/epersons/" + member.getID()) - ).andExpect(status().isNotFound()); + context.restoreAuthSystemState(); + String authToken = getAuthToken(admin.getEmail(), password); - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } + getClient(authToken).perform( + delete("/api/eperson/groups/" + UUID.randomUUID() + "/epersons/" + member.getID()) + ).andExpect(status().isNotFound()); } @Test public void removeMemberUnprocessableTest() throws Exception { - GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); - EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - - Group parentGroup = null; - EPerson member = null; - - try { context.turnOffAuthorisationSystem(); - member = EPersonBuilder.createEPerson(context).build(); - parentGroup = GroupBuilder.createGroup(context) + EPerson member = EPersonBuilder.createEPerson(context).build(); + Group parentGroup = GroupBuilder.createGroup(context) .addMember(member) .build(); - context.commit(); - - parentGroup = context.reloadEntity(parentGroup); - member = context.reloadEntity(member); - context.restoreAuthSystemState(); String authToken = getAuthToken(admin.getEmail(), password); getClient(authToken).perform( delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + UUID.randomUUID()) ).andExpect(status().isUnprocessableEntity()); - - } finally { - if (parentGroup != null) { - GroupBuilder.deleteGroup(parentGroup.getID()); - } - if (member != null) { - EPersonBuilder.deleteEPerson(member.getID()); - } - } } @Test From 7d7edcb4c6ab8de23b9d3d8a868fd706294b9523 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 16:43:36 +0200 Subject: [PATCH 087/632] #9806: Align provider reg in CreateMissingIdentifiersIT with other tests VersionedHandlerIdentifierProviderIT uses this registerProvider method which looks more reliable and doesn't do a refresh/reload of applicationContext after (which I suspected might have an odd interaction with VersioningWithRelationshipsIT and its createBean() calls?) (cherry picked from commit 90536e443b7fedef0481a34326cafc58fb334396) --- .../general/CreateMissingIdentifiersIT.java | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java index 2a07799deee5..8038a7153325 100644 --- a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java +++ b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java @@ -10,6 +10,8 @@ import static org.junit.Assert.assertEquals; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; @@ -19,7 +21,10 @@ import org.dspace.content.Item; import org.dspace.core.factory.CoreServiceFactory; import org.dspace.curate.Curator; +import org.dspace.identifier.IdentifierProvider; +import org.dspace.identifier.IdentifierServiceImpl; import org.dspace.identifier.VersionedHandleIdentifierProviderWithCanonicalHandles; +import org.dspace.kernel.ServiceManager; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; import org.junit.After; @@ -32,10 +37,23 @@ */ public class CreateMissingIdentifiersIT extends AbstractIntegrationTestWithDatabase { + private ServiceManager serviceManager; + private IdentifierServiceImpl identifierService; private static final String P_TASK_DEF = "plugin.named.org.dspace.curate.CurationTask"; private static final String TASK_NAME = "test"; + @Override + public void setUp() throws Exception { + super.setUp(); + context.turnOffAuthorisationSystem(); + + serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); + identifierService = serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0); + // Clean out providers to avoid any being used for creation of community and collection + identifierService.setProviders(new ArrayList<>()); + } + @Test public void testPerform() throws IOException { @@ -67,11 +85,7 @@ public void testPerform() /* * Now install an incompatible provider to make the task fail. */ - DSpaceServicesFactory.getInstance() - .getServiceManager() - .registerServiceClass( - VersionedHandleIdentifierProviderWithCanonicalHandles.class.getCanonicalName(), - VersionedHandleIdentifierProviderWithCanonicalHandles.class); + registerProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); curator.curate(context, item); System.out.format("With incompatible provider, result is '%s'.\n", @@ -86,4 +100,14 @@ public void destroy() throws Exception { super.destroy(); DSpaceServicesFactory.getInstance().getServiceManager().getApplicationContext().refresh(); } + + private void registerProvider(Class type) { + // Register our new provider + serviceManager.registerServiceClass(type.getName(), type); + IdentifierProvider identifierProvider = + (IdentifierProvider) serviceManager.getServiceByName(type.getName(), type); + + // Overwrite the identifier-service's providers with the new one to ensure only this provider is used + identifierService.setProviders(List.of(identifierProvider)); + } } From 59ecfb8360b761980dfc14d3ca7ab0b9bd6bfc7d Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 16:45:05 +0200 Subject: [PATCH 088/632] #9806: Use builders for creation in VersioningWithRelationshipsIT I am a bit uncertain about the createBean() calls here, why do we not simply *get* the configured beans using the service manager instead, but will look at that in a separate change (cherry picked from commit 3521ab6d3598e716cc9fe8e938e883b302006580) --- .../VersioningWithRelationshipsIT.java | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java index 44653300e0de..accc52d0d830 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java @@ -49,6 +49,7 @@ import org.dspace.builder.ItemBuilder; import org.dspace.builder.RelationshipBuilder; import org.dspace.builder.RelationshipTypeBuilder; +import org.dspace.builder.VersionBuilder; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; @@ -62,8 +63,6 @@ import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.Version; -import org.dspace.versioning.factory.VersionServiceFactory; -import org.dspace.versioning.service.VersioningService; import org.hamcrest.Matcher; import org.junit.Assert; import org.junit.Before; @@ -74,8 +73,6 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa private final RelationshipService relationshipService = ContentServiceFactory.getInstance().getRelationshipService(); - private final VersioningService versioningService = - VersionServiceFactory.getInstance().getVersionService(); private final WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService(); private final InstallItemService installItemService = @@ -291,7 +288,7 @@ public void test_createNewVersionOfItemOnLeftSideOfRelationships() throws Except // create a new version of the publication // ///////////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPublication); + Version newVersion = VersionBuilder.createVersion(context, originalPublication, "test").build(); Item newPublication = newVersion.getItem(); assertNotSame(originalPublication, newPublication); @@ -567,7 +564,7 @@ public void test_createNewVersionOfItemAndModifyRelationships() throws Exception // create a new version of the publication // ///////////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPublication); + Version newVersion = VersionBuilder.createVersion(context, originalPublication, "test").build(); Item newPublication = newVersion.getItem(); assertNotSame(originalPublication, newPublication); @@ -927,7 +924,7 @@ public void test_createNewVersionOfItemOnRightSideOfRelationships() throws Excep // create a new version of the person // //////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPerson); + Version newVersion = VersionBuilder.createVersion(context, originalPerson, "test").build(); Item newPerson = newVersion.getItem(); assertNotSame(originalPerson, newPerson); @@ -1300,7 +1297,7 @@ public void test_createNewVersionOfItemAndVerifyMetadataOrder() throws Exception // create new version of publication // /////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPublication); + Version newVersion = VersionBuilder.createVersion(context, originalPublication, "test").build(); Item newPublication = newVersion.getItem(); assertNotSame(originalPublication, newPublication); @@ -1463,7 +1460,7 @@ public void test_createNewVersionOfItemWithAddRemoveMove() throws Exception { // create a new version of the publication // ///////////////////////////////////////////// - Version newVersion = versioningService.createNewVersion(context, originalPublication); + Version newVersion = VersionBuilder.createVersion(context, originalPublication, "test").build(); Item newPublication = newVersion.getItem(); assertNotSame(originalPublication, newPublication); @@ -1782,7 +1779,7 @@ public void test_placeRecalculationAfterDelete() throws Exception { // create new version - volume 1.2 // ///////////////////////////////////// - Item v1_2 = versioningService.createNewVersion(context, v1_1).getItem(); + Item v1_2 = VersionBuilder.createVersion(context, v1_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, v1_2)); context.commit(); @@ -1790,7 +1787,7 @@ public void test_placeRecalculationAfterDelete() throws Exception { // create new version - issue 3.2 // //////////////////////////////////// - Item i3_2 = versioningService.createNewVersion(context, i3_1).getItem(); + Item i3_2 = VersionBuilder.createVersion(context, i3_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, i3_2)); context.commit(); @@ -2316,7 +2313,7 @@ public void test_placeRecalculationAfterDelete_complex() throws Exception { // create new version - person 3.2 // ///////////////////////////////////// - Item pe3_2 = versioningService.createNewVersion(context, pe3_1).getItem(); + Item pe3_2 = VersionBuilder.createVersion(context, pe3_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, pe3_2)); context.commit(); @@ -2324,7 +2321,7 @@ public void test_placeRecalculationAfterDelete_complex() throws Exception { // create new version - project 3.2 // ////////////////////////////////////// - Item pr3_2 = versioningService.createNewVersion(context, pr3_1).getItem(); + Item pr3_2 = VersionBuilder.createVersion(context, pr3_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, pr3_2)); context.commit(); @@ -3056,7 +3053,7 @@ public void test_placeRecalculationNoUseForPlace() throws Exception { // create new version - volume 1.2 // ///////////////////////////////////// - Item v1_2 = versioningService.createNewVersion(context, v1_1).getItem(); + Item v1_2 = VersionBuilder.createVersion(context, v1_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, v1_2)); context.commit(); @@ -3064,7 +3061,7 @@ public void test_placeRecalculationNoUseForPlace() throws Exception { // create new version - issue 3.2 // //////////////////////////////////// - Item i3_2 = versioningService.createNewVersion(context, i3_1).getItem(); + Item i3_2 = VersionBuilder.createVersion(context, i3_1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, i3_2)); context.commit(); @@ -3509,7 +3506,7 @@ public void test_virtualMetadataPreserved() throws Exception { // create a new version of publication 1 and archive // /////////////////////////////////////////////////////// - Item publication1V2 = versioningService.createNewVersion(context, publication1V1).getItem(); + Item publication1V2 = VersionBuilder.createVersion(context, publication1V1, "test").build().getItem(); installItemService.installItem(context, workspaceItemService.findByItem(context, publication1V2)); context.dispatchEvents(); @@ -3517,7 +3514,7 @@ public void test_virtualMetadataPreserved() throws Exception { // create new version of person 1 // //////////////////////////////////// - Item person1V2 = versioningService.createNewVersion(context, person1V1).getItem(); + Item person1V2 = VersionBuilder.createVersion(context, person1V1, "test").build().getItem(); // update "Smith, Donald" to "Smith, D." itemService.replaceMetadata( context, person1V2, "person", "givenName", null, null, "D.", @@ -3853,7 +3850,7 @@ public void test_virtualMetadataPreserved() throws Exception { // create new version of person 2 // //////////////////////////////////// - Item person2V2 = versioningService.createNewVersion(context, person2V1).getItem(); + Item person2V2 = VersionBuilder.createVersion(context, person2V1, "test").build().getItem(); Relationship rel1 = getRelationship(publication1V2, isAuthorOfPublication, person2V2); assertNotNull(rel1); rel1.setRightwardValue("Doe, Jane Jr"); From 8f8680179695c4dad637ac798eff0bc6fb47b1c8 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 17:15:15 +0200 Subject: [PATCH 089/632] #9806: Set explicit id provider before VersioningWithRelationshipsIT (cherry picked from commit 4af690065038d9cb401d0fa1fc5fbfe0fa1fe2c7) --- .../VersioningWithRelationshipsIT.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java index accc52d0d830..10cb30cd52b9 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java @@ -60,6 +60,9 @@ import org.dspace.content.virtual.VirtualMetadataPopulator; import org.dspace.core.Constants; import org.dspace.discovery.SolrSearchCore; +import org.dspace.identifier.IdentifierProvider; +import org.dspace.identifier.IdentifierServiceImpl; +import org.dspace.identifier.VersionedHandleIdentifierProvider; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.Version; @@ -81,7 +84,7 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa ContentServiceFactory.getInstance().getItemService(); private final SolrSearchCore solrSearchCore = DSpaceServicesFactory.getInstance().getServiceManager().getServicesByType(SolrSearchCore.class).get(0); - + private IdentifierServiceImpl identifierService; protected Community community; protected Collection collection; protected EntityType publicationEntityType; @@ -98,6 +101,22 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa protected RelationshipType isIssueOfJournalVolume; protected RelationshipType isProjectOfPerson; + private void registerProvider(Class type) { + // Register our new provider + IdentifierProvider identifierProvider = + (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(type.getName(), type); + if (identifierProvider == null) { + DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); + identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(type.getName(), type); + } + + // Overwrite the identifier-service's providers with the new one to ensure only this provider is used + identifierService = DSpaceServicesFactory.getInstance().getServiceManager() + .getServicesByType(IdentifierServiceImpl.class).get(0); + identifierService.setProviders(new ArrayList<>()); + identifierService.setProviders(List.of(identifierProvider)); + } + @Override @Before public void setUp() throws Exception { @@ -105,6 +124,9 @@ public void setUp() throws Exception { context.turnOffAuthorisationSystem(); + + registerProvider(VersionedHandleIdentifierProvider.class); + community = CommunityBuilder.createCommunity(context) .withName("community") .build(); From ad7499f245be07aa9a5715b9eaa91bf164b79515 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 6 Sep 2024 17:58:23 +0200 Subject: [PATCH 090/632] #9806: Move cleanup of handle provider to destroy in VersionedHandleIdentifierProviderIT (cherry picked from commit f6cabe648dfcda786afdf7d5411dc3d7ad85c405) --- .../VersioningWithRelationshipsIT.java | 23 ------------------- .../VersionedHandleIdentifierProviderIT.java | 22 ++++++++++++++++-- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java index 10cb30cd52b9..3acc4ca146ee 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java @@ -60,9 +60,6 @@ import org.dspace.content.virtual.VirtualMetadataPopulator; import org.dspace.core.Constants; import org.dspace.discovery.SolrSearchCore; -import org.dspace.identifier.IdentifierProvider; -import org.dspace.identifier.IdentifierServiceImpl; -import org.dspace.identifier.VersionedHandleIdentifierProvider; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.Version; @@ -84,7 +81,6 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa ContentServiceFactory.getInstance().getItemService(); private final SolrSearchCore solrSearchCore = DSpaceServicesFactory.getInstance().getServiceManager().getServicesByType(SolrSearchCore.class).get(0); - private IdentifierServiceImpl identifierService; protected Community community; protected Collection collection; protected EntityType publicationEntityType; @@ -101,22 +97,6 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa protected RelationshipType isIssueOfJournalVolume; protected RelationshipType isProjectOfPerson; - private void registerProvider(Class type) { - // Register our new provider - IdentifierProvider identifierProvider = - (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(type.getName(), type); - if (identifierProvider == null) { - DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); - identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(type.getName(), type); - } - - // Overwrite the identifier-service's providers with the new one to ensure only this provider is used - identifierService = DSpaceServicesFactory.getInstance().getServiceManager() - .getServicesByType(IdentifierServiceImpl.class).get(0); - identifierService.setProviders(new ArrayList<>()); - identifierService.setProviders(List.of(identifierProvider)); - } - @Override @Before public void setUp() throws Exception { @@ -124,9 +104,6 @@ public void setUp() throws Exception { context.turnOffAuthorisationSystem(); - - registerProvider(VersionedHandleIdentifierProvider.class); - community = CommunityBuilder.createCommunity(context) .withName("community") .build(); diff --git a/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java b/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java index 7e549f6cae33..57acf1f1c453 100644 --- a/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java +++ b/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java @@ -24,6 +24,7 @@ import org.dspace.content.Item; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; +import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -57,13 +58,30 @@ public void setUp() throws Exception { .build(); } + @After + @Override + public void destroy() throws Exception { + super.destroy(); + // After this test has finished running, refresh application context and + // set the expected 'default' versioned handle provider back to ensure other tests don't fail + DSpaceServicesFactory.getInstance().getServiceManager().getApplicationContext().refresh(); + } + private void registerProvider(Class type) { // Register our new provider - serviceManager.registerServiceClass(type.getName(), type); IdentifierProvider identifierProvider = - (IdentifierProvider) serviceManager.getServiceByName(type.getName(), type); + (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + if (identifierProvider == null) { + DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); + identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + } // Overwrite the identifier-service's providers with the new one to ensure only this provider is used + identifierService = DSpaceServicesFactory.getInstance().getServiceManager() + .getServicesByType(IdentifierServiceImpl.class).get(0); + identifierService.setProviders(new ArrayList<>()); identifierService.setProviders(List.of(identifierProvider)); } From 724f821bee86479663671f0eda94341c0e34ec85 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 25 Jun 2024 13:45:31 +0200 Subject: [PATCH 091/632] Fix request a copy link token generation Ensure DSpace URLs with extra segments are included fully in the generated link --- .../rest/repository/RequestItemRepository.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 5945d516600a..a666b673530f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.validator.routines.EmailValidator; import org.apache.http.client.utils.URIBuilder; import org.apache.logging.log4j.LogManager; @@ -287,19 +288,17 @@ public Class getDomainClass() { * Generate a link back to DSpace, to act on a request. * * @param token identifies the request. - * @return URL to the item request API, with the token as request parameter - * "token". + * @return URL to the item request API, with /request-a-copy/{token} as the last URL segments * @throws URISyntaxException passed through. * @throws MalformedURLException passed through. */ private String getLinkTokenEmail(String token) throws URISyntaxException, MalformedURLException { final String base = configurationService.getProperty("dspace.ui.url"); - - URI link = new URIBuilder(base) - .setPathSegments("request-a-copy", token) - .build(); - - return link.toURL().toExternalForm(); + URIBuilder uriBuilder = new URIBuilder(base); + // Add request-a-copy/token to the existing path (without breaking /sub/dir dspace URLs) + URI uri = uriBuilder.setPath(StringUtils.stripEnd(uriBuilder.getPath(), "") + + "/request-a-copy/" + token).build(); + return uri.toURL().toExternalForm(); } } From cdb255fecaf2fb06944137d359cc188a36e5ee66 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 25 Jun 2024 14:36:17 +0200 Subject: [PATCH 092/632] Make RequestItemRepository#getLinkTokenEmail public, write test --- .../repository/RequestItemRepository.java | 2 +- .../app/rest/RequestItemRepositoryIT.java | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index a666b673530f..3a3444615344 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -292,7 +292,7 @@ public Class getDomainClass() { * @throws URISyntaxException passed through. * @throws MalformedURLException passed through. */ - private String getLinkTokenEmail(String token) + public String getLinkTokenEmail(String token) throws URISyntaxException, MalformedURLException { final String base = configurationService.getProperty("dspace.ui.url"); URIBuilder uriBuilder = new URIBuilder(base); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java index 2fb7dbbc969d..065660f2c879 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java @@ -29,6 +29,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.sql.SQLException; import java.time.temporal.ChronoUnit; import java.util.Date; @@ -56,10 +58,12 @@ import org.dspace.content.Bitstream; import org.dspace.content.Collection; import org.dspace.content.Item; +import org.dspace.services.ConfigurationService; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; /** * @@ -82,6 +86,12 @@ public class RequestItemRepositoryIT @Autowired(required = true) RequestItemService requestItemService; + @Autowired + ApplicationContext applicationContext; + + @Autowired + private ConfigurationService configurationService; + private Collection collection; private Item item; @@ -610,4 +620,23 @@ public void testGetDomainClass() { Class instanceClass = instance.getDomainClass(); assertEquals("Wrong domain class", RequestItemRest.class, instanceClass); } + + /** + * Test that generated links include the correct base URL, even if it has extra URL segments + */ + @Test + public void testGetLinkTokenEmail() throws MalformedURLException, URISyntaxException { + RequestItemRepository instance = applicationContext.getBean( + RequestItemRest.CATEGORY + '.' + RequestItemRest.PLURAL_NAME, + RequestItemRepository.class); + String currentDspaceUrl = configurationService.getProperty("dspace.ui.url"); + String newDspaceUrl = currentDspaceUrl + "/subdir"; + // Add a /subdir to the url for this test + configurationService.setProperty("dspace.ui.url", newDspaceUrl); + String expectedUrl = newDspaceUrl + "/request-a-copy/token"; + String generatedLink = instance.getLinkTokenEmail("token"); + // The URLs should match + assertEquals(expectedUrl, generatedLink); + configurationService.reloadConfig(); + } } From 64255ffb05788898ee37baef7d42e1e89f98764a Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 10 Jul 2024 16:04:34 +0200 Subject: [PATCH 093/632] #9668: Ensure proper handling of non-subpath URLs in link tokens --- .../repository/RequestItemRepository.java | 5 +++-- .../app/rest/RequestItemRepositoryIT.java | 20 +++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 3a3444615344..71c46b4dc843 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -297,8 +297,9 @@ public String getLinkTokenEmail(String token) final String base = configurationService.getProperty("dspace.ui.url"); URIBuilder uriBuilder = new URIBuilder(base); // Add request-a-copy/token to the existing path (without breaking /sub/dir dspace URLs) - URI uri = uriBuilder.setPath(StringUtils.stripEnd(uriBuilder.getPath(), "") - + "/request-a-copy/" + token).build(); + URI uri = uriBuilder.setPath( + (uriBuilder.getPath() == null ? "" : StringUtils.stripEnd(uriBuilder.getPath(), "")) + + "/request-a-copy/" + token).build(); return uri.toURL().toExternalForm(); } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java index 065660f2c879..f8732d0826e3 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java @@ -622,10 +622,10 @@ public void testGetDomainClass() { } /** - * Test that generated links include the correct base URL, even if it has extra URL segments + * Test that generated links include the correct base URL, where the UI URL has a subpath like /subdir */ @Test - public void testGetLinkTokenEmail() throws MalformedURLException, URISyntaxException { + public void testGetLinkTokenEmailWithSubPath() throws MalformedURLException, URISyntaxException { RequestItemRepository instance = applicationContext.getBean( RequestItemRest.CATEGORY + '.' + RequestItemRest.PLURAL_NAME, RequestItemRepository.class); @@ -639,4 +639,20 @@ public void testGetLinkTokenEmail() throws MalformedURLException, URISyntaxExcep assertEquals(expectedUrl, generatedLink); configurationService.reloadConfig(); } + + /** + * Test that generated links include the correct base URL, with NO subpath elements + */ + @Test + public void testGetLinkTokenEmailWithoutSubPath() throws MalformedURLException, URISyntaxException { + RequestItemRepository instance = applicationContext.getBean( + RequestItemRest.CATEGORY + '.' + RequestItemRest.PLURAL_NAME, + RequestItemRepository.class); + String currentDspaceUrl = configurationService.getProperty("dspace.ui.url"); + String expectedUrl = currentDspaceUrl + "/request-a-copy/token"; + String generatedLink = instance.getLinkTokenEmail("token"); + // The URLs should match + assertEquals(expectedUrl, generatedLink); + configurationService.reloadConfig(); + } } From 1914aac18b244c3b4053a56905c78d359b5e1910 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Sun, 1 Sep 2024 12:53:04 +0200 Subject: [PATCH 094/632] Improved URI build method as per review --- .../rest/repository/RequestItemRepository.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 71c46b4dc843..8be7971c84dd 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -15,7 +15,11 @@ import java.net.URI; import java.net.URISyntaxException; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; import java.util.Date; +import java.util.LinkedList; +import java.util.List; import java.util.UUID; import javax.servlet.http.HttpServletRequest; @@ -295,11 +299,16 @@ public Class getDomainClass() { public String getLinkTokenEmail(String token) throws URISyntaxException, MalformedURLException { final String base = configurationService.getProperty("dspace.ui.url"); + URIBuilder uriBuilder = new URIBuilder(base); - // Add request-a-copy/token to the existing path (without breaking /sub/dir dspace URLs) - URI uri = uriBuilder.setPath( - (uriBuilder.getPath() == null ? "" : StringUtils.stripEnd(uriBuilder.getPath(), "")) - + "/request-a-copy/" + token).build(); + List segments = new LinkedList<>(); + if (StringUtils.isNotBlank(uriBuilder.getPath())) { + segments.add(StringUtils.strip(uriBuilder.getPath(), "/")); + } + segments.add("request-a-copy"); + segments.add(token); + URI uri = uriBuilder.setPathSegments(segments).build(); + return uri.toURL().toExternalForm(); } } From ab43b8606615ce6a77cb88333469611dc8411fb6 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 4 Sep 2024 14:04:20 +0200 Subject: [PATCH 095/632] Tidy implementation of link token generation --- .../dspace/app/rest/repository/RequestItemRepository.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index 8be7971c84dd..f7c986ff9a02 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -300,6 +300,7 @@ public String getLinkTokenEmail(String token) throws URISyntaxException, MalformedURLException { final String base = configurationService.getProperty("dspace.ui.url"); + // Construct the link, making sure to support sub-paths URIBuilder uriBuilder = new URIBuilder(base); List segments = new LinkedList<>(); if (StringUtils.isNotBlank(uriBuilder.getPath())) { @@ -307,8 +308,8 @@ public String getLinkTokenEmail(String token) } segments.add("request-a-copy"); segments.add(token); - URI uri = uriBuilder.setPathSegments(segments).build(); - return uri.toURL().toExternalForm(); + // Build and return the URL from segments (or throw exception) + return uriBuilder.setPathSegments(segments).build().toURL().toExternalForm(); } } From 7ec746d0052a01f5c5ed9f0351c988fe13f6aafa Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 4 Sep 2024 15:19:34 +0200 Subject: [PATCH 096/632] lint fixes (RequestItemRepository) --- .../org/dspace/app/rest/repository/RequestItemRepository.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java index f7c986ff9a02..10208b27fe7a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RequestItemRepository.java @@ -12,11 +12,8 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.LinkedList; import java.util.List; From d40a5e2a4b1e90b3ca7e2ba7e75bb5cbe7bb72fa Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 17 Jun 2024 13:02:33 +0200 Subject: [PATCH 097/632] feat: new parameter "fromdate" to evaluate items only from certain date (cherry picked from commit a9e120f3d434ece061dcaf7371822b9201eac655) --- .../app/mediafilter/MediaFilterScript.java | 15 +++++++++++++-- .../MediaFilterScriptConfiguration.java | 2 ++ .../mediafilter/MediaFilterServiceImpl.java | 18 ++++++++++++++++++ .../service/MediaFilterService.java | 3 +++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java index 5fbbebbb28cc..71c0d6e14ddb 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java @@ -7,6 +7,7 @@ */ package org.dspace.app.mediafilter; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -37,8 +38,9 @@ * MFM: -v verbose outputs all extracted text to STDOUT; -f force forces all * bitstreams to be processed, even if they have been before; -n noindex does not * recreate index after processing bitstreams; -i [identifier] limits processing - * scope to a community, collection or item; and -m [max] limits processing to a - * maximum number of items. + * scope to a community, collection or item; -m [max] limits processing to a + * maximum number of items; -fd [fromdate] takes only items starting from this date, + * filtering by last_modified in the item table. */ public class MediaFilterScript extends DSpaceRunnable { @@ -60,6 +62,7 @@ public class MediaFilterScript extends DSpaceRunnable> filterFormats = new HashMap<>(); + private LocalDate fromDate = null; public MediaFilterScriptConfiguration getScriptConfiguration() { return new DSpace().getServiceManager() @@ -112,6 +115,10 @@ public void setup() throws ParseException { skipIds = commandLine.getOptionValues('s'); } + if (commandLine.hasOption('f')) { + fromDate = LocalDate.parse(commandLine.getOptionValue('f')); + } + } @@ -215,6 +222,10 @@ public void internalRun() throws Exception { mediaFilterService.setSkipList(Arrays.asList(skipIds)); } + if (fromDate != null) { + mediaFilterService.setFromDate(fromDate); + } + Context c = null; try { diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScriptConfiguration.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScriptConfiguration.java index 7465fa6e1279..9f62f19e8367 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScriptConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScriptConfiguration.java @@ -52,6 +52,8 @@ public Options getOptions() { .build(); options.addOption(pluginOption); + options.addOption("fd", "fromdate", true, "Process only item from specified last modified date"); + Option skipOption = Option.builder("s") .longOpt("skip") .hasArg() diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterServiceImpl.java index a6ba9fde88d9..512b8f803b9b 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterServiceImpl.java @@ -9,8 +9,11 @@ import java.io.InputStream; import java.sql.SQLException; +import java.time.LocalDate; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -93,6 +96,7 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB protected boolean isVerbose = false; protected boolean isQuiet = false; protected boolean isForce = false; // default to not forced + protected LocalDate fromDate = null; protected MediaFilterServiceImpl() { @@ -120,6 +124,15 @@ public void applyFiltersAllItems(Context context) throws Exception { for (Community topLevelCommunity : topLevelCommunities) { applyFiltersCommunity(context, topLevelCommunity); } + } else if (fromDate != null) { + Iterator itemIterator = + itemService.findByLastModifiedSince( + context, + Date.from(fromDate.atStartOfDay(ZoneId.systemDefault()).toInstant()) + ); + while (itemIterator.hasNext() && processed < max2Process) { + applyFiltersItem(context, itemIterator.next()); + } } else { //otherwise, just find every item and process Iterator itemIterator = itemService.findAll(context); @@ -588,4 +601,9 @@ public void setFilterFormats(Map> filterFormats) { public void setLogHandler(DSpaceRunnableHandler handler) { this.handler = handler; } + + @Override + public void setFromDate(LocalDate fromDate) { + this.fromDate = fromDate; + } } diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/service/MediaFilterService.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/service/MediaFilterService.java index bc92ff521098..30e6dba42f08 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/service/MediaFilterService.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/service/MediaFilterService.java @@ -8,6 +8,7 @@ package org.dspace.app.mediafilter.service; import java.sql.SQLException; +import java.time.LocalDate; import java.util.List; import java.util.Map; @@ -149,4 +150,6 @@ public void updatePoliciesOfDerivativeBitstreams(Context context, Item item, Bit * @param handler */ public void setLogHandler(DSpaceRunnableHandler handler); + + public void setFromDate(LocalDate fromDate); } From cc76ebee108074c538090230cb397ce44f01e9d3 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 17 Jun 2024 13:57:39 +0200 Subject: [PATCH 098/632] refactor: changed short parameter fd to d (cherry picked from commit 2f6b7f3ee4b0c40d215730dd2e86f4492a455e77) --- .../main/java/org/dspace/app/mediafilter/MediaFilterScript.java | 2 +- .../dspace/app/mediafilter/MediaFilterScriptConfiguration.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java index 71c0d6e14ddb..e76feada0339 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java @@ -115,7 +115,7 @@ public void setup() throws ParseException { skipIds = commandLine.getOptionValues('s'); } - if (commandLine.hasOption('f')) { + if (commandLine.hasOption('d')) { fromDate = LocalDate.parse(commandLine.getOptionValue('f')); } diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScriptConfiguration.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScriptConfiguration.java index 9f62f19e8367..c9f61292d617 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScriptConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScriptConfiguration.java @@ -52,7 +52,7 @@ public Options getOptions() { .build(); options.addOption(pluginOption); - options.addOption("fd", "fromdate", true, "Process only item from specified last modified date"); + options.addOption("d", "fromdate", true, "Process only item from specified last modified date"); Option skipOption = Option.builder("s") .longOpt("skip") From f652b2c47ac2aab95c8dd84b4f045b715d2ea9f8 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 17 Jun 2024 16:39:02 +0200 Subject: [PATCH 099/632] refactor: changed short parameter fd to d (cherry picked from commit 3fd88b867eb9bbd8b3621904ecac5b845fc7346e) --- .../main/java/org/dspace/app/mediafilter/MediaFilterScript.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java index e76feada0339..7f022f38b318 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/MediaFilterScript.java @@ -116,7 +116,7 @@ public void setup() throws ParseException { } if (commandLine.hasOption('d')) { - fromDate = LocalDate.parse(commandLine.getOptionValue('f')); + fromDate = LocalDate.parse(commandLine.getOptionValue('d')); } From 83f61ce12caf582ff1a59df699bffe7b09d3b95e Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 4 Sep 2024 15:31:28 +0200 Subject: [PATCH 100/632] fix: changed parameter of HQL query (cherry picked from commit 9c7b20ff5721e2886acd7186ba4df310c9efcf07) --- .../src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java index 3be39f1788fb..bd042648384b 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/ItemDAOImpl.java @@ -441,7 +441,7 @@ public int countItems(Context context, List collections, boolean inc public Iterator findByLastModifiedSince(Context context, Date since) throws SQLException { Query query = createQuery(context, - "SELECT i.id FROM Item i WHERE last_modified > :last_modified ORDER BY id"); + "SELECT i.id FROM Item i WHERE lastModified > :last_modified ORDER BY id"); query.setParameter("last_modified", since, TemporalType.TIMESTAMP); @SuppressWarnings("unchecked") List uuids = query.getResultList(); From 4ac4c911cf47ecf3540e05a9067550bba3faab25 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 6 Sep 2024 14:38:15 -0500 Subject: [PATCH 101/632] Singular name needed in 7.x --- .../java/org/dspace/app/rest/RequestItemRepositoryIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java index f8732d0826e3..fbbd179fd287 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RequestItemRepositoryIT.java @@ -627,7 +627,7 @@ public void testGetDomainClass() { @Test public void testGetLinkTokenEmailWithSubPath() throws MalformedURLException, URISyntaxException { RequestItemRepository instance = applicationContext.getBean( - RequestItemRest.CATEGORY + '.' + RequestItemRest.PLURAL_NAME, + RequestItemRest.CATEGORY + '.' + RequestItemRest.NAME, RequestItemRepository.class); String currentDspaceUrl = configurationService.getProperty("dspace.ui.url"); String newDspaceUrl = currentDspaceUrl + "/subdir"; @@ -646,7 +646,7 @@ public void testGetLinkTokenEmailWithSubPath() throws MalformedURLException, URI @Test public void testGetLinkTokenEmailWithoutSubPath() throws MalformedURLException, URISyntaxException { RequestItemRepository instance = applicationContext.getBean( - RequestItemRest.CATEGORY + '.' + RequestItemRest.PLURAL_NAME, + RequestItemRest.CATEGORY + '.' + RequestItemRest.NAME, RequestItemRepository.class); String currentDspaceUrl = configurationService.getProperty("dspace.ui.url"); String expectedUrl = currentDspaceUrl + "/request-a-copy/token"; From 9031322e7d4eccc73f057a5b3cf11c3c8cfc5361 Mon Sep 17 00:00:00 2001 From: Mikhail Schastlivtsev Date: Wed, 15 May 2024 10:08:46 +0300 Subject: [PATCH 102/632] add missing wosPublisherContrib key-ref in wos-integration.xml (#9579) (cherry picked from commit 6a8c76bbe1e7149785c17c7a7249e319199c3e0a) --- dspace/config/spring/api/wos-integration.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dspace/config/spring/api/wos-integration.xml b/dspace/config/spring/api/wos-integration.xml index 17bd53c04a4d..ba90363a2e60 100644 --- a/dspace/config/spring/api/wos-integration.xml +++ b/dspace/config/spring/api/wos-integration.xml @@ -35,6 +35,7 @@ + From a49ee624508f71c3e928d032b8448d1ec1316d6d Mon Sep 17 00:00:00 2001 From: Mikhail Schastlivtsev Date: Mon, 17 Jun 2024 14:06:53 +0300 Subject: [PATCH 103/632] add missing publisher metadatum in test (#9579) (cherry picked from commit cde892c8c7e1df8fff70a4cbfc693f378c2065d2) --- .../org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java index f1d3f5303ec0..9f68d79c2036 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java @@ -136,6 +136,7 @@ private ArrayList getRecords() { MetadatumDTO subject15 = createMetadatumDTO("dc", "subject", null, "Coding concepts"); MetadatumDTO subject16 = createMetadatumDTO("dc", "subject", null, "Lesson design"); MetadatumDTO subject17 = createMetadatumDTO("dc", "subject", null, "Social Sciences"); + MetadatumDTO publisher = createMetadatumDTO("dc", "publisher", null, "SPRINGER"); MetadatumDTO other = createMetadatumDTO("dc", "identifier", "other", "WOS:000805105200003"); metadatums.add(edition); metadatums.add(date); @@ -166,6 +167,7 @@ private ArrayList getRecords() { metadatums.add(subject15); metadatums.add(subject16); metadatums.add(subject17); + metadatums.add(publisher); metadatums.add(other); ImportRecord firstrRecord = new ImportRecord(metadatums); @@ -205,6 +207,7 @@ private ArrayList getRecords() { MetadatumDTO subject26 = createMetadatumDTO("dc", "subject", null, "Social Sciences"); MetadatumDTO subject27 = createMetadatumDTO("dc", "subject", null, "Science & Technology"); MetadatumDTO subject28 = createMetadatumDTO("dc", "subject", null, "Life Sciences & Biomedicine"); + MetadatumDTO publisher2 = createMetadatumDTO("dc", "publisher", null, "NATURE PORTFOLIO"); MetadatumDTO other2 = createMetadatumDTO("dc", "identifier", "other", "WOS:000805100600001"); MetadatumDTO rid = createMetadatumDTO("person", "identifier", "rid", "C-6334-2011"); MetadatumDTO rid2 = createMetadatumDTO("person", "identifier", "rid", "B-1251-2008"); @@ -236,6 +239,7 @@ private ArrayList getRecords() { metadatums2.add(subject26); metadatums2.add(subject27); metadatums2.add(subject28); + metadatums2.add(publisher2); metadatums2.add(other2); metadatums2.add(rid); metadatums2.add(rid2); From 4f5b9bb916b084f258fedb56ffbbc3abeda72895 Mon Sep 17 00:00:00 2001 From: Mikhail Schastlivtsev Date: Mon, 17 Jun 2024 14:06:53 +0300 Subject: [PATCH 104/632] add missing publisher metadatum in test (#9579) --- .../org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java index f1d3f5303ec0..9f68d79c2036 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java @@ -136,6 +136,7 @@ private ArrayList getRecords() { MetadatumDTO subject15 = createMetadatumDTO("dc", "subject", null, "Coding concepts"); MetadatumDTO subject16 = createMetadatumDTO("dc", "subject", null, "Lesson design"); MetadatumDTO subject17 = createMetadatumDTO("dc", "subject", null, "Social Sciences"); + MetadatumDTO publisher = createMetadatumDTO("dc", "publisher", null, "SPRINGER"); MetadatumDTO other = createMetadatumDTO("dc", "identifier", "other", "WOS:000805105200003"); metadatums.add(edition); metadatums.add(date); @@ -166,6 +167,7 @@ private ArrayList getRecords() { metadatums.add(subject15); metadatums.add(subject16); metadatums.add(subject17); + metadatums.add(publisher); metadatums.add(other); ImportRecord firstrRecord = new ImportRecord(metadatums); @@ -205,6 +207,7 @@ private ArrayList getRecords() { MetadatumDTO subject26 = createMetadatumDTO("dc", "subject", null, "Social Sciences"); MetadatumDTO subject27 = createMetadatumDTO("dc", "subject", null, "Science & Technology"); MetadatumDTO subject28 = createMetadatumDTO("dc", "subject", null, "Life Sciences & Biomedicine"); + MetadatumDTO publisher2 = createMetadatumDTO("dc", "publisher", null, "NATURE PORTFOLIO"); MetadatumDTO other2 = createMetadatumDTO("dc", "identifier", "other", "WOS:000805100600001"); MetadatumDTO rid = createMetadatumDTO("person", "identifier", "rid", "C-6334-2011"); MetadatumDTO rid2 = createMetadatumDTO("person", "identifier", "rid", "B-1251-2008"); @@ -236,6 +239,7 @@ private ArrayList getRecords() { metadatums2.add(subject26); metadatums2.add(subject27); metadatums2.add(subject28); + metadatums2.add(publisher2); metadatums2.add(other2); metadatums2.add(rid); metadatums2.add(rid2); From 5263b08eafe4393b6abc2af50132590795cdda81 Mon Sep 17 00:00:00 2001 From: Mikhail Schastlivtsev Date: Wed, 15 May 2024 10:08:46 +0300 Subject: [PATCH 105/632] add missing wosPublisherContrib key-ref in wos-integration.xml (#9579) --- dspace/config/spring/api/wos-integration.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dspace/config/spring/api/wos-integration.xml b/dspace/config/spring/api/wos-integration.xml index 17bd53c04a4d..ba90363a2e60 100644 --- a/dspace/config/spring/api/wos-integration.xml +++ b/dspace/config/spring/api/wos-integration.xml @@ -35,6 +35,7 @@ + From 405397b8b061205253768db73924aeffa77c846d Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:23:32 +0200 Subject: [PATCH 106/632] update eperson's attributes right after successful login (cherry picked from commit 428489ca5258ea7ac6942a722621e22c3371bfcf) --- .../authenticate/LDAPAuthentication.java | 69 +++++++++++-------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index 585eaf9cd8b1..2203937e75d6 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -68,12 +68,8 @@ * @author Ivan Masár * @author Michael Plate */ -public class LDAPAuthentication - implements AuthenticationMethod { +public class LDAPAuthentication implements AuthenticationMethod { - /** - * log4j category - */ private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(LDAPAuthentication.class); @@ -130,7 +126,7 @@ public boolean allowSetPassword(Context context, return false; } - /* + /** * This is an explicit method. */ @Override @@ -138,7 +134,7 @@ public boolean isImplicit() { return false; } - /* + /** * Add authenticated users to the group defined in dspace.cfg by * the login.specialgroup key. */ @@ -177,7 +173,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request) return Collections.EMPTY_LIST; } - /* + /** * Authenticate the given credentials. * This is the heart of the authentication method: test the * credentials for authenticity, and if accepted, attempt to match @@ -250,7 +246,7 @@ public int authenticate(Context context, } // Check a DN was found - if ((dn == null) || (dn.trim().equals(""))) { + if (StringUtils.isBlank(dn)) { log.info(LogHelper .getHeader(context, "failed_login", "no DN found for user " + netid)); return BAD_CREDENTIALS; @@ -269,6 +265,18 @@ public int authenticate(Context context, context.setCurrentUser(eperson); request.setAttribute(LDAP_AUTHENTICATED, true); + // update eperson's attributes + context.turnOffAuthorisationSystem(); + setEpersonAttributes(context, eperson, ldap, Optional.empty()); + try { + ePersonService.update(context, eperson); + context.dispatchEvents(); + } catch (AuthorizeException e) { + log.warn("update of eperson " + eperson.getID() + " failed", e); + } finally { + context.restoreAuthSystemState(); + } + // assign user to groups based on ldap dn assignGroups(dn, ldap.ldapGroup, context); @@ -313,14 +321,13 @@ public int authenticate(Context context, log.info(LogHelper.getHeader(context, "type=ldap-login", "type=ldap_but_already_email")); context.turnOffAuthorisationSystem(); - eperson.setNetid(netid.toLowerCase()); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); ePersonService.update(context, eperson); context.dispatchEvents(); context.restoreAuthSystemState(); context.setCurrentUser(eperson); request.setAttribute(LDAP_AUTHENTICATED, true); - // assign user to groups based on ldap dn assignGroups(dn, ldap.ldapGroup, context); @@ -331,20 +338,7 @@ public int authenticate(Context context, try { context.turnOffAuthorisationSystem(); eperson = ePersonService.create(context); - if (StringUtils.isNotEmpty(email)) { - eperson.setEmail(email); - } - if (StringUtils.isNotEmpty(ldap.ldapGivenName)) { - eperson.setFirstName(context, ldap.ldapGivenName); - } - if (StringUtils.isNotEmpty(ldap.ldapSurname)) { - eperson.setLastName(context, ldap.ldapSurname); - } - if (StringUtils.isNotEmpty(ldap.ldapPhone)) { - ePersonService.setMetadataSingleValue(context, eperson, - MD_PHONE, ldap.ldapPhone, null); - } - eperson.setNetid(netid.toLowerCase()); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); eperson.setCanLogIn(true); authenticationService.initEPerson(context, request, eperson); ePersonService.update(context, eperson); @@ -382,6 +376,27 @@ public int authenticate(Context context, return BAD_ARGS; } + /** + * Update eperson's attributes + */ + private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) throws SQLException { + if (StringUtils.isNotEmpty(ldap.ldapEmail)) { + eperson.setEmail(ldap.ldapEmail); + } + if (StringUtils.isNotEmpty(ldap.ldapGivenName)) { + eperson.setFirstName(context, ldap.ldapGivenName); + } + if (StringUtils.isNotEmpty(ldap.ldapSurname)) { + eperson.setLastName(context, ldap.ldapSurname); + } + if (StringUtils.isNotEmpty(ldap.ldapPhone)) { + ePersonService.setMetadataSingleValue(context, eperson, MD_PHONE, ldap.ldapPhone, null); + } + if (netid.isPresent()) { + eperson.setNetid(netid.get().toLowerCase()); + } + } + /** * Internal class to manage LDAP query and results, mainly * because there are multiple values to return. @@ -671,7 +686,7 @@ protected boolean ldapAuthenticate(String netid, String password, } } - /* + /** * Returns the URL of an external login page which is not applicable for this authn method. * * Note: Prior to DSpace 7, this method return the page of login servlet. @@ -699,7 +714,7 @@ public String getName() { return "ldap"; } - /* + /** * Add authenticated users to the group defined in dspace.cfg by * the authentication-ldap.login.groupmap.* key. * From b0370a064b843db6d77efb58c5d54788e3872253 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:36:45 +0200 Subject: [PATCH 107/632] add missing import (cherry picked from commit c5ad32a9b3ece7e64043f9f39d22b594e913737f) --- .../main/java/org/dspace/authenticate/LDAPAuthentication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index 2203937e75d6..06bd6ae603d9 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -17,6 +17,7 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Optional; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; From 31af49ea725b5658f408e519cc577805b8f8c72d Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:54:53 +0200 Subject: [PATCH 108/632] fix Checkstyle violations (cherry picked from commit aaa74b88c99af8ece67d43fa412a39a7406fe10c) --- .../org/dspace/authenticate/LDAPAuthentication.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index 06bd6ae603d9..93f0feb384c0 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -184,7 +184,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request) * @param context * DSpace context, will be modified (ePerson set) upon success. * - * @param username + * @param netid * Username (or email address) when method is explicit. Use null for * implicit method. * @@ -322,7 +322,7 @@ public int authenticate(Context context, log.info(LogHelper.getHeader(context, "type=ldap-login", "type=ldap_but_already_email")); context.turnOffAuthorisationSystem(); - setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); ePersonService.update(context, eperson); context.dispatchEvents(); context.restoreAuthSystemState(); @@ -380,7 +380,9 @@ public int authenticate(Context context, /** * Update eperson's attributes */ - private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) throws SQLException { + private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) + throws SQLException { + if (StringUtils.isNotEmpty(ldap.ldapEmail)) { eperson.setEmail(ldap.ldapEmail); } @@ -389,7 +391,7 @@ private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDA } if (StringUtils.isNotEmpty(ldap.ldapSurname)) { eperson.setLastName(context, ldap.ldapSurname); - } + } if (StringUtils.isNotEmpty(ldap.ldapPhone)) { ePersonService.setMetadataSingleValue(context, eperson, MD_PHONE, ldap.ldapPhone, null); } From da6de795338f95e8b6658c4765d5837e6325554c Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:23:32 +0200 Subject: [PATCH 109/632] update eperson's attributes right after successful login (cherry picked from commit 428489ca5258ea7ac6942a722621e22c3371bfcf) --- .../authenticate/LDAPAuthentication.java | 69 +++++++++++-------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index b791df15b5c0..c6df4b30faad 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -68,12 +68,8 @@ * @author Ivan Masár * @author Michael Plate */ -public class LDAPAuthentication - implements AuthenticationMethod { +public class LDAPAuthentication implements AuthenticationMethod { - /** - * log4j category - */ private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(LDAPAuthentication.class); @@ -130,7 +126,7 @@ public boolean allowSetPassword(Context context, return false; } - /* + /** * This is an explicit method. */ @Override @@ -138,7 +134,7 @@ public boolean isImplicit() { return false; } - /* + /** * Add authenticated users to the group defined in dspace.cfg by * the login.specialgroup key. */ @@ -177,7 +173,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request) return Collections.EMPTY_LIST; } - /* + /** * Authenticate the given credentials. * This is the heart of the authentication method: test the * credentials for authenticity, and if accepted, attempt to match @@ -250,7 +246,7 @@ public int authenticate(Context context, } // Check a DN was found - if ((dn == null) || (dn.trim().equals(""))) { + if (StringUtils.isBlank(dn)) { log.info(LogHelper .getHeader(context, "failed_login", "no DN found for user " + netid)); return BAD_CREDENTIALS; @@ -269,6 +265,18 @@ public int authenticate(Context context, context.setCurrentUser(eperson); request.setAttribute(LDAP_AUTHENTICATED, true); + // update eperson's attributes + context.turnOffAuthorisationSystem(); + setEpersonAttributes(context, eperson, ldap, Optional.empty()); + try { + ePersonService.update(context, eperson); + context.dispatchEvents(); + } catch (AuthorizeException e) { + log.warn("update of eperson " + eperson.getID() + " failed", e); + } finally { + context.restoreAuthSystemState(); + } + // assign user to groups based on ldap dn assignGroups(dn, ldap.ldapGroup, context); @@ -313,14 +321,13 @@ public int authenticate(Context context, log.info(LogHelper.getHeader(context, "type=ldap-login", "type=ldap_but_already_email")); context.turnOffAuthorisationSystem(); - eperson.setNetid(netid.toLowerCase()); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); ePersonService.update(context, eperson); context.dispatchEvents(); context.restoreAuthSystemState(); context.setCurrentUser(eperson); request.setAttribute(LDAP_AUTHENTICATED, true); - // assign user to groups based on ldap dn assignGroups(dn, ldap.ldapGroup, context); @@ -331,20 +338,7 @@ public int authenticate(Context context, try { context.turnOffAuthorisationSystem(); eperson = ePersonService.create(context); - if (StringUtils.isNotEmpty(email)) { - eperson.setEmail(email); - } - if (StringUtils.isNotEmpty(ldap.ldapGivenName)) { - eperson.setFirstName(context, ldap.ldapGivenName); - } - if (StringUtils.isNotEmpty(ldap.ldapSurname)) { - eperson.setLastName(context, ldap.ldapSurname); - } - if (StringUtils.isNotEmpty(ldap.ldapPhone)) { - ePersonService.setMetadataSingleValue(context, eperson, - MD_PHONE, ldap.ldapPhone, null); - } - eperson.setNetid(netid.toLowerCase()); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); eperson.setCanLogIn(true); authenticationService.initEPerson(context, request, eperson); ePersonService.update(context, eperson); @@ -382,6 +376,27 @@ public int authenticate(Context context, return BAD_ARGS; } + /** + * Update eperson's attributes + */ + private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) throws SQLException { + if (StringUtils.isNotEmpty(ldap.ldapEmail)) { + eperson.setEmail(ldap.ldapEmail); + } + if (StringUtils.isNotEmpty(ldap.ldapGivenName)) { + eperson.setFirstName(context, ldap.ldapGivenName); + } + if (StringUtils.isNotEmpty(ldap.ldapSurname)) { + eperson.setLastName(context, ldap.ldapSurname); + } + if (StringUtils.isNotEmpty(ldap.ldapPhone)) { + ePersonService.setMetadataSingleValue(context, eperson, MD_PHONE, ldap.ldapPhone, null); + } + if (netid.isPresent()) { + eperson.setNetid(netid.get().toLowerCase()); + } + } + /** * Internal class to manage LDAP query and results, mainly * because there are multiple values to return. @@ -671,7 +686,7 @@ protected boolean ldapAuthenticate(String netid, String password, } } - /* + /** * Returns the URL of an external login page which is not applicable for this authn method. * * Note: Prior to DSpace 7, this method return the page of login servlet. @@ -699,7 +714,7 @@ public String getName() { return "ldap"; } - /* + /** * Add authenticated users to the group defined in dspace.cfg by * the authentication-ldap.login.groupmap.* key. * From c6d95c69583342e3d18bb90b81da1b7e40c838e0 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:36:45 +0200 Subject: [PATCH 110/632] add missing import (cherry picked from commit c5ad32a9b3ece7e64043f9f39d22b594e913737f) --- .../main/java/org/dspace/authenticate/LDAPAuthentication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index c6df4b30faad..9ca5245c54ba 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -17,6 +17,7 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Optional; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; From 8a3596d0db8b2f0abdca932312a960e487028ddf Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:54:53 +0200 Subject: [PATCH 111/632] fix Checkstyle violations (cherry picked from commit aaa74b88c99af8ece67d43fa412a39a7406fe10c) --- .../org/dspace/authenticate/LDAPAuthentication.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index 9ca5245c54ba..4f2c5cc3d02c 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -184,7 +184,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request) * @param context * DSpace context, will be modified (ePerson set) upon success. * - * @param username + * @param netid * Username (or email address) when method is explicit. Use null for * implicit method. * @@ -322,7 +322,7 @@ public int authenticate(Context context, log.info(LogHelper.getHeader(context, "type=ldap-login", "type=ldap_but_already_email")); context.turnOffAuthorisationSystem(); - setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); ePersonService.update(context, eperson); context.dispatchEvents(); context.restoreAuthSystemState(); @@ -380,7 +380,9 @@ public int authenticate(Context context, /** * Update eperson's attributes */ - private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) throws SQLException { + private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) + throws SQLException { + if (StringUtils.isNotEmpty(ldap.ldapEmail)) { eperson.setEmail(ldap.ldapEmail); } @@ -389,7 +391,7 @@ private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDA } if (StringUtils.isNotEmpty(ldap.ldapSurname)) { eperson.setLastName(context, ldap.ldapSurname); - } + } if (StringUtils.isNotEmpty(ldap.ldapPhone)) { ePersonService.setMetadataSingleValue(context, eperson, MD_PHONE, ldap.ldapPhone, null); } From 702ff9cf4c0e9e2afeb1bab820087e6fb7584154 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 27 Sep 2024 12:07:52 +0200 Subject: [PATCH 112/632] minor fix in parameter description (cherry picked from commit 5758d9e90302d4da33ec869b6ec656e5c25b865a) --- dspace/config/emails/subscriptions_content | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/emails/subscriptions_content b/dspace/config/emails/subscriptions_content index 9b8c91e559df..a1b107e8fc50 100644 --- a/dspace/config/emails/subscriptions_content +++ b/dspace/config/emails/subscriptions_content @@ -1,7 +1,7 @@ ## E-mail sent to designated address about updates on subscribed items ## -## Parameters: {0} Collections updates -## {1} Communities updates +## Parameters: {0} Communities updates +## {1} Collections updates #set($subject = "${config.get('dspace.name')} Subscriptions") This email is sent from ${config.get('dspace.name')} based on the chosen subscription preferences. From c08c62fccf450c98225827e3ecc126e494b16c5e Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 27 Sep 2024 12:07:52 +0200 Subject: [PATCH 113/632] minor fix in parameter description (cherry picked from commit 5758d9e90302d4da33ec869b6ec656e5c25b865a) --- dspace/config/emails/subscriptions_content | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/emails/subscriptions_content b/dspace/config/emails/subscriptions_content index 9b8c91e559df..a1b107e8fc50 100644 --- a/dspace/config/emails/subscriptions_content +++ b/dspace/config/emails/subscriptions_content @@ -1,7 +1,7 @@ ## E-mail sent to designated address about updates on subscribed items ## -## Parameters: {0} Collections updates -## {1} Communities updates +## Parameters: {0} Communities updates +## {1} Collections updates #set($subject = "${config.get('dspace.name')} Subscriptions") This email is sent from ${config.get('dspace.name')} based on the chosen subscription preferences. From a721f8c41e92762d6d1af831b337b111a5ea9991 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 27 Aug 2024 10:33:01 +0200 Subject: [PATCH 114/632] fix failed first login attempt in HAL browser (cherry picked from commit 002e637d4fc69b31c2a2321230d96534e49ee33e) --- .../src/main/webapp/login.html | 128 ++++++++++-------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/dspace-server-webapp/src/main/webapp/login.html b/dspace-server-webapp/src/main/webapp/login.html index 50d95b80472f..0597a66bfe96 100644 --- a/dspace-server-webapp/src/main/webapp/login.html +++ b/dspace-server-webapp/src/main/webapp/login.html @@ -32,7 +32,7 @@ border-radius: 5px; box-shadow: 0 1px 2px rgba(0, 0, 0, .05); } - .form-signin .form-signin-heading, .form-signin .checkbox { + .form-signin .form-signin-heading, .form-signin { margin-bottom: 10px; } .form-signin input[type="text"], .form-signin input[type="password"] { @@ -94,63 +94,71 @@

    Other login methods:

    "onclick" : function() { toastr.remove(); } } + // retrieves a valid CSRF token (please note that this method works both in DS 7 and DS 8) + // HTTP response code 403 is expected at this point (the response contains the DSPACE-XSRF-TOKEN header) + $.ajax({ + url : window.location.href.replace("login.html", "") + 'api/authn/login', + type : 'POST', + error : function(xhr) { + // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) + checkForUpdatedCSRFTokenInResponse(xhr); + } + }); + // When the login page loads, we do *two* AJAX requests. - // (1) Call GET /api/authn/status. This call has two purposes. First, it checks to see if you are logged in, - // (if not, WWW-Authenticate will return login options). Second, it retrieves the CSRF token, if a - // new one has been assigned (as a valid CSRF token is required for the POST call). + // (1) Call GET /api/authn/status. This call checks to see if you are logged in + // (if not, WWW-Authenticate will return login options). // (2) If that /api/authn/status call finds authentication data, call POST /api/authn/login. - // This scenario occurs when you login via an external authentication system (e.g. Shibboleth)... + // This scenario occurs when you log in via an external authentication system (e.g. Shibboleth) // in which case the main role of /api/authn/login is to simply ensure the "Authorization" header // is sent back to the client (based on your authentication data). $.ajax({ - url : window.location.href.replace("login.html", "") + 'api/authn/status', - type : 'GET', - success : function(result, status, xhr) { - // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) - checkForUpdatedCSRFTokenInResponse(xhr); + url : window.location.href.replace("login.html", "") + 'api/authn/status', + type : 'GET', + success : function(result, status, xhr) { - // Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and - // therefore we need to display available authentication options. - var authenticate = xhr.getResponseHeader("WWW-Authenticate"); - if (authenticate !== null) { - var element = $('div.other-login-methods'); - var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); - if (realms.length == 1){ - var loc = /location="([^,]*)"/.exec(authenticate); - if (loc !== null && loc.length === 2) { - document.location = loc[1]; - } - } else if (realms.length > 1){ - for (var i = 0; i < realms.length; i++){ - addLocationButton(realms[i], element); + // Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and + // therefore we need to display available authentication options. + var authenticate = xhr.getResponseHeader("WWW-Authenticate"); + if (authenticate !== null && authenticate.contains('location=')) { + var element = $('div.other-login-methods'); + var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); + if (realms.length === 1){ + var loc = /location="([^,]*)"/.exec(authenticate); + if (loc !== null && loc.length === 2) { + document.location = loc[1]; + } + } else if (realms.length > 1){ + for (var i = 0; i < realms.length; i++){ + addLocationButton(realms[i], element); + } } + } else { + // If Authentication data was found, do a POST /api/authn/login to ensure that data's JWT + // is sent back in the "Authorization" header. This simply completes an external authentication + // process (e.g. Shibboleth) + $.ajax({ + url : window.location.href.replace("login.html", "") + 'api/authn/login', + type : 'POST', + beforeSend: function (xhr) { + // If CSRF token found in cookie, send it back as X-XSRF-Token header + var csrfToken = getCSRFToken(); + if (csrfToken != null) { + xhr.setRequestHeader('X-XSRF-Token', csrfToken); + } + }, + success : successHandler, + error : function(xhr) { + // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) + checkForUpdatedCSRFTokenInResponse(xhr); + toastr.error('Failed to logged in. Please check for errors in Javascript console.', 'Login Failed'); + } + }); } - } else { - // If Authentication data was found, do a POST /api/authn/login to ensure that data's JWT - // is sent back in the "Authorization" header. This simply completes an external authentication - // process (e.g. Shibboleth) - $.ajax({ - url : window.location.href.replace("login.html", "") + 'api/authn/login', - type : 'POST', - beforeSend: function (xhr, settings) { - // If CSRF token found in cookie, send it back as X-XSRF-Token header - var csrfToken = getCSRFToken(); - if (csrfToken != null) { - xhr.setRequestHeader('X-XSRF-Token', csrfToken); - } - }, - success : successHandler, - error : function(xhr, textStatus, errorThrown) { - // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) - checkForUpdatedCSRFTokenInResponse(xhr); - toastr.error('Failed to logged in. Please check for errors in Javascript console.', 'Login Failed'); - } - }); + }, + error : function() { + toastr.error('Failed to connect with backend. Please check for errors in Javascript console.', 'Could Not Load'); } - }, - error : function(xhr, textStatus, errorThrown) { - toastr.error('Failed to connect with backend. Please check for errors in Javascript console.', 'Could Not Load'); - } }); function addLocationButton(realm, element){ @@ -166,22 +174,22 @@

    Other login methods:

    return string.charAt(0).toUpperCase() + string.slice(1); } - /** - * Check current response headers to see if the CSRF Token has changed. If a new value is found in headers, - * save the new value into our "MyHalBrowserCsrfToken" cookie. - **/ + /** + * Check current response headers to see if the CSRF Token has changed. If a new value is found in headers, + * save the new value into our "MyHalBrowserCsrfToken" cookie. + **/ function checkForUpdatedCSRFTokenInResponse(jqxhr) { // look for DSpace-XSRF-TOKEN header & save to our MyHalBrowserCsrfToken cookie (if found) var updatedCsrfToken = jqxhr.getResponseHeader('DSPACE-XSRF-TOKEN'); if (updatedCsrfToken != null) { - document.cookie = "MyHalBrowserCsrfToken=" + updatedCsrfToken; + document.cookie = "MyHalBrowserCsrfToken=" + updatedCsrfToken; } } - /** - * Get CSRF Token by parsing it out of the "MyHalBrowserCsrfToken" cookie. - * This cookie is set in login.html after a successful login occurs. - **/ + /** + * Get CSRF Token by parsing it out of the "MyHalBrowserCsrfToken" cookie. + * This cookie is set in login.html after a successful login occurs. + **/ function getCSRFToken() { var cookie = document.cookie.match('(^|;)\\s*' + 'MyHalBrowserCsrfToken' + '\\s*=\\s*([^;]+)'); if (cookie != null) { @@ -204,11 +212,11 @@

    Other login methods:

    user: $("#username").val(), password: $("#password").val() }, - beforeSend: function (xhr, settings) { + beforeSend: function (xhr) { // If CSRF token found in cookie, send it back as X-XSRF-Token header var csrfToken = getCSRFToken(); if (csrfToken != null) { - xhr.setRequestHeader('X-XSRF-Token', csrfToken); + xhr.setRequestHeader('X-XSRF-Token', csrfToken); } }, success : successHandler, From 4669d8f7605a980a3f038c6f10835f89b7d81bee Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 29 Aug 2024 16:24:38 +0200 Subject: [PATCH 115/632] applied change suggested by reviewer: use String.prototype.includes (cherry picked from commit 546afb189e1df8bdfbc9948e790004baa81ec894) --- dspace-server-webapp/src/main/webapp/login.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/webapp/login.html b/dspace-server-webapp/src/main/webapp/login.html index 0597a66bfe96..959190020a13 100644 --- a/dspace-server-webapp/src/main/webapp/login.html +++ b/dspace-server-webapp/src/main/webapp/login.html @@ -120,7 +120,7 @@

    Other login methods:

    // Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and // therefore we need to display available authentication options. var authenticate = xhr.getResponseHeader("WWW-Authenticate"); - if (authenticate !== null && authenticate.contains('location=')) { + if (authenticate !== null && authenticate.includes('location=')) { var element = $('div.other-login-methods'); var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); if (realms.length === 1){ From 058f878d9275873bc9849c75777543bce686d989 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 27 Aug 2024 10:33:01 +0200 Subject: [PATCH 116/632] fix failed first login attempt in HAL browser (cherry picked from commit 002e637d4fc69b31c2a2321230d96534e49ee33e) --- .../src/main/resources/static/login.html | 128 ++++++++++-------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/dspace-server-webapp/src/main/resources/static/login.html b/dspace-server-webapp/src/main/resources/static/login.html index 50d95b80472f..0597a66bfe96 100644 --- a/dspace-server-webapp/src/main/resources/static/login.html +++ b/dspace-server-webapp/src/main/resources/static/login.html @@ -32,7 +32,7 @@ border-radius: 5px; box-shadow: 0 1px 2px rgba(0, 0, 0, .05); } - .form-signin .form-signin-heading, .form-signin .checkbox { + .form-signin .form-signin-heading, .form-signin { margin-bottom: 10px; } .form-signin input[type="text"], .form-signin input[type="password"] { @@ -94,63 +94,71 @@

    Other login methods:

    "onclick" : function() { toastr.remove(); } } + // retrieves a valid CSRF token (please note that this method works both in DS 7 and DS 8) + // HTTP response code 403 is expected at this point (the response contains the DSPACE-XSRF-TOKEN header) + $.ajax({ + url : window.location.href.replace("login.html", "") + 'api/authn/login', + type : 'POST', + error : function(xhr) { + // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) + checkForUpdatedCSRFTokenInResponse(xhr); + } + }); + // When the login page loads, we do *two* AJAX requests. - // (1) Call GET /api/authn/status. This call has two purposes. First, it checks to see if you are logged in, - // (if not, WWW-Authenticate will return login options). Second, it retrieves the CSRF token, if a - // new one has been assigned (as a valid CSRF token is required for the POST call). + // (1) Call GET /api/authn/status. This call checks to see if you are logged in + // (if not, WWW-Authenticate will return login options). // (2) If that /api/authn/status call finds authentication data, call POST /api/authn/login. - // This scenario occurs when you login via an external authentication system (e.g. Shibboleth)... + // This scenario occurs when you log in via an external authentication system (e.g. Shibboleth) // in which case the main role of /api/authn/login is to simply ensure the "Authorization" header // is sent back to the client (based on your authentication data). $.ajax({ - url : window.location.href.replace("login.html", "") + 'api/authn/status', - type : 'GET', - success : function(result, status, xhr) { - // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) - checkForUpdatedCSRFTokenInResponse(xhr); + url : window.location.href.replace("login.html", "") + 'api/authn/status', + type : 'GET', + success : function(result, status, xhr) { - // Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and - // therefore we need to display available authentication options. - var authenticate = xhr.getResponseHeader("WWW-Authenticate"); - if (authenticate !== null) { - var element = $('div.other-login-methods'); - var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); - if (realms.length == 1){ - var loc = /location="([^,]*)"/.exec(authenticate); - if (loc !== null && loc.length === 2) { - document.location = loc[1]; - } - } else if (realms.length > 1){ - for (var i = 0; i < realms.length; i++){ - addLocationButton(realms[i], element); + // Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and + // therefore we need to display available authentication options. + var authenticate = xhr.getResponseHeader("WWW-Authenticate"); + if (authenticate !== null && authenticate.contains('location=')) { + var element = $('div.other-login-methods'); + var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); + if (realms.length === 1){ + var loc = /location="([^,]*)"/.exec(authenticate); + if (loc !== null && loc.length === 2) { + document.location = loc[1]; + } + } else if (realms.length > 1){ + for (var i = 0; i < realms.length; i++){ + addLocationButton(realms[i], element); + } } + } else { + // If Authentication data was found, do a POST /api/authn/login to ensure that data's JWT + // is sent back in the "Authorization" header. This simply completes an external authentication + // process (e.g. Shibboleth) + $.ajax({ + url : window.location.href.replace("login.html", "") + 'api/authn/login', + type : 'POST', + beforeSend: function (xhr) { + // If CSRF token found in cookie, send it back as X-XSRF-Token header + var csrfToken = getCSRFToken(); + if (csrfToken != null) { + xhr.setRequestHeader('X-XSRF-Token', csrfToken); + } + }, + success : successHandler, + error : function(xhr) { + // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) + checkForUpdatedCSRFTokenInResponse(xhr); + toastr.error('Failed to logged in. Please check for errors in Javascript console.', 'Login Failed'); + } + }); } - } else { - // If Authentication data was found, do a POST /api/authn/login to ensure that data's JWT - // is sent back in the "Authorization" header. This simply completes an external authentication - // process (e.g. Shibboleth) - $.ajax({ - url : window.location.href.replace("login.html", "") + 'api/authn/login', - type : 'POST', - beforeSend: function (xhr, settings) { - // If CSRF token found in cookie, send it back as X-XSRF-Token header - var csrfToken = getCSRFToken(); - if (csrfToken != null) { - xhr.setRequestHeader('X-XSRF-Token', csrfToken); - } - }, - success : successHandler, - error : function(xhr, textStatus, errorThrown) { - // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) - checkForUpdatedCSRFTokenInResponse(xhr); - toastr.error('Failed to logged in. Please check for errors in Javascript console.', 'Login Failed'); - } - }); + }, + error : function() { + toastr.error('Failed to connect with backend. Please check for errors in Javascript console.', 'Could Not Load'); } - }, - error : function(xhr, textStatus, errorThrown) { - toastr.error('Failed to connect with backend. Please check for errors in Javascript console.', 'Could Not Load'); - } }); function addLocationButton(realm, element){ @@ -166,22 +174,22 @@

    Other login methods:

    return string.charAt(0).toUpperCase() + string.slice(1); } - /** - * Check current response headers to see if the CSRF Token has changed. If a new value is found in headers, - * save the new value into our "MyHalBrowserCsrfToken" cookie. - **/ + /** + * Check current response headers to see if the CSRF Token has changed. If a new value is found in headers, + * save the new value into our "MyHalBrowserCsrfToken" cookie. + **/ function checkForUpdatedCSRFTokenInResponse(jqxhr) { // look for DSpace-XSRF-TOKEN header & save to our MyHalBrowserCsrfToken cookie (if found) var updatedCsrfToken = jqxhr.getResponseHeader('DSPACE-XSRF-TOKEN'); if (updatedCsrfToken != null) { - document.cookie = "MyHalBrowserCsrfToken=" + updatedCsrfToken; + document.cookie = "MyHalBrowserCsrfToken=" + updatedCsrfToken; } } - /** - * Get CSRF Token by parsing it out of the "MyHalBrowserCsrfToken" cookie. - * This cookie is set in login.html after a successful login occurs. - **/ + /** + * Get CSRF Token by parsing it out of the "MyHalBrowserCsrfToken" cookie. + * This cookie is set in login.html after a successful login occurs. + **/ function getCSRFToken() { var cookie = document.cookie.match('(^|;)\\s*' + 'MyHalBrowserCsrfToken' + '\\s*=\\s*([^;]+)'); if (cookie != null) { @@ -204,11 +212,11 @@

    Other login methods:

    user: $("#username").val(), password: $("#password").val() }, - beforeSend: function (xhr, settings) { + beforeSend: function (xhr) { // If CSRF token found in cookie, send it back as X-XSRF-Token header var csrfToken = getCSRFToken(); if (csrfToken != null) { - xhr.setRequestHeader('X-XSRF-Token', csrfToken); + xhr.setRequestHeader('X-XSRF-Token', csrfToken); } }, success : successHandler, From c468e48f2f1177fc5477f003e68319503bf2b265 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 29 Aug 2024 16:24:38 +0200 Subject: [PATCH 117/632] applied change suggested by reviewer: use String.prototype.includes (cherry picked from commit 546afb189e1df8bdfbc9948e790004baa81ec894) --- dspace-server-webapp/src/main/resources/static/login.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/resources/static/login.html b/dspace-server-webapp/src/main/resources/static/login.html index 0597a66bfe96..959190020a13 100644 --- a/dspace-server-webapp/src/main/resources/static/login.html +++ b/dspace-server-webapp/src/main/resources/static/login.html @@ -120,7 +120,7 @@

    Other login methods:

    // Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and // therefore we need to display available authentication options. var authenticate = xhr.getResponseHeader("WWW-Authenticate"); - if (authenticate !== null && authenticate.contains('location=')) { + if (authenticate !== null && authenticate.includes('location=')) { var element = $('div.other-login-methods'); var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); if (realms.length === 1){ From 6e22495bffae2bb6a414e094cc6ed5b77886422a Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 10 Oct 2024 16:02:53 -0500 Subject: [PATCH 118/632] Bump to Spring 6.1.13, Spring Boot 3.3.4 and Spring Security 6.3.3 (cherry picked from commit 46dfd902f113b9ea13ce53b496aff6979024d67e) --- dspace-server-webapp/pom.xml | 14 +++++++++++++- pom.xml | 6 +++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 563019983402..759ad724b9b6 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -343,6 +343,18 @@ org.springframework.boot spring-boot-starter-actuator ${spring-boot.version} + + + + io.micrometer + micrometer-observation + + + + io.micrometer + micrometer-commons + +
    @@ -437,7 +449,7 @@ spring-boot-starter-security ${spring-boot.version} - + io.micrometer micrometer-observation diff --git a/pom.xml b/pom.xml index 54e56556f275..e92469dff3c4 100644 --- a/pom.xml +++ b/pom.xml @@ -19,9 +19,9 @@ 17 - 6.1.8 - 3.2.6 - 6.2.4 + 6.1.13 + 3.3.4 + 6.3.3 6.4.8.Final 8.0.1.Final 42.7.3 From 1e47fa61d92c9c87aeabbb4d1c074cc360c721af Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 11 Oct 2024 14:38:47 -0500 Subject: [PATCH 119/632] Bump to Spring 5.3.39 and Spring Security 5.8.14 --- dspace-server-webapp/pom.xml | 21 +++++++++++++++++++++ pom.xml | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index e0ec7ef5ed76..97bdaa241a4f 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -362,6 +362,27 @@ org.springframework.boot spring-boot-starter-security ${spring-boot.version} + + + + org.springframework.security + spring-security-core + + + org.springframework.security + spring-security-web + + + + + org.springframework.security + spring-security-core + ${spring-security.version} + + + org.springframework.security + spring-security-web + ${spring-security.version} diff --git a/pom.xml b/pom.xml index b662e333225d..6433b6f227de 100644 --- a/pom.xml +++ b/pom.xml @@ -19,9 +19,9 @@ 11 - 5.3.34 + 5.3.39 2.7.18 - 5.7.11 + 5.8.14 5.6.15.Final 6.2.5.Final 42.7.3 From 70dd8477599abf1e0b4c8933b45c80ddd49e7561 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 11 Oct 2024 16:41:40 -0500 Subject: [PATCH 120/632] Revert to Spring Security 5.7.12. Spring Security 5.8.x changes behavior of CSRF tokens --- dspace-server-webapp/pom.xml | 9 +++++++++ pom.xml | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 97bdaa241a4f..5a4e1b32123d 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -364,6 +364,10 @@ ${spring-boot.version} + + org.springframework.security + spring-security-config + org.springframework.security spring-security-core @@ -374,6 +378,11 @@
    + + org.springframework.security + spring-security-config + ${spring-security.version} + org.springframework.security spring-security-core diff --git a/pom.xml b/pom.xml index 6433b6f227de..02579c03294a 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 11 5.3.39 2.7.18 - 5.8.14 + 5.7.12 5.6.15.Final 6.2.5.Final 42.7.3 From 4a4a8bcb22796e5b22c9bbb1796e3458b48f1c07 Mon Sep 17 00:00:00 2001 From: Brian Keese Date: Tue, 15 Oct 2024 11:38:54 -0500 Subject: [PATCH 121/632] Fix full-text indexing for files over the character limit The error handler for files over the limit logged the correct message, but never actually added the full text to the index doc. --- .../indexobject/IndexFactoryImpl.java | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java index f1ae137b9163..c9a865ec85b2 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java @@ -118,20 +118,10 @@ protected void writeDocument(SolrInputDocument doc, FullTextContentStreams strea ParseContext tikaContext = new ParseContext(); // Use Apache Tika to parse the full text stream(s) + boolean extractionSucceeded = false; try (InputStream fullTextStreams = streams.getStream()) { tikaParser.parse(fullTextStreams, tikaHandler, tikaMetadata, tikaContext); - - // Write Tika metadata to "tika_meta_*" fields. - // This metadata is not very useful right now, - // but we'll keep it just in case it becomes more useful. - for (String name : tikaMetadata.names()) { - for (String value : tikaMetadata.getValues(name)) { - doc.addField("tika_meta_" + name, value); - } - } - - // Save (parsed) full text to "fulltext" field - doc.addField("fulltext", tikaHandler.toString()); + extractionSucceeded = true; } catch (SAXException saxe) { // Check if this SAXException is just a notice that this file was longer than the character limit. // Unfortunately there is not a unique, public exception type to catch here. This error is thrown @@ -141,6 +131,7 @@ protected void writeDocument(SolrInputDocument doc, FullTextContentStreams strea // log that we only indexed up to that configured limit log.info("Full text is larger than the configured limit (discovery.solr.fulltext.charLimit)." + " Only the first {} characters were indexed.", charLimit); + extractionSucceeded = true; } else { log.error("Tika parsing error. Could not index full text.", saxe); throw new IOException("Tika parsing error. Could not index full text.", saxe); @@ -148,11 +139,19 @@ protected void writeDocument(SolrInputDocument doc, FullTextContentStreams strea } catch (TikaException | IOException ex) { log.error("Tika parsing error. Could not index full text.", ex); throw new IOException("Tika parsing error. Could not index full text.", ex); - } finally { - // Add document to index - solr.add(doc); } - return; + if (extractionSucceeded) { + // Write Tika metadata to "tika_meta_*" fields. + // This metadata is not very useful right now, + // but we'll keep it just in case it becomes more useful. + for (String name : tikaMetadata.names()) { + for (String value : tikaMetadata.getValues(name)) { + doc.addField("tika_meta_" + name, value); + } + } + // Save (parsed) full text to "fulltext" field + doc.addField("fulltext", tikaHandler.toString()); + } } // Add document to index solr.add(doc); From 6018f926d7a599b081664bf862531ededb645839 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 15 Oct 2024 23:23:24 +0200 Subject: [PATCH 122/632] Add Eclipse JDT .factorypath to .gitignore (cherry picked from commit 9ce645e08b50cd752e48a640e340b55466f019be) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2fcb46b9932c..529351edc5c2 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ tags .project .classpath .checkstyle +.factorypath ## Ignore project files created by IntelliJ IDEA *.iml From f6ec314ef762ce83037ad94940cfc352246e300d Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 15 Oct 2024 23:23:24 +0200 Subject: [PATCH 123/632] Add Eclipse JDT .factorypath to .gitignore (cherry picked from commit 9ce645e08b50cd752e48a640e340b55466f019be) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2fcb46b9932c..529351edc5c2 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ tags .project .classpath .checkstyle +.factorypath ## Ignore project files created by IntelliJ IDEA *.iml From 42be64cf941083c7f517e81c70651f78fcedd788 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 20:21:19 +0000 Subject: [PATCH 124/632] Bump the maven group with 3 updates Bumps the maven group with 3 updates: [org.springframework:spring-context](https://github.com/spring-projects/spring-framework), org.eclipse.jetty:jetty-server and org.eclipse.jetty:jetty-http. Updates `org.springframework:spring-context` from 6.1.13 to 6.1.14 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.13...v6.1.14) Updates `org.eclipse.jetty:jetty-server` from 9.4.54.v20240208 to 9.4.55.v20240627 Updates `org.eclipse.jetty:jetty-http` from 9.4.54.v20240208 to 9.4.55.v20240627 --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production dependency-group: maven - dependency-name: org.eclipse.jetty:jetty-server dependency-type: direct:production dependency-group: maven - dependency-name: org.eclipse.jetty:jetty-http dependency-type: direct:production dependency-group: maven ... Signed-off-by: dependabot[bot] (cherry picked from commit e96dbfefeb6924c4b17c66535215878576190fb5) --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e92469dff3c4..3eec65d4a9fd 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 17 - 6.1.13 + 6.1.14 3.3.4 6.3.3 6.4.8.Final @@ -38,7 +38,7 @@ 4.0.5 1.1.1 - 9.4.54.v20240208 + 9.4.55.v20240627 2.23.1 2.0.31 1.19.0 From e6d4ea07f6ab49b7baa63fe1dfd45ea1ee09d126 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 1 Nov 2024 14:12:25 +0100 Subject: [PATCH 125/632] fix typo in endpoint path (cherry picked from commit 6a7b0fc06b48ad145cc654d38675dcdbe0fafa70) --- .../app/rest/ItemOwningCollectionUpdateRestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index eec5b15825ac..db238e1a5c83 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -43,7 +43,7 @@ import org.springframework.web.bind.annotation.RestController; /** - * This controller will handle all the incoming calls on the api/code/items/{uuid}/owningCollection endpoint + * This controller will handle all the incoming calls on the api/core/items/{uuid}/owningCollection endpoint * where the uuid corresponds to the item of which you want to edit the owning collection. */ @RestController From 10a95ae92aa78fbd1998d439015eb91a7bc9b75c Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 23 Oct 2024 08:53:01 +0200 Subject: [PATCH 126/632] 119602: Add accessibility settings metadata field --- dspace/config/registries/dspace-types.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dspace/config/registries/dspace-types.xml b/dspace/config/registries/dspace-types.xml index fcdbc9b2af9b..ebe021dad267 100644 --- a/dspace/config/registries/dspace-types.xml +++ b/dspace/config/registries/dspace-types.xml @@ -93,4 +93,12 @@ Stores the timestamp related to the user authentication on ORCID + + dspace + accessibility + settings + Metadata field storing the user-configured accessibility settings values for the EPerson. + + + From 68266cd3c19d27dbed4f181bc12017d46fc6f64c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 6 Nov 2024 13:36:17 -0600 Subject: [PATCH 127/632] Move logging of test methods to Abstract*Test classes in dspace-api. That way they work for **both** dspace-server-webapp and dspace-api tests. (cherry picked from commit bd20c9262b1992ff15033701fa01738329864b1b) --- .../dspace/AbstractDSpaceIntegrationTest.java | 24 ++++++++++ .../java/org/dspace/AbstractDSpaceTest.java | 23 ++++++++++ .../AbstractControllerIntegrationTest.java | 4 -- .../AbstractWebClientIntegrationTest.java | 4 -- .../test/LoggingTestExecutionListener.java | 44 ------------------- 5 files changed, 47 insertions(+), 52 deletions(-) delete mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/test/LoggingTestExecutionListener.java diff --git a/dspace-api/src/test/java/org/dspace/AbstractDSpaceIntegrationTest.java b/dspace-api/src/test/java/org/dspace/AbstractDSpaceIntegrationTest.java index 5a5ce8bf6d4c..791fdbc66abc 100644 --- a/dspace-api/src/test/java/org/dspace/AbstractDSpaceIntegrationTest.java +++ b/dspace-api/src/test/java/org/dspace/AbstractDSpaceIntegrationTest.java @@ -21,8 +21,12 @@ import org.dspace.discovery.SearchUtils; import org.dspace.servicemanager.DSpaceKernelImpl; import org.dspace.servicemanager.DSpaceKernelInit; +import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.rules.TestName; /** * Abstract Test class copied from DSpace API @@ -46,6 +50,12 @@ public class AbstractDSpaceIntegrationTest { */ protected static DSpaceKernelImpl kernelImpl; + /** + * Obtain the TestName from JUnit, so that we can print it out in the test logs (see below) + */ + @Rule + public TestName testName = new TestName(); + /** * Default constructor */ @@ -90,6 +100,20 @@ public static void initTestEnvironment() { } } + @Before + public void printTestMethodBefore() { + // Log the test method being executed. Put lines around it to make it stand out. + log.info("---"); + log.info("Starting execution of test method: {}()", testName.getMethodName()); + log.info("---"); + } + + @After + public void printTestMethodAfter() { + // Log the test method just completed. + log.info("Finished execution of test method: {}()", testName.getMethodName()); + } + /** * This method will be run after all tests finish as per @AfterClass. It * will clean resources initialized by the @BeforeClass methods. diff --git a/dspace-api/src/test/java/org/dspace/AbstractDSpaceTest.java b/dspace-api/src/test/java/org/dspace/AbstractDSpaceTest.java index 36477556d3de..136af83f076f 100644 --- a/dspace-api/src/test/java/org/dspace/AbstractDSpaceTest.java +++ b/dspace-api/src/test/java/org/dspace/AbstractDSpaceTest.java @@ -18,9 +18,13 @@ import org.apache.logging.log4j.Logger; import org.dspace.servicemanager.DSpaceKernelImpl; import org.dspace.servicemanager.DSpaceKernelInit; +import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; +import org.junit.Rule; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; @@ -62,6 +66,12 @@ protected AbstractDSpaceTest() { } */ protected static DSpaceKernelImpl kernelImpl; + /** + * Obtain the TestName from JUnit, so that we can print it out in the test logs (see below) + */ + @Rule + public TestName testName = new TestName(); + /** * This method will be run before the first test as per @BeforeClass. It will * initialize shared resources required for all tests of this class. @@ -94,6 +104,19 @@ public static void initKernel() { } } + @Before + public void printTestMethodBefore() { + // Log the test method being executed. Put lines around it to make it stand out. + log.info("---"); + log.info("Starting execution of test method: {}()", testName.getMethodName()); + log.info("---"); + } + + @After + public void printTestMethodAfter() { + // Log the test method just completed. + log.info("Finished execution of test method: {}()", testName.getMethodName()); + } /** * This method will be run after all tests finish as per @AfterClass. It diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java index 00339ba2e482..28c5560edf31 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java @@ -39,7 +39,6 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; @@ -75,9 +74,6 @@ @WebAppConfiguration // Load our src/test/resources/application-test.properties to override some settings in default application.properties @TestPropertySource(locations = "classpath:application-test.properties") -// Enable our custom Logging listener to log when each test method starts/stops -@TestExecutionListeners(listeners = {LoggingTestExecutionListener.class}, - mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS) public class AbstractControllerIntegrationTest extends AbstractIntegrationTestWithDatabase { protected static final String AUTHORIZATION_HEADER = "Authorization"; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java index 75b0143e3e65..df6afcb16e32 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java @@ -22,7 +22,6 @@ import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; @@ -52,9 +51,6 @@ @ContextConfiguration(initializers = { DSpaceKernelInitializer.class, DSpaceConfigurationInitializer.class }) // Load our src/test/resources/application-test.properties to override some settings in default application.properties @TestPropertySource(locations = "classpath:application-test.properties") -// Enable our custom Logging listener to log when each test method starts/stops -@TestExecutionListeners(listeners = {LoggingTestExecutionListener.class}, - mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS) public class AbstractWebClientIntegrationTest extends AbstractIntegrationTestWithDatabase { // (Random) port chosen for test web server @LocalServerPort diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/LoggingTestExecutionListener.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/LoggingTestExecutionListener.java deleted file mode 100644 index 2a04bab2041c..000000000000 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/LoggingTestExecutionListener.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.test; - -import org.apache.logging.log4j.Logger; -import org.springframework.test.context.TestContext; -import org.springframework.test.context.support.AbstractTestExecutionListener; - -/** - * Custom DSpace TestExecutionListener which logs messages whenever a specific Test Case (i.e. test method) has - * started or ended execution. This makes Test environment logs easier to read/understand as you know which method has - * caused errors, etc. - */ -public class LoggingTestExecutionListener extends AbstractTestExecutionListener { - - private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(LoggingTestExecutionListener.class); - - /** - * Before each test method is run - * @param testContext - */ - @Override - public void beforeTestMethod(TestContext testContext) { - // Log the test method being executed. Put lines around it to make it stand out. - log.info("---"); - log.info("Starting execution of test method: {}()", testContext.getTestMethod().getName()); - log.info("---"); - } - - /** - * After each test method is run - * @param testContext - */ - @Override - public void afterTestMethod(TestContext testContext) { - // Log the test method just completed. - log.info("Finished execution of test method: {}()", testContext.getTestMethod().getName()); - } -} From 2bf5baf69779cfde398f368cb756a0576d82794b Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 6 Nov 2024 13:36:17 -0600 Subject: [PATCH 128/632] Move logging of test methods to Abstract*Test classes in dspace-api. That way they work for **both** dspace-server-webapp and dspace-api tests. (cherry picked from commit bd20c9262b1992ff15033701fa01738329864b1b) --- .../dspace/AbstractDSpaceIntegrationTest.java | 24 ++++++++++ .../java/org/dspace/AbstractDSpaceTest.java | 23 ++++++++++ .../AbstractControllerIntegrationTest.java | 4 -- .../AbstractWebClientIntegrationTest.java | 4 -- .../test/LoggingTestExecutionListener.java | 44 ------------------- 5 files changed, 47 insertions(+), 52 deletions(-) delete mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/test/LoggingTestExecutionListener.java diff --git a/dspace-api/src/test/java/org/dspace/AbstractDSpaceIntegrationTest.java b/dspace-api/src/test/java/org/dspace/AbstractDSpaceIntegrationTest.java index 5a5ce8bf6d4c..791fdbc66abc 100644 --- a/dspace-api/src/test/java/org/dspace/AbstractDSpaceIntegrationTest.java +++ b/dspace-api/src/test/java/org/dspace/AbstractDSpaceIntegrationTest.java @@ -21,8 +21,12 @@ import org.dspace.discovery.SearchUtils; import org.dspace.servicemanager.DSpaceKernelImpl; import org.dspace.servicemanager.DSpaceKernelInit; +import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.rules.TestName; /** * Abstract Test class copied from DSpace API @@ -46,6 +50,12 @@ public class AbstractDSpaceIntegrationTest { */ protected static DSpaceKernelImpl kernelImpl; + /** + * Obtain the TestName from JUnit, so that we can print it out in the test logs (see below) + */ + @Rule + public TestName testName = new TestName(); + /** * Default constructor */ @@ -90,6 +100,20 @@ public static void initTestEnvironment() { } } + @Before + public void printTestMethodBefore() { + // Log the test method being executed. Put lines around it to make it stand out. + log.info("---"); + log.info("Starting execution of test method: {}()", testName.getMethodName()); + log.info("---"); + } + + @After + public void printTestMethodAfter() { + // Log the test method just completed. + log.info("Finished execution of test method: {}()", testName.getMethodName()); + } + /** * This method will be run after all tests finish as per @AfterClass. It * will clean resources initialized by the @BeforeClass methods. diff --git a/dspace-api/src/test/java/org/dspace/AbstractDSpaceTest.java b/dspace-api/src/test/java/org/dspace/AbstractDSpaceTest.java index 36477556d3de..136af83f076f 100644 --- a/dspace-api/src/test/java/org/dspace/AbstractDSpaceTest.java +++ b/dspace-api/src/test/java/org/dspace/AbstractDSpaceTest.java @@ -18,9 +18,13 @@ import org.apache.logging.log4j.Logger; import org.dspace.servicemanager.DSpaceKernelImpl; import org.dspace.servicemanager.DSpaceKernelInit; +import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; +import org.junit.Rule; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; @@ -62,6 +66,12 @@ protected AbstractDSpaceTest() { } */ protected static DSpaceKernelImpl kernelImpl; + /** + * Obtain the TestName from JUnit, so that we can print it out in the test logs (see below) + */ + @Rule + public TestName testName = new TestName(); + /** * This method will be run before the first test as per @BeforeClass. It will * initialize shared resources required for all tests of this class. @@ -94,6 +104,19 @@ public static void initKernel() { } } + @Before + public void printTestMethodBefore() { + // Log the test method being executed. Put lines around it to make it stand out. + log.info("---"); + log.info("Starting execution of test method: {}()", testName.getMethodName()); + log.info("---"); + } + + @After + public void printTestMethodAfter() { + // Log the test method just completed. + log.info("Finished execution of test method: {}()", testName.getMethodName()); + } /** * This method will be run after all tests finish as per @AfterClass. It diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java index c4ab14250bca..26dac5facdec 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java @@ -42,7 +42,6 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; @@ -80,9 +79,6 @@ @WebAppConfiguration // Load our src/test/resources/application-test.properties to override some settings in default application.properties @TestPropertySource(locations = "classpath:application-test.properties") -// Enable our custom Logging listener to log when each test method starts/stops -@TestExecutionListeners(listeners = {LoggingTestExecutionListener.class}, - mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS) public class AbstractControllerIntegrationTest extends AbstractIntegrationTestWithDatabase { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java index 7745fba96c3f..e4ef1c741f72 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java @@ -22,7 +22,6 @@ import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; @@ -52,9 +51,6 @@ @ContextConfiguration(initializers = { DSpaceKernelInitializer.class, DSpaceConfigurationInitializer.class }) // Load our src/test/resources/application-test.properties to override some settings in default application.properties @TestPropertySource(locations = "classpath:application-test.properties") -// Enable our custom Logging listener to log when each test method starts/stops -@TestExecutionListeners(listeners = {LoggingTestExecutionListener.class}, - mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS) public class AbstractWebClientIntegrationTest extends AbstractIntegrationTestWithDatabase { // (Random) port chosen for test web server @LocalServerPort diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/LoggingTestExecutionListener.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/LoggingTestExecutionListener.java deleted file mode 100644 index 2a04bab2041c..000000000000 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/LoggingTestExecutionListener.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.test; - -import org.apache.logging.log4j.Logger; -import org.springframework.test.context.TestContext; -import org.springframework.test.context.support.AbstractTestExecutionListener; - -/** - * Custom DSpace TestExecutionListener which logs messages whenever a specific Test Case (i.e. test method) has - * started or ended execution. This makes Test environment logs easier to read/understand as you know which method has - * caused errors, etc. - */ -public class LoggingTestExecutionListener extends AbstractTestExecutionListener { - - private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(LoggingTestExecutionListener.class); - - /** - * Before each test method is run - * @param testContext - */ - @Override - public void beforeTestMethod(TestContext testContext) { - // Log the test method being executed. Put lines around it to make it stand out. - log.info("---"); - log.info("Starting execution of test method: {}()", testContext.getTestMethod().getName()); - log.info("---"); - } - - /** - * After each test method is run - * @param testContext - */ - @Override - public void afterTestMethod(TestContext testContext) { - // Log the test method just completed. - log.info("Finished execution of test method: {}()", testContext.getTestMethod().getName()); - } -} From 831db33018cdcfa132dc0b1da0f427aca0d03585 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 14 Oct 2024 17:03:15 +0200 Subject: [PATCH 129/632] 118774: status of doi should be set to TO_BE_DELETED when related item is removed permanently (cherry picked from commit 352f4c21523237cefa5bf67c99f7d7b26a51d72b) --- .../src/main/java/org/dspace/content/ItemServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index b2cc3e939d87..ad4156328aeb 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -66,6 +66,7 @@ import org.dspace.harvest.HarvestedItem; import org.dspace.harvest.service.HarvestedItemService; import org.dspace.identifier.DOI; +import org.dspace.identifier.DOIIdentifierProvider; import org.dspace.identifier.IdentifierException; import org.dspace.identifier.service.DOIService; import org.dspace.identifier.service.IdentifierService; @@ -848,6 +849,7 @@ protected void rawDelete(Context context, Item item) throws AuthorizeException, DOI doi = doiService.findDOIByDSpaceObject(context, item); if (doi != null) { doi.setDSpaceObject(null); + doi.setStatus(DOIIdentifierProvider.TO_BE_DELETED); } // remove version attached to the item From 578726c25174d97710b4d5e12d2ed14c874735d3 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 14 Oct 2024 17:03:15 +0200 Subject: [PATCH 130/632] 118774: status of doi should be set to TO_BE_DELETED when related item is removed permanently (cherry picked from commit 352f4c21523237cefa5bf67c99f7d7b26a51d72b) --- .../src/main/java/org/dspace/content/ItemServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index cceb954ebe2f..cb6cb15054cb 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -67,6 +67,7 @@ import org.dspace.harvest.HarvestedItem; import org.dspace.harvest.service.HarvestedItemService; import org.dspace.identifier.DOI; +import org.dspace.identifier.DOIIdentifierProvider; import org.dspace.identifier.IdentifierException; import org.dspace.identifier.service.DOIService; import org.dspace.identifier.service.IdentifierService; @@ -851,6 +852,7 @@ protected void rawDelete(Context context, Item item) throws AuthorizeException, DOI doi = doiService.findDOIByDSpaceObject(context, item); if (doi != null) { doi.setDSpaceObject(null); + doi.setStatus(DOIIdentifierProvider.TO_BE_DELETED); } // remove version attached to the item From fde825265db6b44ca0bd852ec6df56ca3f3eacfe Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 27 Sep 2024 12:52:03 +0200 Subject: [PATCH 131/632] fix: performance of claiming workflow task (cherry picked from commit 27dd5a2ec58970256964f15f0879834c436aa542) --- .../storedcomponents/PoolTaskServiceImpl.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java index fb673725e181..d3c8f6334d8f 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java @@ -13,6 +13,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.Set; import org.apache.commons.collections4.CollectionUtils; @@ -100,12 +101,17 @@ public PoolTask findByWorkflowIdAndEPerson(Context context, XmlWorkflowItem work //If the user does not have a claimedtask yet, see whether one of the groups of the user has pooltasks //for this workflow item Set groups = groupService.allMemberGroupsSet(context, ePerson); - for (Group group : groups) { - poolTask = poolTaskDAO.findByWorkflowItemAndGroup(context, group, workflowItem); - if (poolTask != null) { - return poolTask; - } + List generalTasks = poolTaskDAO.findByWorkflowItem(context, workflowItem); + Optional firstClaimedTask = groups.stream() + .flatMap(group -> generalTasks.stream() + .filter(f -> f.getGroup().getID().equals(group.getID())) + .findFirst() + .stream()) + .findFirst(); + + if (firstClaimedTask.isPresent()) { + return firstClaimedTask.get(); } } } From b8dc7683814de4fe72b2e26218c99b8ea989a333 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 27 Sep 2024 12:52:03 +0200 Subject: [PATCH 132/632] fix: performance of claiming workflow task (cherry picked from commit 27dd5a2ec58970256964f15f0879834c436aa542) --- .../storedcomponents/PoolTaskServiceImpl.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java index fb673725e181..d3c8f6334d8f 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java @@ -13,6 +13,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.Set; import org.apache.commons.collections4.CollectionUtils; @@ -100,12 +101,17 @@ public PoolTask findByWorkflowIdAndEPerson(Context context, XmlWorkflowItem work //If the user does not have a claimedtask yet, see whether one of the groups of the user has pooltasks //for this workflow item Set groups = groupService.allMemberGroupsSet(context, ePerson); - for (Group group : groups) { - poolTask = poolTaskDAO.findByWorkflowItemAndGroup(context, group, workflowItem); - if (poolTask != null) { - return poolTask; - } + List generalTasks = poolTaskDAO.findByWorkflowItem(context, workflowItem); + Optional firstClaimedTask = groups.stream() + .flatMap(group -> generalTasks.stream() + .filter(f -> f.getGroup().getID().equals(group.getID())) + .findFirst() + .stream()) + .findFirst(); + + if (firstClaimedTask.isPresent()) { + return firstClaimedTask.get(); } } } From 6283c6e072edea6d867551e94d35da9aec1c123c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 11 Nov 2024 10:26:29 -0600 Subject: [PATCH 133/632] Add a job to test Docker deployment with the built images (cherry picked from commit f1d12ef4560bdf7dffea29c5545d8d51d596cd17) --- .github/workflows/docker.yml | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a9ff8760e763..12d49689b319 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -147,4 +147,45 @@ jobs: tags_flavor: suffix=-loadsql secrets: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} - DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }} \ No newline at end of file + DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + ######################################################################## + # Test Deployment via Docker to ensure images are working properly + ######################################################################## + docker-deploy: + # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace' + if: github.repository == 'dspace/dspace' + runs-on: ubuntu-latest + # Must run after all major images are built + needs: [dspace-test, dspace-cli, dspace-postgres-pgcrypto, dspace-solr] + steps: + - name: Checkout codebase + uses: actions/checkout@v4 + # Start backend using our compose script in the codebase. + - name: Start backend in Docker + env: + # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 + dspace__P__server__P__url: http://127.0.0.1:8080/server + run: | + docker compose -f docker-compose.yml up -d + sleep 10 + docker container ls + # Create a test admin account. Load test data from a simple set of AIPs as defined in cli.ingest.yml + - name: Load test data into Backend + run: | + docker compose -f docker-compose-cli.yml run --rm dspace-cli create-administrator -e test@test.edu -f admin -l user -p admin -c en + docker compose -f docker-compose-cli.yml -f dspace/src/main/docker-compose/cli.ingest.yml run --rm dspace-cli + # Verify backend started successfully. + # 1. Make sure root endpoint is responding (check for dspace.name defined in docker-compose.yml) + # 2. Also check /collections endpoint to ensure the test data loaded properly (check for a collection name in AIPs) + - name: Verify backend is responding properly + run: | + result=$(wget -O- -q http://127.0.0.1:8080/server/api) + echo "$result" + echo "$result" | grep -oE "\"DSpace Started with Docker Compose\"," + result=$(wget -O- -q http://127.0.0.1:8080/server/api/core/collections) + echo "$result" + echo "$result" | grep -oE "\"Dog in Yard\"," + - name: Shutdown Docker containers + run: | + docker compose -f docker-compose.yml down From 0c3aee117cef30e8ebe9664eb634e8fe27b8c7f3 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 11 Nov 2024 14:10:44 -0600 Subject: [PATCH 134/632] Add a check that the Handle Server can be started & works properly (cherry picked from commit c96b5316d5b4af9e479c814fd0048dac002cbffa) --- .github/workflows/docker.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 12d49689b319..660c9eb817a6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -186,6 +186,25 @@ jobs: result=$(wget -O- -q http://127.0.0.1:8080/server/api/core/collections) echo "$result" echo "$result" | grep -oE "\"Dog in Yard\"," + # Verify Handle Server can be stared and is working properly + # 1. First generate the "[dspace]/handle-server" folder with the sitebndl.zip + # 2. Start the Handle Server (and wait 20 seconds to let it start up) + # 3. Verify logs do NOT include "Exception" in the text (as that means an error occurred) + # 4. Check that Handle Proxy HTML page is responding on default port (8000) + - name: Verify Handle Server is working properly + run: | + docker exec -i dspace /dspace/bin/make-handle-config + docker exec -i dspace /dspace/bin/start-handle-server + sleep 20 + echo "Checking for errors in handle-server.log..." + result=$(docker exec -i dspace cat /dspace/log/handle-server.log) + echo "$result" + echo "$result" | grep -vqz "Exception" + echo "Checking to see if Handle Proxy webpage is available..." + result=$(wget -O- -q http://127.0.0.1:8000/) + echo "$result" + echo "$result" | grep -oE "Handle Proxy" + # Shutdown our containers - name: Shutdown Docker containers run: | docker compose -f docker-compose.yml down From 77b76b32f1b981fee485fdb517144d35f06243bc Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 12 Nov 2024 13:50:57 -0600 Subject: [PATCH 135/632] Ensure Docker images built from PRs are stored as artifacts. This allows us to use those new images when testing deployment (in docker-deploy) (cherry picked from commit eb766c7cdf1d92898cc8c2a1ba067ba8dac2abad) --- .github/workflows/docker.yml | 34 +++++++++--- .github/workflows/reusable-docker-build.yml | 58 +++++++++++++++++++-- 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 660c9eb817a6..eed8de5a8722 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -157,27 +157,47 @@ jobs: if: github.repository == 'dspace/dspace' runs-on: ubuntu-latest # Must run after all major images are built - needs: [dspace-test, dspace-cli, dspace-postgres-pgcrypto, dspace-solr] + needs: [dspace, dspace-test, dspace-cli, dspace-postgres-pgcrypto, dspace-solr] steps: + # Checkout our codebase (to get access to Docker Compose scripts) - name: Checkout codebase uses: actions/checkout@v4 - # Start backend using our compose script in the codebase. + # For PRs, download Docker image artifacts (built by reusable-docker-build.yml for all PRs) + - name: Download Docker image artifacts (for PRs) + if: github.event_name == 'pull_request' + uses: actions/download-artifact@v4 + with: + # Download all Docker images (TAR files) into the /tmp/docker directory + pattern: docker-image-* + path: /tmp/docker + merge-multiple: true + # For PRs, load each of the images into Docker by calling "docker image load" for each. + # This ensures we are using the images built from this PR & not the prior versions on DockerHub + - name: Load all downloaded Docker images (for PRs) + if: github.event_name == 'pull_request' + run: | + find /tmp/docker -type f -name "*.tar" -exec docker image load --input "{}" \; + docker image ls -a + # Start backend using our compose script in the codebase. - name: Start backend in Docker env: # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 dspace__P__server__P__url: http://127.0.0.1:8080/server + # Force using "pr-testing" version of Docker images. The "pr-testing" tag is a temporary tag that we assign to + # all PR-built docker images in reusabe-docker-build.yml + DSPACE_VER: pr-testing run: | docker compose -f docker-compose.yml up -d sleep 10 docker container ls - # Create a test admin account. Load test data from a simple set of AIPs as defined in cli.ingest.yml + # Create a test admin account. Load test data from a simple set of AIPs as defined in cli.ingest.yml - name: Load test data into Backend run: | docker compose -f docker-compose-cli.yml run --rm dspace-cli create-administrator -e test@test.edu -f admin -l user -p admin -c en docker compose -f docker-compose-cli.yml -f dspace/src/main/docker-compose/cli.ingest.yml run --rm dspace-cli - # Verify backend started successfully. - # 1. Make sure root endpoint is responding (check for dspace.name defined in docker-compose.yml) - # 2. Also check /collections endpoint to ensure the test data loaded properly (check for a collection name in AIPs) + # Verify backend started successfully. + # 1. Make sure root endpoint is responding (check for dspace.name defined in docker-compose.yml) + # 2. Also check /collections endpoint to ensure the test data loaded properly (check for a collection name in AIPs) - name: Verify backend is responding properly run: | result=$(wget -O- -q http://127.0.0.1:8080/server/api) @@ -204,7 +224,7 @@ jobs: result=$(wget -O- -q http://127.0.0.1:8000/) echo "$result" echo "$result" | grep -oE "Handle Proxy" - # Shutdown our containers + # Shutdown our containers - name: Shutdown Docker containers run: | docker compose -f docker-compose.yml down diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index 7a8de661fa68..91aa93c54ab2 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -113,6 +113,12 @@ jobs: - name: Set up QEMU emulation to build for multiple architectures uses: docker/setup-qemu-action@v3 + #------------------------------------------------------------ + # Build & deploy steps for new commits to a branch (non-PRs) + # + # These steps build the images, push to DockerHub, and + # (if necessary) redeploy demo/sandbox sites. + #------------------------------------------------------------ # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push @@ -125,6 +131,7 @@ jobs: # https://github.com/docker/metadata-action # Get Metadata for docker_build_deps step below - name: Sync metadata (tags, labels) from GitHub to Docker for image + if: ${{ ! matrix.isPr }} id: meta_build uses: docker/metadata-action@v5 with: @@ -133,7 +140,9 @@ jobs: flavor: ${{ env.TAGS_FLAVOR }} # https://github.com/docker/build-push-action - - name: Build and push image + - name: Build and push image to DockerHub + # Only build & push if not a PR + if: ${{ ! matrix.isPr }} id: docker_build uses: docker/build-push-action@v5 with: @@ -142,9 +151,7 @@ jobs: context: ${{ inputs.dockerfile_context }} file: ${{ inputs.dockerfile_path }} platforms: ${{ matrix.arch }} - # For pull requests, we run the Docker build (to ensure no PR changes break the build), - # but we ONLY do an image push to DockerHub if it's NOT a PR - push: ${{ ! matrix.isPr }} + push: true # Use tags / labels provided by 'docker/metadata-action' above tags: ${{ steps.meta_build.outputs.tags }} labels: ${{ steps.meta_build.outputs.labels }} @@ -189,11 +196,54 @@ jobs: run: | curl -X POST $REDEPLOY_DEMO_URL + #------------------------------------------------------------- + # Build steps for PRs only + # + # These steps build the images and store as a build artifact. + # These artifacts can then be used by later jobs to run the + # brand-new images for automated testing. + #-------------------------------------------------------------- + # Get Metadata for docker_build_deps step below + - name: Create metadata (tags, labels) for local Docker image + if: matrix.isPr + id: meta_build_pr + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + # Hardcode to use custom "pr-testing" tag because that will allow us to spin up this PR + # for testing in docker.yml + tags: pr-testing + flavor: ${{ env.TAGS_FLAVOR }} + # Build local image and stores in a TAR file in /tmp directory + - name: Build and push image to local image + if: matrix.isPr + uses: docker/build-push-action@v5 + with: + build-contexts: | + ${{ inputs.dockerfile_additional_contexts }} + context: ${{ inputs.dockerfile_context }} + file: ${{ inputs.dockerfile_path }} + platforms: ${{ matrix.arch }} + tags: ${{ steps.meta_build_pr.outputs.tags }} + labels: ${{ steps.meta_build_pr.outputs.labels }} + # Export image to a local TAR file + outputs: type=docker,dest=/tmp/${{ inputs.build_id }}.tar + # Upload the local docker image (in TAR file) to a build Artifact + - name: Upload local image to artifact + if: matrix.isPr + uses: actions/upload-artifact@v4 + with: + name: docker-image-${{ inputs.build_id }} + path: /tmp/${{ inputs.build_id }}.tar + if-no-files-found: error + retention-days: 1 + # Merge Docker digests (from various architectures) into a manifest. # This runs after all Docker builds complete above, and it tells hub.docker.com # that these builds should be all included in the manifest for this tag. # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) docker-build_manifest: + # Only run if this is NOT a PR if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-latest needs: From cf3da4585551862cf6c74ad1e7906a6a08c162c6 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 11 Nov 2024 16:45:59 -0600 Subject: [PATCH 136/632] Fix error in running Handle Server in GitHub Actions. Must exclude "spring-jcl" from dependencies as it conflicts with "commons-logging" (used by more of our dependencies) (cherry picked from commit 31312b800a6bed795d5ca31bf2dfb445fc709c4d) --- dspace-api/pom.xml | 7 +++++++ dspace-iiif/pom.xml | 5 +++++ dspace-oai/pom.xml | 5 +++++ dspace-rdf/pom.xml | 5 +++++ dspace-server-webapp/pom.xml | 5 +++++ dspace-services/pom.xml | 7 +++++++ dspace-sword/pom.xml | 5 +++++ dspace-swordv2/pom.xml | 5 +++++ pom.xml | 7 +++++++ 9 files changed, 51 insertions(+) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index dfb3f030ac0e..c51685fdb425 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -388,6 +388,13 @@ org.springframework spring-orm + + + + org.springframework + spring-jcl + + diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index cd2b69288d2e..030ac31b3843 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -44,6 +44,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 4158ec74f34d..29644392d540 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -80,6 +80,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index d7db7fe76e8a..3d11794d86a2 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -67,6 +67,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 759ad724b9b6..290f8afb0dc6 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -468,6 +468,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index d99132309100..6b2bf191acd5 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -90,6 +90,13 @@ spring-context-support ${spring.version} compile + + + + org.springframework + spring-jcl + + org.apache.commons diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index a808d0bbfeb9..ac84a674c455 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -55,6 +55,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index c0549abcc88c..f22acf9dc9e0 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -78,6 +78,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/pom.xml b/pom.xml index 3eec65d4a9fd..5be05ca44e36 100644 --- a/pom.xml +++ b/pom.xml @@ -1155,6 +1155,13 @@ org.springframework spring-orm ${spring.version} + + + + org.springframework + spring-jcl + + org.swordapp From 48cb5e2082fb0e778c703e2b218a1ab361358af0 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 13 Nov 2024 09:17:30 -0600 Subject: [PATCH 137/632] Ensure "host" command is installed in images, so "bin/make-handle-config" will work. (cherry picked from commit a2172b37c3bb57a55e5a82ac2003ef20918c8984) --- Dockerfile | 5 +++++ Dockerfile.test | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Dockerfile b/Dockerfile index 75817980379c..fdf2808c1c9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,6 +58,11 @@ ENV DSPACE_INSTALL=/dspace # Copy the /dspace directory from 'ant_build' container to /dspace in this container COPY --from=ant_build /dspace $DSPACE_INSTALL WORKDIR $DSPACE_INSTALL +# Need host command for "[dspace]/bin/make-handle-config" +RUN apt-get update \ + && apt-get install -y --no-install-recommends host \ + && apt-get purge -y --auto-remove \ + && rm -rf /var/lib/apt/lists/* # Expose Tomcat port EXPOSE 8080 # Give java extra memory (2GB) diff --git a/Dockerfile.test b/Dockerfile.test index f3acef00e825..218126b17aab 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -57,6 +57,11 @@ ENV DSPACE_INSTALL=/dspace # Copy the /dspace directory from 'ant_build' container to /dspace in this container COPY --from=ant_build /dspace $DSPACE_INSTALL WORKDIR $DSPACE_INSTALL +# Need host command for "[dspace]/bin/make-handle-config" +RUN apt-get update \ + && apt-get install -y --no-install-recommends host \ + && apt-get purge -y --auto-remove \ + && rm -rf /var/lib/apt/lists/* # Expose Tomcat port and debugging port EXPOSE 8080 8000 # Give java extra memory (2GB) From 2253d79c1906149c2417d9f1b42fba243fc8c78b Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 13 Nov 2024 10:37:53 -0600 Subject: [PATCH 138/632] Bug fixes. Ensure all steps of docker-deploy use the same environment variables. Ensure Handle Server HTTP port is open (cherry picked from commit daa4abba62d500bb4a9f26dd9f62c156780ee22a) --- .github/workflows/docker.yml | 13 +++++++------ Dockerfile | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index eed8de5a8722..5197ed3bfe39 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -158,6 +158,12 @@ jobs: runs-on: ubuntu-latest # Must run after all major images are built needs: [dspace, dspace-test, dspace-cli, dspace-postgres-pgcrypto, dspace-solr] + env: + # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 + dspace__P__server__P__url: http://127.0.0.1:8080/server + # Force using "pr-testing" version of all Docker images. The "pr-testing" tag is a temporary tag that we + # assign to all PR-built docker images in reusabe-docker-build.yml + DSPACE_VER: pr-testing steps: # Checkout our codebase (to get access to Docker Compose scripts) - name: Checkout codebase @@ -180,12 +186,6 @@ jobs: docker image ls -a # Start backend using our compose script in the codebase. - name: Start backend in Docker - env: - # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 - dspace__P__server__P__url: http://127.0.0.1:8080/server - # Force using "pr-testing" version of Docker images. The "pr-testing" tag is a temporary tag that we assign to - # all PR-built docker images in reusabe-docker-build.yml - DSPACE_VER: pr-testing run: | docker compose -f docker-compose.yml up -d sleep 10 @@ -214,6 +214,7 @@ jobs: - name: Verify Handle Server is working properly run: | docker exec -i dspace /dspace/bin/make-handle-config + echo "Starting Handle Server..." docker exec -i dspace /dspace/bin/start-handle-server sleep 20 echo "Checking for errors in handle-server.log..." diff --git a/Dockerfile b/Dockerfile index fdf2808c1c9a..d3f85a5bd641 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,8 +63,8 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends host \ && apt-get purge -y --auto-remove \ && rm -rf /var/lib/apt/lists/* -# Expose Tomcat port -EXPOSE 8080 +# Expose Tomcat port (8080) & Handle Server HTTP port (8000) +EXPOSE 8080 8000 # Give java extra memory (2GB) ENV JAVA_OPTS=-Xmx2000m # On startup, run DSpace Runnable JAR From 663b871356c4835dc82161e9bd92ba30f79aa953 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 13 Nov 2024 11:45:03 -0600 Subject: [PATCH 139/632] Add check for Handle Server error.log (cherry picked from commit 53d24606431fcd3bd9a7c1a54298190842836e1c) --- .github/workflows/docker.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5197ed3bfe39..1e839e89fceb 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -217,6 +217,10 @@ jobs: echo "Starting Handle Server..." docker exec -i dspace /dspace/bin/start-handle-server sleep 20 + echo "Checking for errors in error.log" + result=$(docker exec -i dspace sh -c "cat /dspace/handle-server/logs/error.log* || echo ''") + echo "$result" + echo "$result" | grep -vqz "Exception" echo "Checking for errors in handle-server.log..." result=$(docker exec -i dspace cat /dspace/log/handle-server.log) echo "$result" From c2e6f6f5d2843a5dd003a3f48ac63171a38a62f1 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 13 Nov 2024 14:27:28 -0600 Subject: [PATCH 140/632] Fix error in Handle Server startup caused by having multiple versions of BouncyCastle in our classpath. Exclude the old version brought in by cnri-servlet-container (cherry picked from commit 6076afec5f9a2bf53ace35abe384dc67dc5c1aef) --- dspace-api/pom.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index c51685fdb425..acac810d6cda 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -413,6 +413,16 @@ org.mortbay.jasper apache-jsp + + + org.bouncycastle + bcpkix-jdk15on + + + org.bouncycastle + bcprov-jdk15on + From c66dde2aa85540dfbfa36f18f581599a6457889e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 11 Nov 2024 10:26:29 -0600 Subject: [PATCH 141/632] Add a job to test Docker deployment with the built images --- .github/workflows/docker.yml | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a9ff8760e763..12d49689b319 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -147,4 +147,45 @@ jobs: tags_flavor: suffix=-loadsql secrets: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} - DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }} \ No newline at end of file + DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + ######################################################################## + # Test Deployment via Docker to ensure images are working properly + ######################################################################## + docker-deploy: + # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace' + if: github.repository == 'dspace/dspace' + runs-on: ubuntu-latest + # Must run after all major images are built + needs: [dspace-test, dspace-cli, dspace-postgres-pgcrypto, dspace-solr] + steps: + - name: Checkout codebase + uses: actions/checkout@v4 + # Start backend using our compose script in the codebase. + - name: Start backend in Docker + env: + # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 + dspace__P__server__P__url: http://127.0.0.1:8080/server + run: | + docker compose -f docker-compose.yml up -d + sleep 10 + docker container ls + # Create a test admin account. Load test data from a simple set of AIPs as defined in cli.ingest.yml + - name: Load test data into Backend + run: | + docker compose -f docker-compose-cli.yml run --rm dspace-cli create-administrator -e test@test.edu -f admin -l user -p admin -c en + docker compose -f docker-compose-cli.yml -f dspace/src/main/docker-compose/cli.ingest.yml run --rm dspace-cli + # Verify backend started successfully. + # 1. Make sure root endpoint is responding (check for dspace.name defined in docker-compose.yml) + # 2. Also check /collections endpoint to ensure the test data loaded properly (check for a collection name in AIPs) + - name: Verify backend is responding properly + run: | + result=$(wget -O- -q http://127.0.0.1:8080/server/api) + echo "$result" + echo "$result" | grep -oE "\"DSpace Started with Docker Compose\"," + result=$(wget -O- -q http://127.0.0.1:8080/server/api/core/collections) + echo "$result" + echo "$result" | grep -oE "\"Dog in Yard\"," + - name: Shutdown Docker containers + run: | + docker compose -f docker-compose.yml down From 3ce85a2df3c548bf7842227cf86d8aa8bd2191b0 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 11 Nov 2024 14:10:44 -0600 Subject: [PATCH 142/632] Add a check that the Handle Server can be started & works properly --- .github/workflows/docker.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 12d49689b319..660c9eb817a6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -186,6 +186,25 @@ jobs: result=$(wget -O- -q http://127.0.0.1:8080/server/api/core/collections) echo "$result" echo "$result" | grep -oE "\"Dog in Yard\"," + # Verify Handle Server can be stared and is working properly + # 1. First generate the "[dspace]/handle-server" folder with the sitebndl.zip + # 2. Start the Handle Server (and wait 20 seconds to let it start up) + # 3. Verify logs do NOT include "Exception" in the text (as that means an error occurred) + # 4. Check that Handle Proxy HTML page is responding on default port (8000) + - name: Verify Handle Server is working properly + run: | + docker exec -i dspace /dspace/bin/make-handle-config + docker exec -i dspace /dspace/bin/start-handle-server + sleep 20 + echo "Checking for errors in handle-server.log..." + result=$(docker exec -i dspace cat /dspace/log/handle-server.log) + echo "$result" + echo "$result" | grep -vqz "Exception" + echo "Checking to see if Handle Proxy webpage is available..." + result=$(wget -O- -q http://127.0.0.1:8000/) + echo "$result" + echo "$result" | grep -oE "Handle Proxy" + # Shutdown our containers - name: Shutdown Docker containers run: | docker compose -f docker-compose.yml down From c1f168245b9756b6109bf6b53bc87317a66aa55c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 12 Nov 2024 13:50:57 -0600 Subject: [PATCH 143/632] Ensure Docker images built from PRs are stored as artifacts. This allows us to use those new images when testing deployment (in docker-deploy) --- .github/workflows/docker.yml | 34 +++++++++--- .github/workflows/reusable-docker-build.yml | 58 +++++++++++++++++++-- 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 660c9eb817a6..eed8de5a8722 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -157,27 +157,47 @@ jobs: if: github.repository == 'dspace/dspace' runs-on: ubuntu-latest # Must run after all major images are built - needs: [dspace-test, dspace-cli, dspace-postgres-pgcrypto, dspace-solr] + needs: [dspace, dspace-test, dspace-cli, dspace-postgres-pgcrypto, dspace-solr] steps: + # Checkout our codebase (to get access to Docker Compose scripts) - name: Checkout codebase uses: actions/checkout@v4 - # Start backend using our compose script in the codebase. + # For PRs, download Docker image artifacts (built by reusable-docker-build.yml for all PRs) + - name: Download Docker image artifacts (for PRs) + if: github.event_name == 'pull_request' + uses: actions/download-artifact@v4 + with: + # Download all Docker images (TAR files) into the /tmp/docker directory + pattern: docker-image-* + path: /tmp/docker + merge-multiple: true + # For PRs, load each of the images into Docker by calling "docker image load" for each. + # This ensures we are using the images built from this PR & not the prior versions on DockerHub + - name: Load all downloaded Docker images (for PRs) + if: github.event_name == 'pull_request' + run: | + find /tmp/docker -type f -name "*.tar" -exec docker image load --input "{}" \; + docker image ls -a + # Start backend using our compose script in the codebase. - name: Start backend in Docker env: # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 dspace__P__server__P__url: http://127.0.0.1:8080/server + # Force using "pr-testing" version of Docker images. The "pr-testing" tag is a temporary tag that we assign to + # all PR-built docker images in reusabe-docker-build.yml + DSPACE_VER: pr-testing run: | docker compose -f docker-compose.yml up -d sleep 10 docker container ls - # Create a test admin account. Load test data from a simple set of AIPs as defined in cli.ingest.yml + # Create a test admin account. Load test data from a simple set of AIPs as defined in cli.ingest.yml - name: Load test data into Backend run: | docker compose -f docker-compose-cli.yml run --rm dspace-cli create-administrator -e test@test.edu -f admin -l user -p admin -c en docker compose -f docker-compose-cli.yml -f dspace/src/main/docker-compose/cli.ingest.yml run --rm dspace-cli - # Verify backend started successfully. - # 1. Make sure root endpoint is responding (check for dspace.name defined in docker-compose.yml) - # 2. Also check /collections endpoint to ensure the test data loaded properly (check for a collection name in AIPs) + # Verify backend started successfully. + # 1. Make sure root endpoint is responding (check for dspace.name defined in docker-compose.yml) + # 2. Also check /collections endpoint to ensure the test data loaded properly (check for a collection name in AIPs) - name: Verify backend is responding properly run: | result=$(wget -O- -q http://127.0.0.1:8080/server/api) @@ -204,7 +224,7 @@ jobs: result=$(wget -O- -q http://127.0.0.1:8000/) echo "$result" echo "$result" | grep -oE "Handle Proxy" - # Shutdown our containers + # Shutdown our containers - name: Shutdown Docker containers run: | docker compose -f docker-compose.yml down diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index 12aa0cfe2864..83dfd74b9a1a 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -113,6 +113,12 @@ jobs: - name: Set up QEMU emulation to build for multiple architectures uses: docker/setup-qemu-action@v3 + #------------------------------------------------------------ + # Build & deploy steps for new commits to a branch (non-PRs) + # + # These steps build the images, push to DockerHub, and + # (if necessary) redeploy demo/sandbox sites. + #------------------------------------------------------------ # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push @@ -125,6 +131,7 @@ jobs: # https://github.com/docker/metadata-action # Get Metadata for docker_build_deps step below - name: Sync metadata (tags, labels) from GitHub to Docker for image + if: ${{ ! matrix.isPr }} id: meta_build uses: docker/metadata-action@v5 with: @@ -133,7 +140,9 @@ jobs: flavor: ${{ env.TAGS_FLAVOR }} # https://github.com/docker/build-push-action - - name: Build and push image + - name: Build and push image to DockerHub + # Only build & push if not a PR + if: ${{ ! matrix.isPr }} id: docker_build uses: docker/build-push-action@v5 with: @@ -142,9 +151,7 @@ jobs: context: ${{ inputs.dockerfile_context }} file: ${{ inputs.dockerfile_path }} platforms: ${{ matrix.arch }} - # For pull requests, we run the Docker build (to ensure no PR changes break the build), - # but we ONLY do an image push to DockerHub if it's NOT a PR - push: ${{ ! matrix.isPr }} + push: true # Use tags / labels provided by 'docker/metadata-action' above tags: ${{ steps.meta_build.outputs.tags }} labels: ${{ steps.meta_build.outputs.labels }} @@ -189,11 +196,54 @@ jobs: run: | curl -X POST $REDEPLOY_DEMO_URL + #------------------------------------------------------------- + # Build steps for PRs only + # + # These steps build the images and store as a build artifact. + # These artifacts can then be used by later jobs to run the + # brand-new images for automated testing. + #-------------------------------------------------------------- + # Get Metadata for docker_build_deps step below + - name: Create metadata (tags, labels) for local Docker image + if: matrix.isPr + id: meta_build_pr + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + # Hardcode to use custom "pr-testing" tag because that will allow us to spin up this PR + # for testing in docker.yml + tags: pr-testing + flavor: ${{ env.TAGS_FLAVOR }} + # Build local image and stores in a TAR file in /tmp directory + - name: Build and push image to local image + if: matrix.isPr + uses: docker/build-push-action@v5 + with: + build-contexts: | + ${{ inputs.dockerfile_additional_contexts }} + context: ${{ inputs.dockerfile_context }} + file: ${{ inputs.dockerfile_path }} + platforms: ${{ matrix.arch }} + tags: ${{ steps.meta_build_pr.outputs.tags }} + labels: ${{ steps.meta_build_pr.outputs.labels }} + # Export image to a local TAR file + outputs: type=docker,dest=/tmp/${{ inputs.build_id }}.tar + # Upload the local docker image (in TAR file) to a build Artifact + - name: Upload local image to artifact + if: matrix.isPr + uses: actions/upload-artifact@v4 + with: + name: docker-image-${{ inputs.build_id }} + path: /tmp/${{ inputs.build_id }}.tar + if-no-files-found: error + retention-days: 1 + # Merge Docker digests (from various architectures) into a manifest. # This runs after all Docker builds complete above, and it tells hub.docker.com # that these builds should be all included in the manifest for this tag. # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) docker-build_manifest: + # Only run if this is NOT a PR if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-latest needs: From 9853aa5bb45ceef6ba6e01a08515f0cdea68f92c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 11 Nov 2024 16:45:59 -0600 Subject: [PATCH 144/632] Fix error in running Handle Server in GitHub Actions. Must exclude "spring-jcl" from dependencies as it conflicts with "commons-logging" (used by more of our dependencies) --- dspace-api/pom.xml | 7 +++++++ dspace-iiif/pom.xml | 5 +++++ dspace-oai/pom.xml | 5 +++++ dspace-rdf/pom.xml | 5 +++++ dspace-server-webapp/pom.xml | 5 +++++ dspace-services/pom.xml | 7 +++++++ dspace-sword/pom.xml | 5 +++++ dspace-swordv2/pom.xml | 5 +++++ pom.xml | 7 +++++++ 9 files changed, 51 insertions(+) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index bdf035179bee..c3ef2c86044d 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -396,6 +396,13 @@ org.springframework spring-orm + + + + org.springframework + spring-jcl + + diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index 64dd5106f0af..49ee02b56500 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -38,6 +38,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 28b610e996c1..bfa2c8a27381 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -80,6 +80,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index e656a920a1e6..075f2d7038e8 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -67,6 +67,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 5a4e1b32123d..35fa473fc170 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -405,6 +405,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 51c6dea62413..7c85ff7f0f0f 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -85,6 +85,13 @@ spring-context-support ${spring.version} compile + + + + org.springframework + spring-jcl + + org.apache.commons diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index 1403c779e720..01aa68dfbfe6 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -60,6 +60,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 470388883126..f575898c122a 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -80,6 +80,11 @@ org.springframework.boot spring-boot-starter-logging + + + org.springframework + spring-jcl + diff --git a/pom.xml b/pom.xml index 02579c03294a..b0d9d1819d3f 100644 --- a/pom.xml +++ b/pom.xml @@ -1171,6 +1171,13 @@ org.springframework spring-orm ${spring.version} + + + + org.springframework + spring-jcl + + org.swordapp From faca14ad4059de0cb66c6d6ca0baf4161ac3aadd Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 13 Nov 2024 09:17:30 -0600 Subject: [PATCH 145/632] Ensure "host" command is installed in images, so "bin/make-handle-config" will work. --- Dockerfile | 5 +++++ Dockerfile.test | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Dockerfile b/Dockerfile index 9d89710fe11c..ffce09239d1b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -55,6 +55,11 @@ FROM tomcat:9-jdk${JDK_VERSION} ENV DSPACE_INSTALL=/dspace # Copy the /dspace directory from 'ant_build' container to /dspace in this container COPY --from=ant_build /dspace $DSPACE_INSTALL +# Need host command for "[dspace]/bin/make-handle-config" +RUN apt-get update \ + && apt-get install -y --no-install-recommends host \ + && apt-get purge -y --auto-remove \ + && rm -rf /var/lib/apt/lists/* # Expose Tomcat port and AJP port EXPOSE 8080 8009 # Give java extra memory (2GB) diff --git a/Dockerfile.test b/Dockerfile.test index 031394ad256c..d88699ca52ab 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -54,6 +54,11 @@ ENV DSPACE_INSTALL=/dspace ENV TOMCAT_INSTALL=/usr/local/tomcat # Copy the /dspace directory from 'ant_build' containger to /dspace in this container COPY --from=ant_build /dspace $DSPACE_INSTALL +# Need host command for "[dspace]/bin/make-handle-config" +RUN apt-get update \ + && apt-get install -y --no-install-recommends host \ + && apt-get purge -y --auto-remove \ + && rm -rf /var/lib/apt/lists/* # Enable the AJP connector in Tomcat's server.xml # NOTE: secretRequired="false" should only be used when AJP is NOT accessible from an external network. But, secretRequired="true" isn't supported by mod_proxy_ajp until Apache 2.5 RUN sed -i '/Service name="Catalina".*/a \\n ' $TOMCAT_INSTALL/conf/server.xml From a0ed4a40eabab6296a577b3d7c8aa5a5fe024888 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 13 Nov 2024 10:37:53 -0600 Subject: [PATCH 146/632] Bug fixes. Ensure all steps of docker-deploy use the same environment variables. Ensure Handle Server HTTP port is open --- .github/workflows/docker.yml | 13 +++++++------ Dockerfile | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index eed8de5a8722..5197ed3bfe39 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -158,6 +158,12 @@ jobs: runs-on: ubuntu-latest # Must run after all major images are built needs: [dspace, dspace-test, dspace-cli, dspace-postgres-pgcrypto, dspace-solr] + env: + # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 + dspace__P__server__P__url: http://127.0.0.1:8080/server + # Force using "pr-testing" version of all Docker images. The "pr-testing" tag is a temporary tag that we + # assign to all PR-built docker images in reusabe-docker-build.yml + DSPACE_VER: pr-testing steps: # Checkout our codebase (to get access to Docker Compose scripts) - name: Checkout codebase @@ -180,12 +186,6 @@ jobs: docker image ls -a # Start backend using our compose script in the codebase. - name: Start backend in Docker - env: - # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 - dspace__P__server__P__url: http://127.0.0.1:8080/server - # Force using "pr-testing" version of Docker images. The "pr-testing" tag is a temporary tag that we assign to - # all PR-built docker images in reusabe-docker-build.yml - DSPACE_VER: pr-testing run: | docker compose -f docker-compose.yml up -d sleep 10 @@ -214,6 +214,7 @@ jobs: - name: Verify Handle Server is working properly run: | docker exec -i dspace /dspace/bin/make-handle-config + echo "Starting Handle Server..." docker exec -i dspace /dspace/bin/start-handle-server sleep 20 echo "Checking for errors in handle-server.log..." diff --git a/Dockerfile b/Dockerfile index ffce09239d1b..adc5d6125f0a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -60,8 +60,8 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends host \ && apt-get purge -y --auto-remove \ && rm -rf /var/lib/apt/lists/* -# Expose Tomcat port and AJP port -EXPOSE 8080 8009 +# Expose Tomcat port (8080) and AJP port (8009) and Handle Server HTTP port (8000) +EXPOSE 8080 8009 8000 # Give java extra memory (2GB) ENV JAVA_OPTS=-Xmx2000m From d6d78298b31252155db7d00d7ae8eee8f2c0ac93 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 13 Nov 2024 11:45:03 -0600 Subject: [PATCH 147/632] Add check for Handle Server error.log --- .github/workflows/docker.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5197ed3bfe39..1e839e89fceb 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -217,6 +217,10 @@ jobs: echo "Starting Handle Server..." docker exec -i dspace /dspace/bin/start-handle-server sleep 20 + echo "Checking for errors in error.log" + result=$(docker exec -i dspace sh -c "cat /dspace/handle-server/logs/error.log* || echo ''") + echo "$result" + echo "$result" | grep -vqz "Exception" echo "Checking for errors in handle-server.log..." result=$(docker exec -i dspace cat /dspace/log/handle-server.log) echo "$result" From 5bb65c6b5647f74161244868c0864e9adb12d12a Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 13 Nov 2024 14:27:28 -0600 Subject: [PATCH 148/632] Fix error in Handle Server startup caused by having multiple versions of BouncyCastle in our classpath. Exclude the old version brought in by cnri-servlet-container --- dspace-api/pom.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index c3ef2c86044d..c42895ab4c49 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -427,6 +427,16 @@ org.bouncycastle bcprov-jdk15on + + + org.bouncycastle + bcpkix-jdk15on + + + org.bouncycastle + bcprov-jdk15on + From aa71e4840be6fa9c6368e061d3e169e08a89c66a Mon Sep 17 00:00:00 2001 From: Agustina Martinez Date: Mon, 5 Aug 2024 11:06:06 +0200 Subject: [PATCH 149/632] Fix 9734: Check configured workflow.reviewer.file-edit to show item edit functionality in workflow UI (cherry picked from commit e8ec0c1b1d20dd5e812f38593a24718fff1d8c6e) --- .../processingaction/ScoreReviewAction.java | 15 ++++++++++++++- .../processingaction/SingleUserReviewAction.java | 8 ++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java index 43a3decacc7e..419bb1236402 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java @@ -8,6 +8,7 @@ package org.dspace.xmlworkflow.state.actions.processingaction; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -20,6 +21,8 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.MetadataFieldName; import org.dspace.core.Context; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.xmlworkflow.service.WorkflowRequirementsService; import org.dspace.xmlworkflow.state.Step; import org.dspace.xmlworkflow.state.actions.ActionAdvancedInfo; @@ -34,6 +37,9 @@ public class ScoreReviewAction extends ProcessingAction { private static final Logger log = LogManager.getLogger(ScoreReviewAction.class); + private final ConfigurationService configurationService + = DSpaceServicesFactory.getInstance().getConfigurationService(); + // Option(s) public static final String SUBMIT_SCORE = "submit_score"; @@ -114,7 +120,14 @@ private boolean checkRequestValid(int score, String review) { @Override public List getOptions() { - return List.of(SUBMIT_SCORE, RETURN_TO_POOL); + List options = new ArrayList<>(); + options.add(SUBMIT_SCORE); + if (configurationService.getBooleanProperty("workflow.reviewer.file-edit", false)) { + options.add(SUBMIT_EDIT_METADATA); + } + options.add(RETURN_TO_POOL); + + return options; } @Override diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java index b3fe896ace24..0b8f2d13648c 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java @@ -21,6 +21,8 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.core.Context; import org.dspace.eperson.EPerson; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.workflow.WorkflowException; import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory; import org.dspace.xmlworkflow.state.Step; @@ -40,6 +42,9 @@ public class SingleUserReviewAction extends ProcessingAction { private static final Logger log = LogManager.getLogger(SingleUserReviewAction.class); + private final ConfigurationService configurationService + = DSpaceServicesFactory.getInstance().getConfigurationService(); + public static final int OUTCOME_REJECT = 1; protected static final String SUBMIT_DECLINE_TASK = "submit_decline_task"; @@ -95,6 +100,9 @@ public ActionResult processAccept(Context c, XmlWorkflowItem wfi) throws SQLExce public List getOptions() { List options = new ArrayList<>(); options.add(SUBMIT_APPROVE); + if (configurationService.getBooleanProperty("workflow.reviewer.file-edit", false)) { + options.add(SUBMIT_EDIT_METADATA); + } options.add(SUBMIT_REJECT); options.add(SUBMIT_DECLINE_TASK); return options; From 60004c32ab1d73a1d0e85d9b68973c1daf31d5b9 Mon Sep 17 00:00:00 2001 From: Agustina Martinez Date: Mon, 5 Aug 2024 11:06:06 +0200 Subject: [PATCH 150/632] Fix 9734: Check configured workflow.reviewer.file-edit to show item edit functionality in workflow UI (cherry picked from commit e8ec0c1b1d20dd5e812f38593a24718fff1d8c6e) --- .../processingaction/ScoreReviewAction.java | 15 ++++++++++++++- .../processingaction/SingleUserReviewAction.java | 8 ++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java index a8ed4fd3dae9..50f338499282 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java @@ -8,6 +8,7 @@ package org.dspace.xmlworkflow.state.actions.processingaction; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -20,6 +21,8 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.MetadataFieldName; import org.dspace.core.Context; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.xmlworkflow.service.WorkflowRequirementsService; import org.dspace.xmlworkflow.state.Step; import org.dspace.xmlworkflow.state.actions.ActionAdvancedInfo; @@ -34,6 +37,9 @@ public class ScoreReviewAction extends ProcessingAction { private static final Logger log = LogManager.getLogger(ScoreReviewAction.class); + private final ConfigurationService configurationService + = DSpaceServicesFactory.getInstance().getConfigurationService(); + // Option(s) public static final String SUBMIT_SCORE = "submit_score"; @@ -114,7 +120,14 @@ private boolean checkRequestValid(int score, String review) { @Override public List getOptions() { - return List.of(SUBMIT_SCORE, RETURN_TO_POOL); + List options = new ArrayList<>(); + options.add(SUBMIT_SCORE); + if (configurationService.getBooleanProperty("workflow.reviewer.file-edit", false)) { + options.add(SUBMIT_EDIT_METADATA); + } + options.add(RETURN_TO_POOL); + + return options; } @Override diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java index 64e0957b65b7..c46fa851e4f1 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java @@ -21,6 +21,8 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.core.Context; import org.dspace.eperson.EPerson; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.workflow.WorkflowException; import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory; import org.dspace.xmlworkflow.state.Step; @@ -40,6 +42,9 @@ public class SingleUserReviewAction extends ProcessingAction { private static final Logger log = LogManager.getLogger(SingleUserReviewAction.class); + private final ConfigurationService configurationService + = DSpaceServicesFactory.getInstance().getConfigurationService(); + public static final int OUTCOME_REJECT = 1; protected static final String SUBMIT_DECLINE_TASK = "submit_decline_task"; @@ -95,6 +100,9 @@ public ActionResult processAccept(Context c, XmlWorkflowItem wfi) throws SQLExce public List getOptions() { List options = new ArrayList<>(); options.add(SUBMIT_APPROVE); + if (configurationService.getBooleanProperty("workflow.reviewer.file-edit", false)) { + options.add(SUBMIT_EDIT_METADATA); + } options.add(SUBMIT_REJECT); options.add(SUBMIT_DECLINE_TASK); return options; From b76d152444f464e26ec6c99b86d59c7e46a540e2 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 14 Nov 2024 14:46:31 -0600 Subject: [PATCH 151/632] Remove unnecessary dependencyManagement section from dspace-api. No longer needed for dependency convergence --- dspace-api/pom.xml | 73 ++-------------------------------------------- 1 file changed, 2 insertions(+), 71 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index acac810d6cda..c953abf0702b 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -793,11 +793,13 @@ org.apache.velocity velocity-engine-core + 2.3 org.xmlunit xmlunit-core + 2.10.0 test @@ -873,75 +875,4 @@ - - - - - - - io.netty - netty-buffer - 4.1.106.Final - - - io.netty - netty-transport - 4.1.106.Final - - - io.netty - netty-transport-native-unix-common - 4.1.106.Final - - - io.netty - netty-common - 4.1.106.Final - - - io.netty - netty-handler - 4.1.106.Final - - - io.netty - netty-codec - 4.1.106.Final - - - org.apache.velocity - velocity-engine-core - 2.3 - - - org.xmlunit - xmlunit-core - 2.10.0 - test - - - com.github.java-json-tools - json-schema-validator - 2.2.14 - - - jakarta.validation - jakarta.validation-api - 3.0.2 - - - io.swagger - swagger-core - 1.6.2 - - - org.scala-lang - scala-library - 2.13.11 - test - - - - From b4f19158b072edcd70ac25163562619ecec7856e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 14 Nov 2024 14:58:49 -0600 Subject: [PATCH 152/632] Fix multiple declarations of maven-dependency-plugin. Combine two tasks into one declaration --- dspace/modules/server/pom.xml | 36 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index ca4eea26a07c..c1ce045fe896 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -27,7 +27,7 @@ maven-dependency-plugin - unpack + unpack-additions prepare-package unpack-dependencies @@ -42,6 +42,20 @@ META-INF/** + + unpack-server + prepare-package + + unpack-dependencies + + + runtime + org.dspace + dspace-server-webapp + **/static/**,**/*.properties + ${project.build.directory}/additions + + @@ -68,26 +82,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - prepare-package - - unpack-dependencies - - - runtime - org.dspace - dspace-server-webapp - **/static/**,**/*.properties - ${project.build.directory}/additions - - - - diff --git a/pom.xml b/pom.xml index 5be05ca44e36..63985484215c 100644 --- a/pom.xml +++ b/pom.xml @@ -1746,36 +1746,6 @@ google-api-services-analytics v3-rev145-1.23.0 - - com.google.api-client - google-api-client - 1.23.0 - - - com.google.http-client - google-http-client - 1.23.0 - - - com.google.http-client - google-http-client-jackson2 - 1.23.0 - - - jackson-core - com.fasterxml.jackson.core - - - jackson-databind - com.fasterxml.jackson.core - - - - - com.google.oauth-client - google-oauth-client - 1.33.3 - From f0c92ac96b6f6f22445020b9e9690886bb83830c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 16:06:10 -0600 Subject: [PATCH 157/632] Ensure only main branch uses "latest". Other branches should use the tag corresponding to the branch name (cherry picked from commit e0b7241acb167496ebc8c80c73ae69b9f6611a1c) --- .github/workflows/docker.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a0aee14bea38..143b69a2f9fe 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -161,10 +161,10 @@ jobs: env: # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 dspace__P__server__P__url: http://127.0.0.1:8080/server - # If this is a PR, force using "pr-testing" version of all Docker images. Otherwise, for branch commits, use the - # "latest" tag. NOTE: the "pr-testing" tag is a temporary tag that we assign to all PR-built docker images in - # reusabe-docker-build.yml - DSPACE_VER: ${{ github.event_name == 'pull_request' && 'pr-testing' || 'latest' }} + # If this is a PR, force using "pr-testing" version of all Docker images. Otherwise, if on main branch, use the + # "latest" tag. Otherwise, use the branch name. NOTE: the "pr-testing" tag is a temporary tag that we assign to + # all PR-built docker images in reusabe-docker-build.yml + DSPACE_VER: ${{ (github.event_name == 'pull_request' && 'pr-testing') || (github.ref_name == github.event.repository.default_branch && 'latest') || github.ref_name }} steps: # Checkout our codebase (to get access to Docker Compose scripts) - name: Checkout codebase From 8c9cdc6c9c0c03df1d4a9342552fe42553cba639 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 16:06:10 -0600 Subject: [PATCH 158/632] Ensure only main branch uses "latest". Other branches should use the tag corresponding to the branch name (cherry picked from commit e0b7241acb167496ebc8c80c73ae69b9f6611a1c) --- .github/workflows/docker.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a0aee14bea38..143b69a2f9fe 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -161,10 +161,10 @@ jobs: env: # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 dspace__P__server__P__url: http://127.0.0.1:8080/server - # If this is a PR, force using "pr-testing" version of all Docker images. Otherwise, for branch commits, use the - # "latest" tag. NOTE: the "pr-testing" tag is a temporary tag that we assign to all PR-built docker images in - # reusabe-docker-build.yml - DSPACE_VER: ${{ github.event_name == 'pull_request' && 'pr-testing' || 'latest' }} + # If this is a PR, force using "pr-testing" version of all Docker images. Otherwise, if on main branch, use the + # "latest" tag. Otherwise, use the branch name. NOTE: the "pr-testing" tag is a temporary tag that we assign to + # all PR-built docker images in reusabe-docker-build.yml + DSPACE_VER: ${{ (github.event_name == 'pull_request' && 'pr-testing') || (github.ref_name == github.event.repository.default_branch && 'latest') || github.ref_name }} steps: # Checkout our codebase (to get access to Docker Compose scripts) - name: Checkout codebase From 56029149c1b7a366ea73269c1f55760b5251cd0e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 11:30:14 -0600 Subject: [PATCH 159/632] Remove parboiled-java and minor cleanup of unused OAI dependencies --- dspace-oai/pom.xml | 23 +------------------ .../xoai/app/CCElementItemCompilePlugin.java | 2 +- .../main/java/org/dspace/xoai/app/XOAI.java | 2 +- .../tests/integration/xoai/PipelineTest.java | 9 ++++---- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 29644392d540..35f12b02a5ce 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -99,22 +99,9 @@ org.springframework.boot spring-boot-starter-web - - - org.parboiled - parboiled-java - - - - org.parboiled - parboiled-java - 1.3.1 - - org.dspace @@ -137,15 +124,7 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - - - org.apache.logging.log4j - log4j-slf4j-impl - runtime - + org.apache.logging.log4j log4j-1.2-api diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/CCElementItemCompilePlugin.java b/dspace-oai/src/main/java/org/dspace/xoai/app/CCElementItemCompilePlugin.java index 225d56a4c982..370543029d8b 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/CCElementItemCompilePlugin.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/CCElementItemCompilePlugin.java @@ -11,7 +11,7 @@ import com.lyncode.xoai.dataprovider.xml.xoai.Element; import com.lyncode.xoai.dataprovider.xml.xoai.Metadata; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.license.factory.LicenseServiceFactory; diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java index 25cc1ee3655f..ad138ca9f2ad 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java @@ -9,7 +9,7 @@ import static com.lyncode.xoai.dataprovider.core.Granularity.Second; import static java.util.Objects.nonNull; -import static org.apache.commons.lang.StringUtils.EMPTY; +import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.apache.solr.common.params.CursorMarkParams.CURSOR_MARK_PARAM; import static org.apache.solr.common.params.CursorMarkParams.CURSOR_MARK_START; import static org.dspace.xoai.util.ItemUtils.retrieveMetadata; diff --git a/dspace-oai/src/test/java/org/dspace/xoai/tests/integration/xoai/PipelineTest.java b/dspace-oai/src/test/java/org/dspace/xoai/tests/integration/xoai/PipelineTest.java index 0f48824159c2..0f7ffde0bd00 100644 --- a/dspace-oai/src/test/java/org/dspace/xoai/tests/integration/xoai/PipelineTest.java +++ b/dspace-oai/src/test/java/org/dspace/xoai/tests/integration/xoai/PipelineTest.java @@ -13,13 +13,14 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.io.InputStream; +import java.nio.charset.Charset; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; import com.lyncode.xoai.util.XSLPipeline; +import org.apache.commons.io.IOUtils; import org.dspace.xoai.tests.support.XmlMatcherBuilder; import org.junit.Test; -import org.parboiled.common.FileUtils; public class PipelineTest { private static TransformerFactory factory = TransformerFactory.newInstance(); @@ -28,9 +29,9 @@ public class PipelineTest { public void pipelineTest() throws Exception { InputStream input = PipelineTest.class.getClassLoader().getResourceAsStream("item.xml"); InputStream xslt = PipelineTest.class.getClassLoader().getResourceAsStream("oai_dc.xsl"); - String output = FileUtils.readAllText(new XSLPipeline(input, true) - .apply(factory.newTemplates(new StreamSource(xslt))) - .getTransformed()); + String output = IOUtils.toString(new XSLPipeline(input, true) + .apply(factory.newTemplates(new StreamSource(xslt))) + .getTransformed(), Charset.defaultCharset()); assertThat(output, oai_dc().withXPath("/oai_dc:dc/dc:title", equalTo("Teste"))); From e53905131049c3a231274ab4cb6732e168609353 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 11:31:28 -0600 Subject: [PATCH 160/632] Fix OAI using incorrect Java Injection API. --- dspace-api/pom.xml | 1 - dspace-oai/pom.xml | 5 ++--- pom.xml | 6 ++++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index acac810d6cda..845692686f30 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -719,7 +719,6 @@ jakarta.inject jakarta.inject-api - 2.0.1 diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 35f12b02a5ce..72c243f55c21 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -65,9 +65,8 @@ - javax.inject - javax.inject - 1 + jakarta.inject + jakarta.inject-api diff --git a/pom.xml b/pom.xml index 5be05ca44e36..7bad6fbc2b9d 100644 --- a/pom.xml +++ b/pom.xml @@ -1553,6 +1553,12 @@ jakarta.activation-api 2.1.3 + + + jakarta.inject + jakarta.inject-api + 2.0.1 + jakarta.mail From f248b6395d12e55d4cc68ee1fb4db7b934fe8b42 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 12:02:20 -0600 Subject: [PATCH 161/632] Log4j cleanup. Remove last traces of log4j v1 (and remove log4j1 bridge to avoid them coming back). Create log4j2 settings for Handle Plugin. --- .../app/bulkedit/MetadataExportSearchIT.java | 5 +- .../dspace/builder/OrcidHistoryBuilder.java | 5 +- dspace-oai/pom.xml | 5 -- .../xoai/filter/ItemsWithBitstreamFilter.java | 4 +- dspace-rdf/pom.xml | 4 -- .../rest/converter/SearchEventConverter.java | 5 +- .../bitstream/BitstreamLinksetProcessor.java | 5 +- .../BitstreamParentItemProcessor.java | 5 +- .../bitstream/BitstreamTypeProcessor.java | 5 +- .../processor/item/ItemAuthorProcessor.java | 5 +- .../item/ItemContentBitstreamsProcessor.java | 5 +- .../item/ItemDescribedbyProcessor.java | 5 +- .../processor/item/ItemLicenseProcessor.java | 5 +- .../processor/item/ItemLinksetProcessor.java | 5 +- .../processor/item/ItemTypeProcessor.java | 5 +- .../service/impl/LinksetServiceImpl.java | 5 +- dspace-sword/pom.xml | 4 -- dspace-swordv2/pom.xml | 4 -- dspace/bin/start-handle-server | 2 +- dspace/bin/start-handle-server.bat | 2 +- dspace/config/log4j-handle-plugin.properties | 34 ------------- dspace/config/log4j2-handle-plugin.xml | 48 +++++++++++++++++++ pom.xml | 25 ---------- 23 files changed, 91 insertions(+), 106 deletions(-) delete mode 100644 dspace/config/log4j-handle-plugin.properties create mode 100644 dspace/config/log4j2-handle-plugin.xml diff --git a/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataExportSearchIT.java b/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataExportSearchIT.java index 3a972692efeb..63a87a48f554 100644 --- a/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataExportSearchIT.java +++ b/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataExportSearchIT.java @@ -23,7 +23,8 @@ import com.google.common.io.Files; import com.opencsv.CSVReader; import com.opencsv.exceptions.CsvException; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; @@ -51,7 +52,7 @@ public class MetadataExportSearchIT extends AbstractIntegrationTestWithDatabase private Item[] itemsSubject2 = new Item[numberItemsSubject2]; private String filename; private Collection collection; - private Logger logger = Logger.getLogger(MetadataExportSearchIT.class); + private Logger logger = LogManager.getLogger(MetadataExportSearchIT.class); private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); private SearchService searchService; diff --git a/dspace-api/src/test/java/org/dspace/builder/OrcidHistoryBuilder.java b/dspace-api/src/test/java/org/dspace/builder/OrcidHistoryBuilder.java index 199f412f8506..d811d03f5358 100644 --- a/dspace-api/src/test/java/org/dspace/builder/OrcidHistoryBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/OrcidHistoryBuilder.java @@ -11,7 +11,8 @@ import java.sql.SQLException; import java.util.Date; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.orcid.OrcidHistory; @@ -24,7 +25,7 @@ */ public class OrcidHistoryBuilder extends AbstractBuilder { - private static final Logger log = Logger.getLogger(OrcidHistoryBuilder.class); + private static final Logger log = LogManager.getLogger(OrcidHistoryBuilder.class); private OrcidHistory orcidHistory; diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 72c243f55c21..f6b220baed3d 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -123,11 +123,6 @@ org.apache.logging.log4j log4j-core - - - org.apache.logging.log4j - log4j-1.2-api - diff --git a/dspace-oai/src/main/java/org/dspace/xoai/filter/ItemsWithBitstreamFilter.java b/dspace-oai/src/main/java/org/dspace/xoai/filter/ItemsWithBitstreamFilter.java index 3599c5b9e168..9bf1c65dc9d9 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/filter/ItemsWithBitstreamFilter.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/filter/ItemsWithBitstreamFilter.java @@ -9,8 +9,8 @@ import java.sql.SQLException; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.content.Bundle; import org.dspace.content.Item; import org.dspace.handle.factory.HandleServiceFactory; diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index 3d11794d86a2..3b3cb17119a1 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -89,10 +89,6 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - org.apache.commons diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java index e9786962e0f5..d781d255df11 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java @@ -13,7 +13,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.model.PageRest; import org.dspace.app.rest.model.SearchEventRest; import org.dspace.app.rest.model.SearchResultsRest; @@ -31,7 +32,7 @@ @Component public class SearchEventConverter { /* Log4j logger */ - private static final Logger log = Logger.getLogger(SearchEventConverter.class); + private static final Logger log = LogManager.getLogger(SearchEventConverter.class); @Autowired private ScopeResolver scopeResolver; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamLinksetProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamLinksetProcessor.java index 97eb9f2a546d..349dde7b6dac 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamLinksetProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamLinksetProcessor.java @@ -10,7 +10,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Bitstream; @@ -25,7 +26,7 @@ */ public class BitstreamLinksetProcessor extends BitstreamSignpostingProcessor { - private static final Logger log = Logger.getLogger(BitstreamLinksetProcessor.class); + private static final Logger log = LogManager.getLogger(BitstreamLinksetProcessor.class); private final BitstreamService bitstreamService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamParentItemProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamParentItemProcessor.java index 32928dfa8892..c855f06784f7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamParentItemProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamParentItemProcessor.java @@ -10,7 +10,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Bitstream; @@ -28,7 +29,7 @@ */ public class BitstreamParentItemProcessor extends BitstreamSignpostingProcessor { - private static final Logger log = Logger.getLogger(BitstreamParentItemProcessor.class); + private static final Logger log = LogManager.getLogger(BitstreamParentItemProcessor.class); private final BitstreamService bitstreamService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamTypeProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamTypeProcessor.java index 8889a415d327..d0f170b4c55a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamTypeProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamTypeProcessor.java @@ -11,7 +11,8 @@ import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Bitstream; @@ -28,7 +29,7 @@ */ public class BitstreamTypeProcessor extends BitstreamSignpostingProcessor { - private static final Logger log = Logger.getLogger(BitstreamTypeProcessor.class); + private static final Logger log = LogManager.getLogger(BitstreamTypeProcessor.class); @Autowired private SimpleMapConverter mapConverterDSpaceToSchemaOrgUri; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemAuthorProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemAuthorProcessor.java index f3a9e35198a7..ebc7c46f4d23 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemAuthorProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemAuthorProcessor.java @@ -16,7 +16,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -37,7 +38,7 @@ public class ItemAuthorProcessor extends ItemSignpostingProcessor { /** * log4j category */ - private static final Logger log = Logger.getLogger(ItemAuthorProcessor.class); + private static final Logger log = LogManager.getLogger(ItemAuthorProcessor.class); private final ItemService itemService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemContentBitstreamsProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemContentBitstreamsProcessor.java index 0b91e57f7b3f..65a29c2b6c98 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemContentBitstreamsProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemContentBitstreamsProcessor.java @@ -11,7 +11,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Bitstream; @@ -33,7 +34,7 @@ public class ItemContentBitstreamsProcessor extends ItemSignpostingProcessor { /** * log4j category */ - private static final Logger log = Logger.getLogger(ItemContentBitstreamsProcessor.class); + private static final Logger log = LogManager.getLogger(ItemContentBitstreamsProcessor.class); public ItemContentBitstreamsProcessor(FrontendUrlService frontendUrlService) { super(frontendUrlService); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemDescribedbyProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemDescribedbyProcessor.java index 20091e6d0992..a86b98f2e5d0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemDescribedbyProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemDescribedbyProcessor.java @@ -10,7 +10,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -23,7 +24,7 @@ */ public class ItemDescribedbyProcessor extends ItemSignpostingProcessor { - private static final Logger log = Logger.getLogger(ItemDescribedbyProcessor.class); + private static final Logger log = LogManager.getLogger(ItemDescribedbyProcessor.class); private final ConfigurationService configurationService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLicenseProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLicenseProcessor.java index b60ee35d7fe4..6e26d8f1b225 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLicenseProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLicenseProcessor.java @@ -11,7 +11,8 @@ import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -25,7 +26,7 @@ */ public class ItemLicenseProcessor extends ItemSignpostingProcessor { - private static final Logger log = Logger.getLogger(ItemLicenseProcessor.class); + private static final Logger log = LogManager.getLogger(ItemLicenseProcessor.class); private final CreativeCommonsService creativeCommonsService = LicenseServiceFactory.getInstance().getCreativeCommonsService(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLinksetProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLinksetProcessor.java index 2d09e5616171..4e48caf9594f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLinksetProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLinksetProcessor.java @@ -10,7 +10,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -23,7 +24,7 @@ */ public class ItemLinksetProcessor extends ItemSignpostingProcessor { - private static final Logger log = Logger.getLogger(ItemLinksetProcessor.class); + private static final Logger log = LogManager.getLogger(ItemLinksetProcessor.class); private final ConfigurationService configurationService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemTypeProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemTypeProcessor.java index 49b3612cd92c..f2533a5a9564 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemTypeProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemTypeProcessor.java @@ -11,7 +11,8 @@ import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -27,7 +28,7 @@ */ public class ItemTypeProcessor extends ItemSignpostingProcessor { - private static final Logger log = Logger.getLogger(ItemTypeProcessor.class); + private static final Logger log = LogManager.getLogger(ItemTypeProcessor.class); private static final String ABOUT_PAGE_URI = "https://schema.org/AboutPage"; @Autowired diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/impl/LinksetServiceImpl.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/impl/LinksetServiceImpl.java index 5b28817c9438..42b1c8184957 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/impl/LinksetServiceImpl.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/impl/LinksetServiceImpl.java @@ -13,7 +13,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.security.BitstreamMetadataReadPermissionEvaluatorPlugin; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.processor.bitstream.BitstreamSignpostingProcessor; @@ -37,7 +38,7 @@ @Service public class LinksetServiceImpl implements LinksetService { - private static final Logger log = Logger.getLogger(LinksetServiceImpl.class); + private static final Logger log = LogManager.getLogger(LinksetServiceImpl.class); @Autowired protected ItemService itemService; diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index ac84a674c455..283e61c86afc 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -91,10 +91,6 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - xom diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index f22acf9dc9e0..af516d566036 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -95,10 +95,6 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - diff --git a/dspace/bin/start-handle-server b/dspace/bin/start-handle-server index 6d5c9a4b4406..b2af9cf759b8 100755 --- a/dspace/bin/start-handle-server +++ b/dspace/bin/start-handle-server @@ -36,6 +36,6 @@ rm -f $HANDLEDIR/txns/lock # does not support more than one JVM writing to the same rolling log. nohup java $JAVA_OPTS -classpath `$BINDIR/dspace classpath` \ -Ddspace.log.init.disable=true \ - -Dlog4j.configuration=log4j-handle-plugin.properties \ + -Dlog4j2.configurationFile=log4j2-handle-plugin.xml \ net.handle.server.Main $HANDLEDIR \ > $LOGDIR/handle-server.log 2>&1 & diff --git a/dspace/bin/start-handle-server.bat b/dspace/bin/start-handle-server.bat index caf6ff3eef12..8280e2b442f1 100644 --- a/dspace/bin/start-handle-server.bat +++ b/dspace/bin/start-handle-server.bat @@ -51,7 +51,7 @@ echo. echo NOTE: If you want to run the Handle Server as a backend process, re-execute this script echo using the Windows "start" command. For example, "start /B start-handle-server.bat" echo. -java %JAVA_OPTS% -cp "%DSPACE_CLASSPATH%" -Ddspace.log.init.disable=true -Dlog4j.configuration=log4j-handle-plugin.properties net.handle.server.Main %HANDLEDIR% >> "%LOGDIR%/handle-server.log" +java %JAVA_OPTS% -cp "%DSPACE_CLASSPATH%" -Ddspace.log.init.disable=true -Dlog4j2.configurationFile=log4j2-handle-plugin.xml net.handle.server.Main %HANDLEDIR% >> "%LOGDIR%/handle-server.log" REM Clean up DSPACE_CLASSPATH variable set DSPACE_CLASSPATH= diff --git a/dspace/config/log4j-handle-plugin.properties b/dspace/config/log4j-handle-plugin.properties deleted file mode 100644 index 44d39fb1bdf0..000000000000 --- a/dspace/config/log4j-handle-plugin.properties +++ /dev/null @@ -1,34 +0,0 @@ -########################################################################### -# log4j-handle-plugin.properties -# -# This is the log4j configuration file for the embedded DSpace Handle server, -# writing daily rolling logs. We cannot simply write to the same logs, since -# log4j does not support more than one JVM writing to the same rolling log. -########################################################################### - -# VARIABLES: -# The following variables can be used to easily tweak the default log4j settings. -# These variables are used by the log4j config / appenders later in this file. - -# log.dir -# Default log file directory for DSpace. Defaults to the 'log' subdirectory -# under [dspace.dir]. NOTE: The value of 'dspace.dir' will be replaced by -# its value in your configuration when DSpace is deployed (via Ant). -log.dir=${dspace.dir}/log - -# Set root category priority to INFO and its only appender to A1. -log4j.rootCategory=INFO, A1 - -# A1 is set to be a DailyRollingFileAppender. -log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender -log4j.appender.A1.File=${log.dir}/handle-plugin.log -log4j.appender.A1.DatePattern='.'yyyy-MM-dd - -# A1 uses PatternLayout. -log4j.appender.A1.layout=org.apache.log4j.PatternLayout -log4j.appender.A1.layout.ConversionPattern=%d %-5p %c @ %m%n - - -# block passwords from being exposed in Axis logs. -# (DEBUG exposes passwords in Basic Auth) -log4j.logger.org.apache.axis.handlers.http.HTTPAuthHandler=INFO \ No newline at end of file diff --git a/dspace/config/log4j2-handle-plugin.xml b/dspace/config/log4j2-handle-plugin.xml new file mode 100644 index 000000000000..5f72e05c7303 --- /dev/null +++ b/dspace/config/log4j2-handle-plugin.xml @@ -0,0 +1,48 @@ + + + + + + + ${log4j:configParentLocation}/../log + + + + + + + + + yyyy-MM-dd + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 7bad6fbc2b9d..d84c4d50f28f 100644 --- a/pom.xml +++ b/pom.xml @@ -1600,36 +1600,11 @@ log4j-api ${log4j.version} - - org.apache.logging.log4j - log4j-1.2-api - ${log4j.version} - org.apache.logging.log4j log4j-core ${log4j.version} - - org.apache.logging.log4j - log4j-web - ${log4j.version} - - - org.apache.logging.log4j - log4j-slf4j-impl - ${log4j.version} - - - org.apache.logging.log4j - log4j-jul - ${log4j.version} - - - org.slf4j - jul-to-slf4j - ${slf4j.version} - org.apache.pdfbox From d952fea6a2f6b5dc8a54b4e6ba3deecca2d7a4fe Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 11:30:14 -0600 Subject: [PATCH 162/632] Remove parboiled-java and minor cleanup of unused OAI dependencies --- dspace-oai/pom.xml | 23 +------------------ .../xoai/app/CCElementItemCompilePlugin.java | 2 +- .../main/java/org/dspace/xoai/app/XOAI.java | 2 +- .../tests/integration/xoai/PipelineTest.java | 9 ++++---- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index bfa2c8a27381..2f8dae45b236 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -99,22 +99,9 @@ org.springframework.boot spring-boot-starter-web - - - org.parboiled - parboiled-java - - - - org.parboiled - parboiled-java - 1.3.1 - - org.dspace @@ -137,15 +124,7 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - - - org.apache.logging.log4j - log4j-slf4j-impl - runtime - + org.apache.logging.log4j log4j-1.2-api diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/CCElementItemCompilePlugin.java b/dspace-oai/src/main/java/org/dspace/xoai/app/CCElementItemCompilePlugin.java index 225d56a4c982..370543029d8b 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/CCElementItemCompilePlugin.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/CCElementItemCompilePlugin.java @@ -11,7 +11,7 @@ import com.lyncode.xoai.dataprovider.xml.xoai.Element; import com.lyncode.xoai.dataprovider.xml.xoai.Metadata; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.license.factory.LicenseServiceFactory; diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java index 4f842b8e944c..c6aaaa34b539 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java @@ -9,7 +9,7 @@ import static com.lyncode.xoai.dataprovider.core.Granularity.Second; import static java.util.Objects.nonNull; -import static org.apache.commons.lang.StringUtils.EMPTY; +import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.apache.solr.common.params.CursorMarkParams.CURSOR_MARK_PARAM; import static org.apache.solr.common.params.CursorMarkParams.CURSOR_MARK_START; import static org.dspace.xoai.util.ItemUtils.retrieveMetadata; diff --git a/dspace-oai/src/test/java/org/dspace/xoai/tests/integration/xoai/PipelineTest.java b/dspace-oai/src/test/java/org/dspace/xoai/tests/integration/xoai/PipelineTest.java index 0f48824159c2..0f7ffde0bd00 100644 --- a/dspace-oai/src/test/java/org/dspace/xoai/tests/integration/xoai/PipelineTest.java +++ b/dspace-oai/src/test/java/org/dspace/xoai/tests/integration/xoai/PipelineTest.java @@ -13,13 +13,14 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.io.InputStream; +import java.nio.charset.Charset; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; import com.lyncode.xoai.util.XSLPipeline; +import org.apache.commons.io.IOUtils; import org.dspace.xoai.tests.support.XmlMatcherBuilder; import org.junit.Test; -import org.parboiled.common.FileUtils; public class PipelineTest { private static TransformerFactory factory = TransformerFactory.newInstance(); @@ -28,9 +29,9 @@ public class PipelineTest { public void pipelineTest() throws Exception { InputStream input = PipelineTest.class.getClassLoader().getResourceAsStream("item.xml"); InputStream xslt = PipelineTest.class.getClassLoader().getResourceAsStream("oai_dc.xsl"); - String output = FileUtils.readAllText(new XSLPipeline(input, true) - .apply(factory.newTemplates(new StreamSource(xslt))) - .getTransformed()); + String output = IOUtils.toString(new XSLPipeline(input, true) + .apply(factory.newTemplates(new StreamSource(xslt))) + .getTransformed(), Charset.defaultCharset()); assertThat(output, oai_dc().withXPath("/oai_dc:dc/dc:title", equalTo("Teste"))); From f3d15e5c04227ceb5425e671189ec4eb5ea42656 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 12:02:20 -0600 Subject: [PATCH 163/632] Log4j cleanup. Remove last traces of log4j v1 (and remove log4j1 bridge to avoid them coming back). Create log4j2 settings for Handle Plugin. --- .../app/bulkedit/MetadataExportSearchIT.java | 5 +- .../dspace/builder/OrcidHistoryBuilder.java | 5 +- dspace-oai/pom.xml | 5 -- dspace-rdf/pom.xml | 4 -- dspace-rest/pom.xml | 4 -- .../rest/converter/SearchEventConverter.java | 5 +- .../bitstream/BitstreamLinksetProcessor.java | 5 +- .../BitstreamParentItemProcessor.java | 5 +- .../bitstream/BitstreamTypeProcessor.java | 5 +- .../processor/item/ItemAuthorProcessor.java | 5 +- .../item/ItemContentBitstreamsProcessor.java | 5 +- .../item/ItemDescribedbyProcessor.java | 5 +- .../processor/item/ItemLicenseProcessor.java | 5 +- .../processor/item/ItemLinksetProcessor.java | 5 +- .../processor/item/ItemTypeProcessor.java | 5 +- .../service/impl/LinksetServiceImpl.java | 5 +- dspace-sword/pom.xml | 4 -- dspace-swordv2/pom.xml | 4 -- dspace/bin/start-handle-server | 2 +- dspace/bin/start-handle-server.bat | 2 +- dspace/config/log4j-handle-plugin.properties | 34 ------------- dspace/config/log4j2-handle-plugin.xml | 48 +++++++++++++++++++ pom.xml | 25 ---------- 23 files changed, 89 insertions(+), 108 deletions(-) delete mode 100644 dspace/config/log4j-handle-plugin.properties create mode 100644 dspace/config/log4j2-handle-plugin.xml diff --git a/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataExportSearchIT.java b/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataExportSearchIT.java index 3a972692efeb..63a87a48f554 100644 --- a/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataExportSearchIT.java +++ b/dspace-api/src/test/java/org/dspace/app/bulkedit/MetadataExportSearchIT.java @@ -23,7 +23,8 @@ import com.google.common.io.Files; import com.opencsv.CSVReader; import com.opencsv.exceptions.CsvException; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; @@ -51,7 +52,7 @@ public class MetadataExportSearchIT extends AbstractIntegrationTestWithDatabase private Item[] itemsSubject2 = new Item[numberItemsSubject2]; private String filename; private Collection collection; - private Logger logger = Logger.getLogger(MetadataExportSearchIT.class); + private Logger logger = LogManager.getLogger(MetadataExportSearchIT.class); private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); private SearchService searchService; diff --git a/dspace-api/src/test/java/org/dspace/builder/OrcidHistoryBuilder.java b/dspace-api/src/test/java/org/dspace/builder/OrcidHistoryBuilder.java index 199f412f8506..d811d03f5358 100644 --- a/dspace-api/src/test/java/org/dspace/builder/OrcidHistoryBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/OrcidHistoryBuilder.java @@ -11,7 +11,8 @@ import java.sql.SQLException; import java.util.Date; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.orcid.OrcidHistory; @@ -24,7 +25,7 @@ */ public class OrcidHistoryBuilder extends AbstractBuilder { - private static final Logger log = Logger.getLogger(OrcidHistoryBuilder.class); + private static final Logger log = LogManager.getLogger(OrcidHistoryBuilder.class); private OrcidHistory orcidHistory; diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 2f8dae45b236..f7acdae99292 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -124,11 +124,6 @@ org.apache.logging.log4j log4j-core - - - org.apache.logging.log4j - log4j-1.2-api - diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index 075f2d7038e8..64d88b63c780 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -89,10 +89,6 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - org.apache.commons diff --git a/dspace-rest/pom.xml b/dspace-rest/pom.xml index d1f3b95aafb0..3f4bdaf1d0d8 100644 --- a/dspace-rest/pom.xml +++ b/dspace-rest/pom.xml @@ -185,10 +185,6 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - org.dspace dspace-services diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java index 126d37ba1ace..978ae2ca9230 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java @@ -13,7 +13,8 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.model.PageRest; import org.dspace.app.rest.model.SearchEventRest; import org.dspace.app.rest.model.SearchResultsRest; @@ -31,7 +32,7 @@ @Component public class SearchEventConverter { /* Log4j logger */ - private static final Logger log = Logger.getLogger(SearchEventConverter.class); + private static final Logger log = LogManager.getLogger(SearchEventConverter.class); @Autowired private ScopeResolver scopeResolver; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamLinksetProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamLinksetProcessor.java index c65191cb0749..c9ee193b3536 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamLinksetProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamLinksetProcessor.java @@ -10,7 +10,8 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Bitstream; @@ -25,7 +26,7 @@ */ public class BitstreamLinksetProcessor extends BitstreamSignpostingProcessor { - private static final Logger log = Logger.getLogger(BitstreamLinksetProcessor.class); + private static final Logger log = LogManager.getLogger(BitstreamLinksetProcessor.class); private final BitstreamService bitstreamService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamParentItemProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamParentItemProcessor.java index 815d7817d4cf..beb318a73481 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamParentItemProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamParentItemProcessor.java @@ -10,7 +10,8 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Bitstream; @@ -28,7 +29,7 @@ */ public class BitstreamParentItemProcessor extends BitstreamSignpostingProcessor { - private static final Logger log = Logger.getLogger(BitstreamParentItemProcessor.class); + private static final Logger log = LogManager.getLogger(BitstreamParentItemProcessor.class); private final BitstreamService bitstreamService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamTypeProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamTypeProcessor.java index 005a8009836d..1dabf398da9b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamTypeProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/bitstream/BitstreamTypeProcessor.java @@ -11,7 +11,8 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Bitstream; @@ -28,7 +29,7 @@ */ public class BitstreamTypeProcessor extends BitstreamSignpostingProcessor { - private static final Logger log = Logger.getLogger(BitstreamTypeProcessor.class); + private static final Logger log = LogManager.getLogger(BitstreamTypeProcessor.class); @Autowired private SimpleMapConverter mapConverterDSpaceToSchemaOrgUri; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemAuthorProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemAuthorProcessor.java index 1bb215c46864..b96a41b00b2b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemAuthorProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemAuthorProcessor.java @@ -16,7 +16,8 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -37,7 +38,7 @@ public class ItemAuthorProcessor extends ItemSignpostingProcessor { /** * log4j category */ - private static final Logger log = Logger.getLogger(ItemAuthorProcessor.class); + private static final Logger log = LogManager.getLogger(ItemAuthorProcessor.class); private final ItemService itemService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemContentBitstreamsProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemContentBitstreamsProcessor.java index 61bf371adbdf..40c3d96cf680 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemContentBitstreamsProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemContentBitstreamsProcessor.java @@ -11,7 +11,8 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Bitstream; @@ -33,7 +34,7 @@ public class ItemContentBitstreamsProcessor extends ItemSignpostingProcessor { /** * log4j category */ - private static final Logger log = Logger.getLogger(ItemContentBitstreamsProcessor.class); + private static final Logger log = LogManager.getLogger(ItemContentBitstreamsProcessor.class); public ItemContentBitstreamsProcessor(FrontendUrlService frontendUrlService) { super(frontendUrlService); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemDescribedbyProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemDescribedbyProcessor.java index a16770c4d103..62374d7ee830 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemDescribedbyProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemDescribedbyProcessor.java @@ -10,7 +10,8 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -23,7 +24,7 @@ */ public class ItemDescribedbyProcessor extends ItemSignpostingProcessor { - private static final Logger log = Logger.getLogger(ItemDescribedbyProcessor.class); + private static final Logger log = LogManager.getLogger(ItemDescribedbyProcessor.class); private final ConfigurationService configurationService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLicenseProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLicenseProcessor.java index 1a26fa7695b1..a88e9eba37d2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLicenseProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLicenseProcessor.java @@ -11,7 +11,8 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -25,7 +26,7 @@ */ public class ItemLicenseProcessor extends ItemSignpostingProcessor { - private static final Logger log = Logger.getLogger(ItemLicenseProcessor.class); + private static final Logger log = LogManager.getLogger(ItemLicenseProcessor.class); private final CreativeCommonsService creativeCommonsService = LicenseServiceFactory.getInstance().getCreativeCommonsService(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLinksetProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLinksetProcessor.java index 9008a28e29a6..1c765047a62d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLinksetProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemLinksetProcessor.java @@ -10,7 +10,8 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -23,7 +24,7 @@ */ public class ItemLinksetProcessor extends ItemSignpostingProcessor { - private static final Logger log = Logger.getLogger(ItemLinksetProcessor.class); + private static final Logger log = LogManager.getLogger(ItemLinksetProcessor.class); private final ConfigurationService configurationService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemTypeProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemTypeProcessor.java index ddd2da12d59a..6945c33619f7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemTypeProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemTypeProcessor.java @@ -11,7 +11,8 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; @@ -27,7 +28,7 @@ */ public class ItemTypeProcessor extends ItemSignpostingProcessor { - private static final Logger log = Logger.getLogger(ItemTypeProcessor.class); + private static final Logger log = LogManager.getLogger(ItemTypeProcessor.class); private static final String ABOUT_PAGE_URI = "https://schema.org/AboutPage"; @Autowired diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/impl/LinksetServiceImpl.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/impl/LinksetServiceImpl.java index 399b7bd1e6b0..de5556173557 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/impl/LinksetServiceImpl.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/impl/LinksetServiceImpl.java @@ -13,7 +13,8 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.security.BitstreamMetadataReadPermissionEvaluatorPlugin; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.processor.bitstream.BitstreamSignpostingProcessor; @@ -37,7 +38,7 @@ @Service public class LinksetServiceImpl implements LinksetService { - private static final Logger log = Logger.getLogger(LinksetServiceImpl.class); + private static final Logger log = LogManager.getLogger(LinksetServiceImpl.class); @Autowired protected ItemService itemService; diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index 01aa68dfbfe6..b72bee24db57 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -101,10 +101,6 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - xom diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index f575898c122a..be9430b4d123 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -97,10 +97,6 @@ org.apache.logging.log4j log4j-core - - org.apache.logging.log4j - log4j-web - + + + + + ${log4j:configParentLocation}/../log + + + + + + + + + yyyy-MM-dd + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index b0d9d1819d3f..9b4dcef37dcf 100644 --- a/pom.xml +++ b/pom.xml @@ -1577,36 +1577,11 @@ log4j-api ${log4j.version} - - org.apache.logging.log4j - log4j-1.2-api - ${log4j.version} - org.apache.logging.log4j log4j-core ${log4j.version} - - org.apache.logging.log4j - log4j-web - ${log4j.version} - - - org.apache.logging.log4j - log4j-slf4j-impl - ${log4j.version} - - - org.apache.logging.log4j - log4j-jul - ${log4j.version} - - - org.slf4j - jul-to-slf4j - ${slf4j.version} - org.apache.pdfbox From 29eefe70b4e5de9da8808ed09bb3cb4c96ffb856 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 20 Nov 2024 12:45:05 -0600 Subject: [PATCH 164/632] Remove unused dependencies from several modules (cherry picked from commit e27ceb57c1324b7b15931d1ed48414c0316c1d2d) --- dspace-services/pom.xml | 23 ----------------------- dspace-sword/pom.xml | 18 ------------------ dspace/modules/server-boot/pom.xml | 4 ---- dspace/modules/server/pom.xml | 5 ----- pom.xml | 14 +------------- 5 files changed, 1 insertion(+), 63 deletions(-) diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 6b2bf191acd5..05b490df7610 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -128,23 +128,6 @@ junit provided - - - org.mortbay.jetty - jetty - 6.1.26 - test - - - org.mortbay.jetty - jetty-servlet-tester - 6.1.26 - test - - - org.apache.commons - commons-collections4 - org.apache.commons commons-configuration2 @@ -164,11 +147,5 @@ jakarta.annotation-api - - org.springframework.boot - spring-boot-starter-log4j2 - ${spring-boot.version} - - diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index 283e61c86afc..ac629cb504e5 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -25,15 +25,6 @@
    - - - - org.dspace dspace-api @@ -63,11 +54,6 @@ - - jaxen - jaxen - - org.apache.httpcomponents httpclient @@ -97,10 +83,6 @@ xom 1.3.9 - - commons-io - commons-io - diff --git a/dspace/modules/server-boot/pom.xml b/dspace/modules/server-boot/pom.xml index f156fbeadb06..87bb2d634e69 100644 --- a/dspace/modules/server-boot/pom.xml +++ b/dspace/modules/server-boot/pom.xml @@ -30,10 +30,6 @@ org.dspace dspace-server-webapp - - org.apache.solr - solr-solrj - diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index c1ce045fe896..f235fcc0279d 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -271,11 +271,6 @@ provided ${spring-boot.version} - - org.apache.solr - solr-solrj - ${solr.client.version} - diff --git a/pom.xml b/pom.xml index d0e720ea3808..f7923b97dedb 100644 --- a/pom.xml +++ b/pom.xml @@ -1163,11 +1163,7 @@ - - org.swordapp - sword-common - 1.1 - + spring-core @@ -1476,14 +1472,6 @@ commons-collections4 4.4 - - - commons-collections - commons-collections - 3.2.2 - org.apache.commons commons-configuration2 From 9f8240987b71f1f37d4f791854b85bcbe870b032 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 20 Nov 2024 12:45:05 -0600 Subject: [PATCH 165/632] Remove unused dependencies from several modules --- dspace-services/pom.xml | 5 ----- dspace-sword/pom.xml | 18 ------------------ dspace/modules/server/pom.xml | 5 ----- pom.xml | 14 +------------- 4 files changed, 1 insertion(+), 41 deletions(-) diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 7c85ff7f0f0f..6504ae2e4b2a 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -131,10 +131,6 @@ 6.1.26 test - - org.apache.commons - commons-collections4 - org.apache.commons commons-configuration2 @@ -159,6 +155,5 @@ spring-boot-starter-log4j2 ${spring-boot.version} - diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index b72bee24db57..12325533c5c5 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -25,15 +25,6 @@ - - - - org.dspace dspace-api @@ -68,11 +59,6 @@ - - jaxen - jaxen - - commons-fileupload @@ -107,10 +93,6 @@ xom 1.3.9 - - commons-io - commons-io - diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index 5134ffb94733..cdbec2f60c8b 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -262,11 +262,6 @@ just adding new jar in the classloader dspace-server-webapp war - - org.apache.solr - solr-solrj - ${solr.client.version} - diff --git a/pom.xml b/pom.xml index 9b4dcef37dcf..c0127724c1d5 100644 --- a/pom.xml +++ b/pom.xml @@ -1179,11 +1179,7 @@ - - org.swordapp - sword-common - 1.1 - + spring-core @@ -1484,14 +1480,6 @@ commons-collections4 4.4 - - - commons-collections - commons-collections - 3.2.2 - org.apache.commons commons-configuration2 From 3ec8862af8888f226c56d177627fa7ac5281bf1c Mon Sep 17 00:00:00 2001 From: Drew Heles Date: Thu, 21 Nov 2024 13:05:19 -0500 Subject: [PATCH 166/632] Update docker files for the 8_x branch --- Dockerfile | 4 ++-- Dockerfile.cli | 4 ++-- Dockerfile.test | 4 ++-- docker-compose-cli.yml | 2 +- docker-compose.yml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index d3f85a5bd641..fb9f8ac512c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,12 @@ # This image will be published as dspace/dspace # See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details # -# - note: default tag for branch: dspace/dspace: dspace/dspace:latest +# - note: default tag for branch: dspace/dspace: dspace/dspace:dspace-8_x # This Dockerfile uses JDK17 by default. # To build with other versions, use "--build-arg JDK_VERSION=[value]" ARG JDK_VERSION=17 -ARG DSPACE_VERSION=latest +ARG DSPACE_VERSION=dspace-8_x # Step 1 - Run Maven Build FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build diff --git a/Dockerfile.cli b/Dockerfile.cli index 5254d1eb4d69..7de72511e849 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -1,12 +1,12 @@ # This image will be published as dspace/dspace-cli # See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details # -# - note: default tag for branch: dspace/dspace-cli: dspace/dspace-cli:latest +# - note: default tag for branch: dspace/dspace-cli: dspace/dspace-cli:dspace-8_x # This Dockerfile uses JDK17 by default. # To build with other versions, use "--build-arg JDK_VERSION=[value]" ARG JDK_VERSION=17 -ARG DSPACE_VERSION=latest +ARG DSPACE_VERSION=dspace-8_x # Step 1 - Run Maven Build FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build diff --git a/Dockerfile.test b/Dockerfile.test index 218126b17aab..921c57e69919 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -1,14 +1,14 @@ # This image will be published as dspace/dspace # See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details # -# - note: default tag for branch: dspace/dspace: dspace/dspace:latest-test +# - note: default tag for branch: dspace/dspace: dspace/dspace:8_x-test # # This image is meant for TESTING/DEVELOPMENT ONLY as it deploys the old v6 REST API under HTTP (not HTTPS) # This Dockerfile uses JDK17 by default. # To build with other versions, use "--build-arg JDK_VERSION=[value]" ARG JDK_VERSION=17 -ARG DSPACE_VERSION=latest +ARG DSPACE_VERSION=dspace-8_x # Step 1 - Run Maven Build FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build diff --git a/docker-compose-cli.yml b/docker-compose-cli.yml index 91f89916d208..dd77bdf108ca 100644 --- a/docker-compose-cli.yml +++ b/docker-compose-cli.yml @@ -6,7 +6,7 @@ networks: external: true services: dspace-cli: - image: "${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-latest}" + image: "${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-dspace-8_x}" container_name: dspace-cli build: context: . diff --git a/docker-compose.yml b/docker-compose.yml index 6a930a8d31ec..4322c7173457 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,7 @@ services: # from the host machine. This IP range MUST correspond to the 'dspacenet' subnet defined above. proxies__P__trusted__P__ipranges: '172.23.0' LOGGING_CONFIG: /dspace/config/log4j2-container.xml - image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-latest-test}" + image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-dspace-8_x-test}" build: context: . dockerfile: Dockerfile.test From b28cc63cbb42985e1a34d1e685c9640fa06a1cce Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 21 Nov 2024 16:21:22 -0600 Subject: [PATCH 167/632] Ensure log4j-slf4j2-impl bridge exists to forward slf4J logs to log4j. Move that and log4j-core to dspace-api so it is inherited everywhere else. --- dspace-api/pom.xml | 8 ++++++++ dspace-oai/pom.xml | 4 ---- dspace-rdf/pom.xml | 4 ---- dspace-sword/pom.xml | 4 ---- dspace-swordv2/pom.xml | 4 ---- pom.xml | 6 ++++++ 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index ada822c1fb12..58bd8106e9af 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -341,6 +341,14 @@ org.apache.logging.log4j log4j-api + + org.apache.logging.log4j + log4j-core + + + org.apache.logging.log4j + log4j-slf4j2-impl + org.hibernate.orm hibernate-core diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index f6b220baed3d..1447fc6e19a0 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -119,10 +119,6 @@ org.apache.logging.log4j log4j-api - - org.apache.logging.log4j - log4j-core - diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index 3b3cb17119a1..f8e1bb9e36c4 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -85,10 +85,6 @@ org.apache.logging.log4j log4j-api - - org.apache.logging.log4j - log4j-core - org.apache.commons diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index ac629cb504e5..48a6392d3dba 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -73,10 +73,6 @@ org.apache.logging.log4j log4j-api - - org.apache.logging.log4j - log4j-core - xom diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index af516d566036..d218406a16cc 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -91,10 +91,6 @@ org.apache.logging.log4j log4j-api - - org.apache.logging.log4j - log4j-core - diff --git a/pom.xml b/pom.xml index f7923b97dedb..4bbd60ca9091 100644 --- a/pom.xml +++ b/pom.xml @@ -1593,6 +1593,12 @@ log4j-core ${log4j.version} + + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j.version} + org.apache.pdfbox From 03890e6ef3b2ab4d5965f7ba2b7d5cf651b292d9 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 21 Nov 2024 16:59:30 -0600 Subject: [PATCH 168/632] Remove unused slf4j dependencies --- pom.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pom.xml b/pom.xml index 4bbd60ca9091..fa37ca9ed4f0 100644 --- a/pom.xml +++ b/pom.xml @@ -1660,16 +1660,6 @@ slf4j-api ${slf4j.version} - - org.slf4j - slf4j-jdk14 - ${slf4j.version} - - - org.slf4j - log4j-over-slf4j - ${slf4j.version} - com.google.errorprone From 9a597891bb319ef5d9ab80cb526d5f0e586c5553 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 22 Nov 2024 11:04:11 -0600 Subject: [PATCH 169/632] Enable all optional modules/controllers to test their deployment in Spring Boot (cherry picked from commit 98768d6f4fcc5181501d02d77ef5056641ac8cd3) --- .github/workflows/docker.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 143b69a2f9fe..816dcd228ca5 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -161,6 +161,15 @@ jobs: env: # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 dspace__P__server__P__url: http://127.0.0.1:8080/server + # Enable all optional modules / controllers for this test deployment. + # This helps check for errors in deploying these modules via Spring Boot + iiif__P__enabled: true + ldn__P__enabled: true + oai__P__enabled: true + rdf__P__enabled: true + signposting__P__enabled: true + sword-server__P__enabled: true + swordv2-server__P__enabled: true # If this is a PR, force using "pr-testing" version of all Docker images. Otherwise, if on main branch, use the # "latest" tag. Otherwise, use the branch name. NOTE: the "pr-testing" tag is a temporary tag that we assign to # all PR-built docker images in reusabe-docker-build.yml From 71e17a275817a68a838575c5e92297c58f8a2bb8 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 22 Nov 2024 13:50:16 -0600 Subject: [PATCH 170/632] Fix syntax error in #10040. Env variables cannot have dashes or periods --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 816dcd228ca5..7e7cbc1b07ca 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -168,8 +168,8 @@ jobs: oai__P__enabled: true rdf__P__enabled: true signposting__P__enabled: true - sword-server__P__enabled: true - swordv2-server__P__enabled: true + sword__D__server__P__enabled: true + swordv2__D__server__P__enabled: true # If this is a PR, force using "pr-testing" version of all Docker images. Otherwise, if on main branch, use the # "latest" tag. Otherwise, use the branch name. NOTE: the "pr-testing" tag is a temporary tag that we assign to # all PR-built docker images in reusabe-docker-build.yml From f44dba60cba8cacaa785e9bc5329b569f77a0c1e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 22 Nov 2024 11:04:11 -0600 Subject: [PATCH 171/632] Enable all optional modules/controllers to test their deployment in Spring Boot (cherry picked from commit 98768d6f4fcc5181501d02d77ef5056641ac8cd3) --- .github/workflows/docker.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 143b69a2f9fe..7013f1e71a09 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -161,6 +161,14 @@ jobs: env: # Override defaults dspace.server.url because backend starts at http://127.0.0.1:8080 dspace__P__server__P__url: http://127.0.0.1:8080/server + # Enable all optional modules / controllers for this test deployment. + # This helps check for errors in deploying these modules via Spring Boot + iiif__P__enabled: true + oai__P__enabled: true + rdf__P__enabled: true + signposting__P__enabled: true + sword-server__P__enabled: true + swordv2-server__P__enabled: true # If this is a PR, force using "pr-testing" version of all Docker images. Otherwise, if on main branch, use the # "latest" tag. Otherwise, use the branch name. NOTE: the "pr-testing" tag is a temporary tag that we assign to # all PR-built docker images in reusabe-docker-build.yml From 66a9782eeefc4e9211a4efdd1a10b1303640415e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 22 Nov 2024 13:50:16 -0600 Subject: [PATCH 172/632] Fix syntax error in #10040. Env variables cannot have dashes or periods --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7013f1e71a09..daa940f215a1 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -167,8 +167,8 @@ jobs: oai__P__enabled: true rdf__P__enabled: true signposting__P__enabled: true - sword-server__P__enabled: true - swordv2-server__P__enabled: true + sword__D__server__P__enabled: true + swordv2__D__server__P__enabled: true # If this is a PR, force using "pr-testing" version of all Docker images. Otherwise, if on main branch, use the # "latest" tag. Otherwise, use the branch name. NOTE: the "pr-testing" tag is a temporary tag that we assign to # all PR-built docker images in reusabe-docker-build.yml From cf99694a84714221ed506fa9afd54f262c11c1ce Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 22 Nov 2024 14:58:08 -0600 Subject: [PATCH 173/632] Fix startup errors for SWORDv2. Requires the log4jv1->v2 bridge to be installed. --- dspace-swordv2/pom.xml | 6 ++++++ pom.xml | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index be9430b4d123..7cae05672470 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -97,6 +97,12 @@ org.apache.logging.log4j log4j-core + + + org.apache.logging.log4j + log4j-1.2-api + + + org.apache.logging.log4j + log4j-1.2-api + ${log4j.version} + org.apache.pdfbox From 54a1c75cbc652bbb60e39157450043087c2d822b Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Thu, 28 Nov 2024 13:06:23 +0100 Subject: [PATCH 174/632] 109807: ArXiv mapping fix - author/name to dc.contributor.author https://info.arxiv.org/help/api/basics.html#using --- dspace/config/spring/api/arxiv-integration.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace/config/spring/api/arxiv-integration.xml b/dspace/config/spring/api/arxiv-integration.xml index e963e73a2055..3f7f408dff40 100644 --- a/dspace/config/spring/api/arxiv-integration.xml +++ b/dspace/config/spring/api/arxiv-integration.xml @@ -94,7 +94,7 @@ - + From 4d1f65c47f7c50bb349c0f13510d57d1d603477c Mon Sep 17 00:00:00 2001 From: "David P. Steelman" Date: Mon, 25 Nov 2024 08:57:37 -0500 Subject: [PATCH 175/632] Adjustments to POM files so that the changes in "modules/server" are incorporated into the JAR generated by "server-boot". This commit adds an "attachClasses" parameter to the "maven-war-plugin" in the "dspace/modules/server/pom.xml", which generates a JAR file that can be referenced in the "dspace/modules/server-boot/pom.xml" (see ) via ``` org.dspace.modules server classes ``` The dependency must be placed *before* the "dspace-server-webapp" dependency, to ensure that it overrides the classes in the "dspace-server-webapp" module. In the "server-boot.jar", the CLASSPATH is determined by the order of JARs in the "BOOT-INF/classpath.idx", which is generated based on the order of dependencies in the POM (see https://stackoverflow.com/a/67997782). The root "pom.xml" file was modified to provide the version for "modules/server" JAR file, in keeping with how the versions of other JAR files are specified. (cherry picked from commit 5bf1f26ebaacfc211d8dac3766ae9e4d7a31d4cd) --- dspace/modules/server-boot/pom.xml | 5 +++++ dspace/modules/server/pom.xml | 1 + pom.xml | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/dspace/modules/server-boot/pom.xml b/dspace/modules/server-boot/pom.xml index 87bb2d634e69..f2f79bb73869 100644 --- a/dspace/modules/server-boot/pom.xml +++ b/dspace/modules/server-boot/pom.xml @@ -26,6 +26,11 @@ org.dspace.modules additions + + org.dspace.modules + server + classes + org.dspace dspace-server-webapp diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index f235fcc0279d..916689516a1c 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -63,6 +63,7 @@ maven-war-plugin false + true true + + @@ -1050,24 +1052,6 @@ Available - - Collected - - - Copyrighted - - - Created - - - Submitted - - - Updated - - - Valid - From 04953b94d919bf5e0135aa3311b70767cba20160 Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Wed, 11 Dec 2024 21:39:08 +0100 Subject: [PATCH 213/632] 121971: #9715 - Only dc.date.issued should have date types Accepted and Issued --- dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl index b6abd9daa056..f92367646d1f 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -731,7 +731,7 @@ From 31c79500ceec1c8e36228195b802a289ac9c30c9 Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Wed, 11 Dec 2024 21:49:37 +0100 Subject: [PATCH 214/632] 121971: #9716 - Only dc.date.embargo should have date type Available --- dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl index f92367646d1f..7b141e48b3a0 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -1049,7 +1049,9 @@ - + + + Available From 52e5b35c0653afc17ebd47ce1272549ddf205469 Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Thu, 12 Dec 2024 09:16:21 +0100 Subject: [PATCH 215/632] 121971: #9664 - Make cclicense step required in openaire submission form --- dspace/config/item-submission.xml | 4 ++++ dspace/config/submission-forms.xml | 23 ----------------------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index a6cd49bdf1e8..866426afd61d 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -379,6 +379,10 @@ + + + + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 39a4778356c0..13c8fc208f6e 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -1133,29 +1133,6 @@ - - - dc - rights - false - - dropdown - Select the access type of the resource. - - - - - - oaire - license - condition - false - - dropdown - Select the license of the resource. - - - dc From e5401685944b6135795462748c791ed7ba7bab7d Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Thu, 12 Dec 2024 09:18:40 +0100 Subject: [PATCH 216/632] 121971: #9867 - Remove objectType attribute from openaire crosswalk --- .../crosswalks/oai/metadataFormats/oai_openaire.xsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl index 7b141e48b3a0..6c6c369071a6 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -888,13 +888,13 @@ - + + fulltext - + other - + --> From 8ec4ae45b887645ab499daf738193bbabe3014cb Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 4 Dec 2024 13:44:44 -0600 Subject: [PATCH 217/632] Add Docker registry to all scripts. Allow it to be configurable for DSpace images (only). Other minor Dockerfile cleanup --- Dockerfile | 16 ++++++++++------ Dockerfile.cli | 16 ++++++++++------ Dockerfile.dependencies | 2 +- Dockerfile.test | 16 ++++++++++------ docker-compose-cli.yml | 2 +- docker-compose.yml | 6 +++--- .../dspace-postgres-pgcrypto-curl/Dockerfile | 2 +- .../docker/dspace-postgres-pgcrypto/Dockerfile | 2 +- .../src/main/docker/dspace-shibboleth/Dockerfile | 2 +- dspace/src/main/docker/dspace-solr/Dockerfile | 2 +- 10 files changed, 39 insertions(+), 27 deletions(-) diff --git a/Dockerfile b/Dockerfile index fb9f8ac512c6..0b844a1b26c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,10 +6,14 @@ # This Dockerfile uses JDK17 by default. # To build with other versions, use "--build-arg JDK_VERSION=[value]" ARG JDK_VERSION=17 +# The Docker version tag to build from ARG DSPACE_VERSION=dspace-8_x +# The Docker registry to use for DSpace images. Defaults to "docker.io" +# NOTE: non-DSpace images are hardcoded to use "docker.io" and are not impacted by this build argument +ARG DOCKER_REGISTRY=docker.io # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build +FROM ${DOCKER_REGISTRY}/dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -31,15 +35,15 @@ RUN mvn --no-transfer-progress package ${MAVEN_FLAGS} && \ RUN rm -rf /install/webapps/server/ # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} AS ant_build +FROM docker.io/eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src WORKDIR /dspace-src # Create the initial install deployment using ANT -ENV ANT_VERSION 1.10.13 -ENV ANT_HOME /tmp/ant-$ANT_VERSION -ENV PATH $ANT_HOME/bin:$PATH +ENV ANT_VERSION=1.10.13 +ENV ANT_HOME=/tmp/ant-$ANT_VERSION +ENV PATH=$ANT_HOME/bin:$PATH # Need wget to install ant RUN apt-get update \ && apt-get install -y --no-install-recommends wget \ @@ -52,7 +56,7 @@ RUN mkdir $ANT_HOME && \ RUN ant init_installation update_configs update_code update_webapps # Step 3 - Start up DSpace via Runnable JAR -FROM eclipse-temurin:${JDK_VERSION} +FROM docker.io/eclipse-temurin:${JDK_VERSION} # NOTE: DSPACE_INSTALL must align with the "dspace.dir" default configuration. ENV DSPACE_INSTALL=/dspace # Copy the /dspace directory from 'ant_build' container to /dspace in this container diff --git a/Dockerfile.cli b/Dockerfile.cli index 7de72511e849..b0b056dfc99e 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -6,10 +6,14 @@ # This Dockerfile uses JDK17 by default. # To build with other versions, use "--build-arg JDK_VERSION=[value]" ARG JDK_VERSION=17 +# The Docker version tag to build from ARG DSPACE_VERSION=dspace-8_x +# The Docker registry to use for DSpace images. Defaults to "docker.io" +# NOTE: non-DSpace images are hardcoded to use "docker.io" and are not impacted by this build argument +ARG DOCKER_REGISTRY=docker.io # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build +FROM ${DOCKER_REGISTRY}/dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -25,15 +29,15 @@ RUN mvn --no-transfer-progress package && \ mvn clean # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} AS ant_build +FROM docker.io/eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src WORKDIR /dspace-src # Create the initial install deployment using ANT -ENV ANT_VERSION 1.10.13 -ENV ANT_HOME /tmp/ant-$ANT_VERSION -ENV PATH $ANT_HOME/bin:$PATH +ENV ANT_VERSION=1.10.13 +ENV ANT_HOME=/tmp/ant-$ANT_VERSION +ENV PATH=$ANT_HOME/bin:$PATH # Need wget to install ant RUN apt-get update \ && apt-get install -y --no-install-recommends wget \ @@ -46,7 +50,7 @@ RUN mkdir $ANT_HOME && \ RUN ant init_installation update_configs update_code # Step 3 - Run jdk -FROM eclipse-temurin:${JDK_VERSION} +FROM docker.io/eclipse-temurin:${JDK_VERSION} # NOTE: DSPACE_INSTALL must align with the "dspace.dir" default configuration. ENV DSPACE_INSTALL=/dspace # Copy the /dspace directory from 'ant_build' container to /dspace in this container diff --git a/Dockerfile.dependencies b/Dockerfile.dependencies index f3bf1f833205..34bfbc3b8c78 100644 --- a/Dockerfile.dependencies +++ b/Dockerfile.dependencies @@ -7,7 +7,7 @@ ARG JDK_VERSION=17 # Step 1 - Run Maven Build -FROM maven:3-eclipse-temurin-${JDK_VERSION} AS build +FROM docker.io/maven:3-eclipse-temurin-${JDK_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # Create the 'dspace' user account & home directory diff --git a/Dockerfile.test b/Dockerfile.test index 921c57e69919..828d61e74708 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -8,10 +8,14 @@ # This Dockerfile uses JDK17 by default. # To build with other versions, use "--build-arg JDK_VERSION=[value]" ARG JDK_VERSION=17 +# The Docker version tag to build from ARG DSPACE_VERSION=dspace-8_x +# The Docker registry to use for DSpace images. Defaults to "docker.io" +# NOTE: non-DSpace images are hardcoded to use "docker.io" and are not impacted by this build argument +ARG DOCKER_REGISTRY=docker.io # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:${DSPACE_VERSION} AS build +FROM ${DOCKER_REGISTRY}/dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -30,15 +34,15 @@ RUN mvn --no-transfer-progress package && \ RUN rm -rf /install/webapps/server/ # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} AS ant_build +FROM docker.io/eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src WORKDIR /dspace-src # Create the initial install deployment using ANT -ENV ANT_VERSION 1.10.12 -ENV ANT_HOME /tmp/ant-$ANT_VERSION -ENV PATH $ANT_HOME/bin:$PATH +ENV ANT_VERSION=1.10.12 +ENV ANT_HOME=/tmp/ant-$ANT_VERSION +ENV PATH=$ANT_HOME/bin:$PATH # Need wget to install ant RUN apt-get update \ && apt-get install -y --no-install-recommends wget \ @@ -51,7 +55,7 @@ RUN mkdir $ANT_HOME && \ RUN ant init_installation update_configs update_code update_webapps # Step 3 - Start up DSpace via Runnable JAR -FROM eclipse-temurin:${JDK_VERSION} +FROM docker.io/eclipse-temurin:${JDK_VERSION} # NOTE: DSPACE_INSTALL must align with the "dspace.dir" default configuration. ENV DSPACE_INSTALL=/dspace # Copy the /dspace directory from 'ant_build' container to /dspace in this container diff --git a/docker-compose-cli.yml b/docker-compose-cli.yml index dd77bdf108ca..5d15845fa8df 100644 --- a/docker-compose-cli.yml +++ b/docker-compose-cli.yml @@ -6,7 +6,7 @@ networks: external: true services: dspace-cli: - image: "${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-dspace-8_x}" + image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-dspace-8_x}" container_name: dspace-cli build: context: . diff --git a/docker-compose.yml b/docker-compose.yml index 8886443824dd..9177ff4bd977 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,7 @@ services: # from the host machine. This IP range MUST correspond to the 'dspacenet' subnet defined above. proxies__P__trusted__P__ipranges: '172.23.0' LOGGING_CONFIG: /dspace/config/log4j2-container.xml - image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-dspace-8_x-test}" + image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-dspace-8_x-test}" build: context: . dockerfile: Dockerfile.test @@ -64,7 +64,7 @@ services: dspacedb: container_name: dspacedb # Uses a custom Postgres image with pgcrypto installed - image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-dspace-8_x}" + image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-dspace-8_x}" build: # Must build out of subdirectory to have access to install script for pgcrypto context: ./dspace/src/main/docker/dspace-postgres-pgcrypto/ @@ -84,7 +84,7 @@ services: # DSpace Solr container dspacesolr: container_name: dspacesolr - image: "${DOCKER_OWNER:-dspace}/dspace-solr:${DSPACE_VER:-dspace-8_x}" + image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace-solr:${DSPACE_VER:-dspace-8_x}" build: context: ./dspace/src/main/docker/dspace-solr/ # Provide path to Solr configs necessary to build Docker image diff --git a/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile b/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile index aabf87df3eda..791242f5bdc7 100644 --- a/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile +++ b/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile @@ -13,7 +13,7 @@ ARG POSTGRES_VERSION=15 ARG POSTGRES_PASSWORD=dspace -FROM postgres:${POSTGRES_VERSION} +FROM docker.io/postgres:${POSTGRES_VERSION} ENV POSTGRES_DB dspace ENV POSTGRES_USER dspace diff --git a/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile b/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile index 2298cd4e76ea..116d2dbcda31 100644 --- a/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile +++ b/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile @@ -13,7 +13,7 @@ ARG POSTGRES_VERSION=15 ARG POSTGRES_PASSWORD=dspace -FROM postgres:${POSTGRES_VERSION} +FROM docker.io/postgres:${POSTGRES_VERSION} ENV POSTGRES_DB dspace ENV POSTGRES_USER dspace diff --git a/dspace/src/main/docker/dspace-shibboleth/Dockerfile b/dspace/src/main/docker/dspace-shibboleth/Dockerfile index 79f2921bd7d6..25fb510e3d39 100644 --- a/dspace/src/main/docker/dspace-shibboleth/Dockerfile +++ b/dspace/src/main/docker/dspace-shibboleth/Dockerfile @@ -10,7 +10,7 @@ # Build from Ubuntu as it has easy Apache tooling (e.g. a2enmod script is debian only). # Apache & mod_shib are required for DSpace to act as an SP # See also https://wiki.lyrasis.org/display/DSDOC7x/Authentication+Plugins#AuthenticationPlugins-ShibbolethAuthentication -FROM ubuntu:20.04 +FROM docker.io/ubuntu:20.04 # Apache ENVs (default values) ENV APACHE_RUN_USER www-data diff --git a/dspace/src/main/docker/dspace-solr/Dockerfile b/dspace/src/main/docker/dspace-solr/Dockerfile index 289949922cc1..241a4345b305 100644 --- a/dspace/src/main/docker/dspace-solr/Dockerfile +++ b/dspace/src/main/docker/dspace-solr/Dockerfile @@ -12,7 +12,7 @@ ARG SOLR_VERSION=8.11 -FROM solr:${SOLR_VERSION}-slim +FROM docker.io/solr:${SOLR_VERSION}-slim ENV AUTHORITY_CONFIGSET_PATH=/opt/solr/server/solr/configsets/authority/conf \ OAI_CONFIGSET_PATH=/opt/solr/server/solr/configsets/oai/conf \ From dee2fae46c419cb86a32753410cd0daecffa0946 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 4 Dec 2024 13:45:33 -0600 Subject: [PATCH 218/632] Minor Dockerfile cleanup. Use new syntax for ENV variables --- .../docker/dspace-postgres-pgcrypto-curl/Dockerfile | 6 +++--- .../main/docker/dspace-postgres-pgcrypto/Dockerfile | 6 +++--- dspace/src/main/docker/dspace-shibboleth/Dockerfile | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile b/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile index 791242f5bdc7..f314fdb79e80 100644 --- a/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile +++ b/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile @@ -15,9 +15,9 @@ ARG POSTGRES_PASSWORD=dspace FROM docker.io/postgres:${POSTGRES_VERSION} -ENV POSTGRES_DB dspace -ENV POSTGRES_USER dspace -ENV POSTGRES_PASSWORD ${POSTGRES_PASSWORD} +ENV POSTGRES_DB=dspace +ENV POSTGRES_USER=dspace +ENV POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # Install curl which is necessary to load SQL file RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* diff --git a/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile b/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile index 116d2dbcda31..4f639f361024 100644 --- a/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile +++ b/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile @@ -15,9 +15,9 @@ ARG POSTGRES_PASSWORD=dspace FROM docker.io/postgres:${POSTGRES_VERSION} -ENV POSTGRES_DB dspace -ENV POSTGRES_USER dspace -ENV POSTGRES_PASSWORD ${POSTGRES_PASSWORD} +ENV POSTGRES_DB=dspace +ENV POSTGRES_USER=dspace +ENV POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # Copy over script which will initialize database and install pgcrypto extension COPY install-pgcrypto.sh /docker-entrypoint-initdb.d/ diff --git a/dspace/src/main/docker/dspace-shibboleth/Dockerfile b/dspace/src/main/docker/dspace-shibboleth/Dockerfile index 25fb510e3d39..15a436d7b6f7 100644 --- a/dspace/src/main/docker/dspace-shibboleth/Dockerfile +++ b/dspace/src/main/docker/dspace-shibboleth/Dockerfile @@ -13,12 +13,12 @@ FROM docker.io/ubuntu:20.04 # Apache ENVs (default values) -ENV APACHE_RUN_USER www-data -ENV APACHE_RUN_GROUP www-data -ENV APACHE_LOCK_DIR /var/lock/apache2 -ENV APACHE_LOG_DIR /var/log/apache2 -ENV APACHE_PID_FILE /var/run/apache2/apache2.pid -ENV APACHE_SERVER_NAME localhost +ENV APACHE_RUN_USER=www-data +ENV APACHE_RUN_GROUP=www-data +ENV APACHE_LOCK_DIR=/var/lock/apache2 +ENV APACHE_LOG_DIR=/var/log/apache2 +ENV APACHE_PID_FILE=/var/run/apache2/apache2.pid +ENV APACHE_SERVER_NAME=localhost # Ensure Apache2, mod_shib & shibboleth daemon are installed. # Also install ssl-cert to provide a local SSL cert for use with Apache From a6d2c4897b46062cca59add6946eb7a86c648585 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 4 Dec 2024 13:44:44 -0600 Subject: [PATCH 219/632] Add Docker registry to all scripts. Allow it to be configurable for DSpace images (only). Other minor Dockerfile cleanup --- Dockerfile | 17 +++++++++++------ Dockerfile.cli | 17 +++++++++++------ Dockerfile.dependencies | 2 +- Dockerfile.test | 17 +++++++++++------ docker-compose-cli.yml | 2 +- docker-compose.yml | 6 +++--- .../dspace-postgres-pgcrypto-curl/Dockerfile | 2 +- .../docker/dspace-postgres-pgcrypto/Dockerfile | 2 +- .../main/docker/dspace-shibboleth/Dockerfile | 2 +- dspace/src/main/docker/dspace-solr/Dockerfile | 2 +- 10 files changed, 42 insertions(+), 27 deletions(-) diff --git a/Dockerfile b/Dockerfile index adc5d6125f0a..ff35f2a2e3a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,9 +6,14 @@ # This Dockerfile uses JDK11 by default, but has also been tested with JDK17. # To build with JDK17, use "--build-arg JDK_VERSION=17" ARG JDK_VERSION=11 +# The Docker version tag to build from +ARG DSPACE_VERSION=dspace-7_x +# The Docker registry to use for DSpace images. Defaults to "docker.io" +# NOTE: non-DSpace images are hardcoded to use "docker.io" and are not impacted by this build argument +ARG DOCKER_REGISTRY=docker.io # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:dspace-7_x AS build +FROM ${DOCKER_REGISTRY}/dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -28,15 +33,15 @@ RUN mvn --no-transfer-progress package ${MAVEN_FLAGS} && \ mvn clean # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} AS ant_build +FROM docker.io/eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src WORKDIR /dspace-src # Create the initial install deployment using ANT -ENV ANT_VERSION 1.10.13 -ENV ANT_HOME /tmp/ant-$ANT_VERSION -ENV PATH $ANT_HOME/bin:$PATH +ENV ANT_VERSION=1.10.13 +ENV ANT_HOME=/tmp/ant-$ANT_VERSION +ENV PATH=$ANT_HOME/bin:$PATH # Need wget to install ant RUN apt-get update \ && apt-get install -y --no-install-recommends wget \ @@ -50,7 +55,7 @@ RUN ant init_installation update_configs update_code update_webapps # Step 3 - Run tomcat # Create a new tomcat image that does not retain the the build directory contents -FROM tomcat:9-jdk${JDK_VERSION} +FROM docker.io/tomcat:9-jdk${JDK_VERSION} # NOTE: DSPACE_INSTALL must align with the "dspace.dir" default configuration. ENV DSPACE_INSTALL=/dspace # Copy the /dspace directory from 'ant_build' container to /dspace in this container diff --git a/Dockerfile.cli b/Dockerfile.cli index 8a69b32e2dc6..be03e8922b2c 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -6,9 +6,14 @@ # This Dockerfile uses JDK11 by default, but has also been tested with JDK17. # To build with JDK17, use "--build-arg JDK_VERSION=17" ARG JDK_VERSION=11 +# The Docker version tag to build from +ARG DSPACE_VERSION=dspace-7_x +# The Docker registry to use for DSpace images. Defaults to "docker.io" +# NOTE: non-DSpace images are hardcoded to use "docker.io" and are not impacted by this build argument +ARG DOCKER_REGISTRY=docker.io # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:dspace-7_x AS build +FROM ${DOCKER_REGISTRY}/dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -24,15 +29,15 @@ RUN mvn --no-transfer-progress package && \ mvn clean # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} AS ant_build +FROM docker.io/eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src WORKDIR /dspace-src # Create the initial install deployment using ANT -ENV ANT_VERSION 1.10.13 -ENV ANT_HOME /tmp/ant-$ANT_VERSION -ENV PATH $ANT_HOME/bin:$PATH +ENV ANT_VERSION=1.10.13 +ENV ANT_HOME=/tmp/ant-$ANT_VERSION +ENV PATH=$ANT_HOME/bin:$PATH # Need wget to install ant RUN apt-get update \ && apt-get install -y --no-install-recommends wget \ @@ -45,7 +50,7 @@ RUN mkdir $ANT_HOME && \ RUN ant init_installation update_configs update_code # Step 3 - Run jdk -FROM eclipse-temurin:${JDK_VERSION} +FROM docker.io/eclipse-temurin:${JDK_VERSION} # NOTE: DSPACE_INSTALL must align with the "dspace.dir" default configuration. ENV DSPACE_INSTALL=/dspace # Copy the /dspace directory from 'ant_build' container to /dspace in this container diff --git a/Dockerfile.dependencies b/Dockerfile.dependencies index 123206ea5887..794dfa9a66a8 100644 --- a/Dockerfile.dependencies +++ b/Dockerfile.dependencies @@ -7,7 +7,7 @@ ARG JDK_VERSION=11 # Step 1 - Run Maven Build -FROM maven:3-eclipse-temurin-${JDK_VERSION} AS build +FROM docker.io/maven:3-eclipse-temurin-${JDK_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # Create the 'dspace' user account & home directory diff --git a/Dockerfile.test b/Dockerfile.test index d88699ca52ab..08b6b3018b80 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -8,9 +8,14 @@ # This Dockerfile uses JDK11 by default, but has also been tested with JDK17. # To build with JDK17, use "--build-arg JDK_VERSION=17" ARG JDK_VERSION=11 +# The Docker version tag to build from +ARG DSPACE_VERSION=dspace-7_x +# The Docker registry to use for DSpace images. Defaults to "docker.io" +# NOTE: non-DSpace images are hardcoded to use "docker.io" and are not impacted by this build argument +ARG DOCKER_REGISTRY=docker.io # Step 1 - Run Maven Build -FROM dspace/dspace-dependencies:dspace-7_x AS build +FROM ${DOCKER_REGISTRY}/dspace/dspace-dependencies:${DSPACE_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app # The dspace-installer directory will be written to /install @@ -27,15 +32,15 @@ RUN mvn --no-transfer-progress package -Pdspace-rest && \ mvn clean # Step 2 - Run Ant Deploy -FROM eclipse-temurin:${JDK_VERSION} AS ant_build +FROM docker.io/eclipse-temurin:${JDK_VERSION} AS ant_build ARG TARGET_DIR=dspace-installer # COPY the /install directory from 'build' container to /dspace-src in this container COPY --from=build /install /dspace-src WORKDIR /dspace-src # Create the initial install deployment using ANT -ENV ANT_VERSION 1.10.12 -ENV ANT_HOME /tmp/ant-$ANT_VERSION -ENV PATH $ANT_HOME/bin:$PATH +ENV ANT_VERSION=1.10.12 +ENV ANT_HOME=/tmp/ant-$ANT_VERSION +ENV PATH=$ANT_HOME/bin:$PATH # Need wget to install ant RUN apt-get update \ && apt-get install -y --no-install-recommends wget \ @@ -49,7 +54,7 @@ RUN ant init_installation update_configs update_code update_webapps # Step 3 - Run tomcat # Create a new tomcat image that does not retain the the build directory contents -FROM tomcat:9-jdk${JDK_VERSION} +FROM docker.io/tomcat:9-jdk${JDK_VERSION} ENV DSPACE_INSTALL=/dspace ENV TOMCAT_INSTALL=/usr/local/tomcat # Copy the /dspace directory from 'ant_build' containger to /dspace in this container diff --git a/docker-compose-cli.yml b/docker-compose-cli.yml index d6a194617e02..ce7676bdc6c3 100644 --- a/docker-compose-cli.yml +++ b/docker-compose-cli.yml @@ -6,7 +6,7 @@ networks: external: true services: dspace-cli: - image: "${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-dspace-7_x}" + image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-dspace-7_x}" container_name: dspace-cli build: context: . diff --git a/docker-compose.yml b/docker-compose.yml index 23fce37db245..a16c3677503c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,7 @@ services: # from the host machine. This IP range MUST correspond to the 'dspacenet' subnet defined above. proxies__P__trusted__P__ipranges: '172.23.0' LOGGING_CONFIG: /dspace/config/log4j2-container.xml - image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-dspace-7_x-test}" + image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-dspace-7_x-test}" build: context: . dockerfile: Dockerfile.test @@ -66,7 +66,7 @@ services: dspacedb: container_name: dspacedb # Uses a custom Postgres image with pgcrypto installed - image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-dspace-7_x}" + image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-dspace-7_x}" build: # Must build out of subdirectory to have access to install script for pgcrypto context: ./dspace/src/main/docker/dspace-postgres-pgcrypto/ @@ -86,7 +86,7 @@ services: # DSpace Solr container dspacesolr: container_name: dspacesolr - image: "${DOCKER_OWNER:-dspace}/dspace-solr:${DSPACE_VER:-dspace-7_x}" + image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace-solr:${DSPACE_VER:-dspace-7_x}" build: context: ./dspace/src/main/docker/dspace-solr/ # Provide path to Solr configs necessary to build Docker image diff --git a/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile b/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile index aabf87df3eda..791242f5bdc7 100644 --- a/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile +++ b/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile @@ -13,7 +13,7 @@ ARG POSTGRES_VERSION=15 ARG POSTGRES_PASSWORD=dspace -FROM postgres:${POSTGRES_VERSION} +FROM docker.io/postgres:${POSTGRES_VERSION} ENV POSTGRES_DB dspace ENV POSTGRES_USER dspace diff --git a/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile b/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile index 2298cd4e76ea..116d2dbcda31 100644 --- a/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile +++ b/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile @@ -13,7 +13,7 @@ ARG POSTGRES_VERSION=15 ARG POSTGRES_PASSWORD=dspace -FROM postgres:${POSTGRES_VERSION} +FROM docker.io/postgres:${POSTGRES_VERSION} ENV POSTGRES_DB dspace ENV POSTGRES_USER dspace diff --git a/dspace/src/main/docker/dspace-shibboleth/Dockerfile b/dspace/src/main/docker/dspace-shibboleth/Dockerfile index 79f2921bd7d6..25fb510e3d39 100644 --- a/dspace/src/main/docker/dspace-shibboleth/Dockerfile +++ b/dspace/src/main/docker/dspace-shibboleth/Dockerfile @@ -10,7 +10,7 @@ # Build from Ubuntu as it has easy Apache tooling (e.g. a2enmod script is debian only). # Apache & mod_shib are required for DSpace to act as an SP # See also https://wiki.lyrasis.org/display/DSDOC7x/Authentication+Plugins#AuthenticationPlugins-ShibbolethAuthentication -FROM ubuntu:20.04 +FROM docker.io/ubuntu:20.04 # Apache ENVs (default values) ENV APACHE_RUN_USER www-data diff --git a/dspace/src/main/docker/dspace-solr/Dockerfile b/dspace/src/main/docker/dspace-solr/Dockerfile index eb8e93493fa8..0c011d43105f 100644 --- a/dspace/src/main/docker/dspace-solr/Dockerfile +++ b/dspace/src/main/docker/dspace-solr/Dockerfile @@ -12,7 +12,7 @@ ARG SOLR_VERSION=8.11 -FROM solr:${SOLR_VERSION}-slim +FROM docker.io/solr:${SOLR_VERSION}-slim ENV AUTHORITY_CONFIGSET_PATH=/opt/solr/server/solr/configsets/authority/conf \ OAI_CONFIGSET_PATH=/opt/solr/server/solr/configsets/oai/conf \ From 2ee328ff18aa973dd2ed82abd062d8a923cbddf5 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 4 Dec 2024 13:45:33 -0600 Subject: [PATCH 220/632] Minor Dockerfile cleanup. Use new syntax for ENV variables --- .../docker/dspace-postgres-pgcrypto-curl/Dockerfile | 6 +++--- .../main/docker/dspace-postgres-pgcrypto/Dockerfile | 6 +++--- dspace/src/main/docker/dspace-shibboleth/Dockerfile | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile b/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile index 791242f5bdc7..f314fdb79e80 100644 --- a/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile +++ b/dspace/src/main/docker/dspace-postgres-pgcrypto-curl/Dockerfile @@ -15,9 +15,9 @@ ARG POSTGRES_PASSWORD=dspace FROM docker.io/postgres:${POSTGRES_VERSION} -ENV POSTGRES_DB dspace -ENV POSTGRES_USER dspace -ENV POSTGRES_PASSWORD ${POSTGRES_PASSWORD} +ENV POSTGRES_DB=dspace +ENV POSTGRES_USER=dspace +ENV POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # Install curl which is necessary to load SQL file RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* diff --git a/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile b/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile index 116d2dbcda31..4f639f361024 100644 --- a/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile +++ b/dspace/src/main/docker/dspace-postgres-pgcrypto/Dockerfile @@ -15,9 +15,9 @@ ARG POSTGRES_PASSWORD=dspace FROM docker.io/postgres:${POSTGRES_VERSION} -ENV POSTGRES_DB dspace -ENV POSTGRES_USER dspace -ENV POSTGRES_PASSWORD ${POSTGRES_PASSWORD} +ENV POSTGRES_DB=dspace +ENV POSTGRES_USER=dspace +ENV POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # Copy over script which will initialize database and install pgcrypto extension COPY install-pgcrypto.sh /docker-entrypoint-initdb.d/ diff --git a/dspace/src/main/docker/dspace-shibboleth/Dockerfile b/dspace/src/main/docker/dspace-shibboleth/Dockerfile index 25fb510e3d39..15a436d7b6f7 100644 --- a/dspace/src/main/docker/dspace-shibboleth/Dockerfile +++ b/dspace/src/main/docker/dspace-shibboleth/Dockerfile @@ -13,12 +13,12 @@ FROM docker.io/ubuntu:20.04 # Apache ENVs (default values) -ENV APACHE_RUN_USER www-data -ENV APACHE_RUN_GROUP www-data -ENV APACHE_LOCK_DIR /var/lock/apache2 -ENV APACHE_LOG_DIR /var/log/apache2 -ENV APACHE_PID_FILE /var/run/apache2/apache2.pid -ENV APACHE_SERVER_NAME localhost +ENV APACHE_RUN_USER=www-data +ENV APACHE_RUN_GROUP=www-data +ENV APACHE_LOCK_DIR=/var/lock/apache2 +ENV APACHE_LOG_DIR=/var/log/apache2 +ENV APACHE_PID_FILE=/var/run/apache2/apache2.pid +ENV APACHE_SERVER_NAME=localhost # Ensure Apache2, mod_shib & shibboleth daemon are installed. # Also install ssl-cert to provide a local SSL cert for use with Apache From f5dcb445514fea275d6986ab40bd66671c2f53e9 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 12 Dec 2024 16:50:02 -0600 Subject: [PATCH 221/632] Refactor Docker build process to use ghcr.io for build, and then copy to docker.io once build completes (cherry picked from commit e6eb00366c4d6ee14366f2061f62682c1b5ed05f) --- .github/workflows/docker.yml | 1 + .github/workflows/reusable-docker-build.yml | 188 ++++++++++++++------ 2 files changed, 130 insertions(+), 59 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0a5618fbe354..d279fca009f4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -15,6 +15,7 @@ on: permissions: contents: read # to fetch code (actions/checkout) + packages: write # to write images to GitHub Container Registry (GHCR) jobs: #################################################### diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index a6e326846006..085880db266b 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -75,6 +75,9 @@ env: DEPLOY_DEMO_BRANCH: 'dspace-8_x' DEPLOY_SANDBOX_BRANCH: 'main' DEPLOY_ARCH: 'linux/amd64' + # Registry used during building of Docker images. (All images are later copied to docker.io registry) + # We use GitHub's Container Registry to avoid aggressive rate limits at DockerHub. + DOCKER_BUILD_REGISTRY: ghcr.io jobs: docker-build: @@ -99,6 +102,7 @@ jobs: # This step converts the slashes in the "arch" matrix values above into dashes & saves to env.ARCH_NAME # E.g. "linux/amd64" becomes "linux-amd64" # This is necessary because all upload artifacts CANNOT have special chars (like slashes) + # NOTE: The regex-like syntax below is Bash Parameter Substitution - name: Prepare run: | platform=${{ matrix.arch }} @@ -109,13 +113,14 @@ jobs: uses: actions/checkout@v4 # https://github.com/docker/login-action - - name: Login to DockerHub - # Only login if not a PR, as PRs only trigger a Docker build and not a push + - name: Login to ${{ env.DOCKER_BUILD_REGISTRY }} + # Only login if not a PR, as PRs only trigger a Docker build and not a push if: ${{ ! matrix.isPr }} uses: docker/login-action@v3 with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + registry: ${{ env.DOCKER_BUILD_REGISTRY }} + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} # https://github.com/docker/setup-qemu-action - name: Set up QEMU emulation to build for multiple architectures @@ -131,19 +136,20 @@ jobs: id: meta_build uses: docker/metadata-action@v5 with: - images: ${{ env.IMAGE_NAME }} + images: ${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }} tags: ${{ env.IMAGE_TAGS }} flavor: ${{ env.TAGS_FLAVOR }} - #------------------------------------------------------------ - # Build & deploy steps for new commits to a branch (non-PRs) + #-------------------------------------------------------------------- + # First, for all branch commits (non-PRs) we build the image & upload + # to GitHub Container Registry (GHCR). After uploading the image + # to GHCR, we store the image digest in an artifact, so we can + # create a merged manifest later (see 'docker-build_manifest' job). # - # These steps build the images, push to DockerHub, and - # (if necessary) redeploy demo/sandbox sites. - #------------------------------------------------------------ + # NOTE: We use GHCR in order to avoid aggressive rate limits at DockerHub. + #-------------------------------------------------------------------- # https://github.com/docker/build-push-action - - name: Build and push image to DockerHub - # Only build & push if not a PR + - name: Build and push image to ${{ env.DOCKER_BUILD_REGISTRY }} if: ${{ ! matrix.isPr }} id: docker_build uses: docker/build-push-action@v5 @@ -152,6 +158,9 @@ jobs: ${{ inputs.dockerfile_additional_contexts }} context: ${{ inputs.dockerfile_context }} file: ${{ inputs.dockerfile_path }} + # Tell DSpace's Docker files to use the build registry instead of DockerHub + build-args: + DOCKER_REGISTRY=${{ env.DOCKER_BUILD_REGISTRY }} platforms: ${{ matrix.arch }} push: true # Use tags / labels provided by 'docker/metadata-action' above @@ -162,7 +171,7 @@ jobs: cache-from: type=gha,scope=${{ inputs.build_id }} cache-to: type=gha,scope=${{ inputs.build_id }},mode=max - # Export the digest of Docker build locally (for non PRs only) + # Export the digest of Docker build locally - name: Export Docker build digest if: ${{ ! matrix.isPr }} run: | @@ -170,7 +179,8 @@ jobs: digest="${{ steps.docker_build.outputs.digest }}" touch "/tmp/digests/${digest#sha256:}" - # Upload digest to an artifact, so that it can be used in manifest below + # Upload digest to an artifact, so that it can be used in combined manifest below + # (The purpose of the combined manifest is to list both amd64 and arm64 builds under same tag) - name: Upload Docker build digest to artifact if: ${{ ! matrix.isPr }} uses: actions/upload-artifact@v4 @@ -180,48 +190,31 @@ jobs: if-no-files-found: error retention-days: 1 - # If this build is NOT a PR and passed in a REDEPLOY_SANDBOX_URL secret, - # Then redeploy https://sandbox.dspace.org if this build is for our deployment architecture and 'main' branch. - - name: Redeploy sandbox.dspace.org (based on main branch) - if: | - !matrix.isPR && - env.REDEPLOY_SANDBOX_URL != '' && - matrix.arch == env.DEPLOY_ARCH && - github.ref_name == env.DEPLOY_SANDBOX_BRANCH - run: | - curl -X POST $REDEPLOY_SANDBOX_URL - - # If this build is NOT a PR and passed in a REDEPLOY_DEMO_URL secret, - # Then redeploy https://demo.dspace.org if this build is for our deployment architecture and demo branch. - - name: Redeploy demo.dspace.org (based on maintenance branch) - if: | - !matrix.isPR && - env.REDEPLOY_DEMO_URL != '' && - matrix.arch == env.DEPLOY_ARCH && - github.ref_name == env.DEPLOY_DEMO_BRANCH - run: | - curl -X POST $REDEPLOY_DEMO_URL - - #------------------------------------------------------------- - # Shared Build steps. - # These are used for PRs as well as new commits to a branch (non-PRs) + #------------------------------------------------------------------------------ + # Second, we build the image again in order to store it in a local TAR file. + # This TAR of the image is cached/saved as an artifact, so that it can be used + # by later jobs to install the brand-new images for automated testing. + # This TAR build is performed BOTH for PRs and for branch commits (non-PRs). # - # These steps build the images and cache/store as a build artifact. - # These artifacts can then be used by later jobs to install the - # brand-new images for automated testing. For non-PRs, this cache is - # also used to avoid pulling the images we just built from DockerHub. - #-------------------------------------------------------------- - + # (This approach has the advantage of avoiding having to download the newly built + # image from DockerHub or GHCR during automated testing.) + # + # See the 'docker-deploy' job in docker.yml as an example of where this TAR is used. + #------------------------------------------------------------------------------- # Build local image (again) and store in a TAR file in /tmp directory - # NOTE: This build is run for both PRs and non-PRs as it's used to "cache" our built images as artifacts. - # NOTE #2: This cannot be combined with push to DockerHub registry above as it's a different type of output. + # This step is only done for AMD64, as that's the only image we use in our automated testing (at this time). + # NOTE: This step cannot be combined with the build above as it's a different type of output. - name: Build and push image to local TAR file + if: ${{ matrix.arch == 'linux/amd64'}} uses: docker/build-push-action@v5 with: build-contexts: | ${{ inputs.dockerfile_additional_contexts }} context: ${{ inputs.dockerfile_context }} file: ${{ inputs.dockerfile_path }} + # Tell DSpace's Docker files to use the build registry instead of DockerHub + build-args: + DOCKER_REGISTRY=${{ env.DOCKER_BUILD_REGISTRY }} platforms: ${{ matrix.arch }} tags: ${{ steps.meta_build.outputs.tags }} labels: ${{ steps.meta_build.outputs.labels }} @@ -233,7 +226,9 @@ jobs: outputs: type=docker,dest=/tmp/${{ inputs.build_id }}.tar # Upload the local docker image (in TAR file) to a build Artifact + # This step is only done for AMD64, as that's the only image we use in our automated testing (at this time). - name: Upload local image TAR to artifact + if: ${{ matrix.arch == 'linux/amd64'}} uses: actions/upload-artifact@v4 with: name: docker-image-${{ inputs.build_id }}-${{ env.ARCH_NAME }} @@ -241,10 +236,12 @@ jobs: if-no-files-found: error retention-days: 1 - # Merge Docker digests (from various architectures) into a manifest. - # This runs after all Docker builds complete above, and it tells hub.docker.com - # that these builds should be all included in the manifest for this tag. - # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) + ########################################################################################## + # Merge Docker digests (from various architectures) into a single manifest. + # This runs after all Docker builds complete above. The purpose is to include all builds + # under a single manifest for this tag. + # (e.g. both linux/amd64 and linux/arm64 should be listed under the same tagged Docker image) + ########################################################################################## docker-build_manifest: # Only run if this is NOT a PR if: ${{ github.event_name != 'pull_request' }} @@ -260,11 +257,12 @@ jobs: pattern: digests-${{ inputs.build_id }}-* merge-multiple: true - - name: Login to Docker Hub + - name: Login to ${{ env.DOCKER_BUILD_REGISTRY }} uses: docker/login-action@v3 with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + registry: ${{ env.DOCKER_BUILD_REGISTRY }} + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -273,16 +271,88 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.IMAGE_NAME }} + images: ${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }} tags: ${{ env.IMAGE_TAGS }} flavor: ${{ env.TAGS_FLAVOR }} - - name: Create manifest list from digests and push + - name: Create manifest list from digests and push to ${{ env.DOCKER_BUILD_REGISTRY }} working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *) + $(printf '${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) + + - name: Inspect manifest in ${{ env.DOCKER_BUILD_REGISTRY }} + run: | + docker buildx imagetools inspect ${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} + + ########################################################################################## + # Copy images / manifest to DockerHub. + # This MUST run after *both* images (AMD64 and ARM64) are built and uploaded to GitHub + # Container Registry (GHCR). Attempting to run this in parallel to GHCR builds can result + # in a race condition...i.e. the copy to DockerHub may fail if GHCR image has been updated + # at the moment when the copy occurs. + ########################################################################################## + docker-copy_to_dockerhub: + # Only run if this is NOT a PR + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + - docker-build_manifest + + steps: + # 'regctl' is used to more easily copy the image to DockerHub and obtain the digest from DockerHub + # See https://github.com/regclient/regclient/blob/main/docs/regctl.md + - name: Install regctl for Docker registry tools + uses: regclient/actions/regctl-installer@main + with: + release: 'v0.8.0' + + # This recreates Docker tags for DockerHub + - name: Add Docker metadata for image + id: meta_dockerhub + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + tags: ${{ env.IMAGE_TAGS }} + flavor: ${{ env.TAGS_FLAVOR }} + + # Login to source registry first, as this is where we are copying *from* + - name: Login to ${{ env.DOCKER_BUILD_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_BUILD_REGISTRY }} + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Login to DockerHub, since this is where we are copying *to* + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + # Copy the image from source to DockerHub + - name: Copy image from ${{ env.DOCKER_BUILD_REGISTRY }} to docker.io + run: | + regctl image copy ${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta_dockerhub.outputs.version }} docker.io/${{ env.IMAGE_NAME }}:${{ steps.meta_dockerhub.outputs.version }} - - name: Inspect image + #-------------------------------------------------------------------- + # Finally, check whether demo.dspace.org or sandbox.dspace.org need + # to be redeployed based on these new DockerHub images. + #-------------------------------------------------------------------- + # If this build is for the branch that Sandbox uses and passed in a REDEPLOY_SANDBOX_URL secret, + # Then redeploy https://sandbox.dspace.org + - name: Redeploy sandbox.dspace.org (based on main branch) + if: | + env.REDEPLOY_SANDBOX_URL != '' && + github.ref_name == env.DEPLOY_SANDBOX_BRANCH + run: | + curl -X POST $REDEPLOY_SANDBOX_URL + # If this build is for the branch that Demo uses and passed in a REDEPLOY_DEMO_URL secret, + # Then redeploy https://demo.dspace.org + - name: Redeploy demo.dspace.org (based on maintenance branch) + if: | + env.REDEPLOY_DEMO_URL != '' && + github.ref_name == env.DEPLOY_DEMO_BRANCH run: | - docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} + curl -X POST $REDEPLOY_DEMO_URL \ No newline at end of file From dc4c4ebc8179fbc661d62735782acb2f6024bc98 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 16 Dec 2024 12:05:41 -0600 Subject: [PATCH 222/632] PRs must also login to ghcr.io in order to read private images for the build process (cherry picked from commit 04d891241b36bad94a1c8a5ae02d99e50f06bf35) --- .github/workflows/reusable-docker-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index 085880db266b..7a8abda3e106 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -113,9 +113,9 @@ jobs: uses: actions/checkout@v4 # https://github.com/docker/login-action + # NOTE: This login occurs for BOTH non-PRs or PRs. PRs *must* also login to access private images from GHCR + # during the build process - name: Login to ${{ env.DOCKER_BUILD_REGISTRY }} - # Only login if not a PR, as PRs only trigger a Docker build and not a push - if: ${{ ! matrix.isPr }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_BUILD_REGISTRY }} From 0328d076be5bb056a191078c9f0a01e0954e448d Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 16 Dec 2024 12:28:16 -0600 Subject: [PATCH 223/632] Ensure "docker-deploy" job also uses ghcr.io by default. (cherry picked from commit 5f314c9a75e1cf6ddaf1f91eeaa267add9ff3439) --- .github/workflows/docker.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d279fca009f4..9d32cb119d41 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -177,6 +177,9 @@ jobs: # Else, just use the branch name. # NOTE: DSPACE_VER is used because our docker compose scripts default to using the "-test" image. DSPACE_VER: ${{ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == github.event.repository.default_branch && 'latest') || (github.event_name == 'pull_request' && github.event.pull_request.base.ref) || (github.ref_name == github.event.repository.default_branch && 'latest') || github.ref_name }} + # Docker Registry to use for Docker compose scripts below. + # We use GitHub's Container Registry to avoid aggressive rate limits at DockerHub. + DOCKER_REGISTRY: ghcr.io steps: # Checkout our codebase (to get access to Docker Compose scripts) - name: Checkout codebase From 2a6c60e1392cf643b4ae4c8512ce92c7aba4b2eb Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 12 Dec 2024 16:50:02 -0600 Subject: [PATCH 224/632] Refactor Docker build process to use ghcr.io for build, and then copy to docker.io once build completes --- .github/workflows/docker.yml | 1 + .github/workflows/reusable-docker-build.yml | 189 ++++++++++++++------ 2 files changed, 131 insertions(+), 59 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ebbd8cc50984..fceea6403d2a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -15,6 +15,7 @@ on: permissions: contents: read # to fetch code (actions/checkout) + packages: write # to write images to GitHub Container Registry (GHCR) jobs: #################################################### diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index d9f4c5342b40..36546af3a5da 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -74,7 +74,11 @@ env: # Current DSpace maintenance branch (and architecture) which is deployed to demo.dspace.org / sandbox.dspace.org # (NOTE: No deployment branch specified for sandbox.dspace.org as it uses the default_branch) DEPLOY_DEMO_BRANCH: 'dspace-8_x' + DEPLOY_SANDBOX_BRANCH: 'main' DEPLOY_ARCH: 'linux/amd64' + # Registry used during building of Docker images. (All images are later copied to docker.io registry) + # We use GitHub's Container Registry to avoid aggressive rate limits at DockerHub. + DOCKER_BUILD_REGISTRY: ghcr.io jobs: docker-build: @@ -99,6 +103,7 @@ jobs: # This step converts the slashes in the "arch" matrix values above into dashes & saves to env.ARCH_NAME # E.g. "linux/amd64" becomes "linux-amd64" # This is necessary because all upload artifacts CANNOT have special chars (like slashes) + # NOTE: The regex-like syntax below is Bash Parameter Substitution - name: Prepare run: | platform=${{ matrix.arch }} @@ -109,13 +114,14 @@ jobs: uses: actions/checkout@v4 # https://github.com/docker/login-action - - name: Login to DockerHub - # Only login if not a PR, as PRs only trigger a Docker build and not a push + - name: Login to ${{ env.DOCKER_BUILD_REGISTRY }} + # Only login if not a PR, as PRs only trigger a Docker build and not a push if: ${{ ! matrix.isPr }} uses: docker/login-action@v3 with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + registry: ${{ env.DOCKER_BUILD_REGISTRY }} + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} # https://github.com/docker/setup-qemu-action - name: Set up QEMU emulation to build for multiple architectures @@ -131,19 +137,20 @@ jobs: id: meta_build uses: docker/metadata-action@v5 with: - images: ${{ env.IMAGE_NAME }} + images: ${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }} tags: ${{ env.IMAGE_TAGS }} flavor: ${{ env.TAGS_FLAVOR }} - #------------------------------------------------------------ - # Build & deploy steps for new commits to a branch (non-PRs) + #-------------------------------------------------------------------- + # First, for all branch commits (non-PRs) we build the image & upload + # to GitHub Container Registry (GHCR). After uploading the image + # to GHCR, we store the image digest in an artifact, so we can + # create a merged manifest later (see 'docker-build_manifest' job). # - # These steps build the images, push to DockerHub, and - # (if necessary) redeploy demo/sandbox sites. - #------------------------------------------------------------ + # NOTE: We use GHCR in order to avoid aggressive rate limits at DockerHub. + #-------------------------------------------------------------------- # https://github.com/docker/build-push-action - - name: Build and push image to DockerHub - # Only build & push if not a PR + - name: Build and push image to ${{ env.DOCKER_BUILD_REGISTRY }} if: ${{ ! matrix.isPr }} id: docker_build uses: docker/build-push-action@v5 @@ -152,6 +159,9 @@ jobs: ${{ inputs.dockerfile_additional_contexts }} context: ${{ inputs.dockerfile_context }} file: ${{ inputs.dockerfile_path }} + # Tell DSpace's Docker files to use the build registry instead of DockerHub + build-args: + DOCKER_REGISTRY=${{ env.DOCKER_BUILD_REGISTRY }} platforms: ${{ matrix.arch }} push: true # Use tags / labels provided by 'docker/metadata-action' above @@ -162,7 +172,7 @@ jobs: cache-from: type=gha,scope=${{ inputs.build_id }} cache-to: type=gha,scope=${{ inputs.build_id }},mode=max - # Export the digest of Docker build locally (for non PRs only) + # Export the digest of Docker build locally - name: Export Docker build digest if: ${{ ! matrix.isPr }} run: | @@ -170,7 +180,8 @@ jobs: digest="${{ steps.docker_build.outputs.digest }}" touch "/tmp/digests/${digest#sha256:}" - # Upload digest to an artifact, so that it can be used in manifest below + # Upload digest to an artifact, so that it can be used in combined manifest below + # (The purpose of the combined manifest is to list both amd64 and arm64 builds under same tag) - name: Upload Docker build digest to artifact if: ${{ ! matrix.isPr }} uses: actions/upload-artifact@v4 @@ -180,48 +191,31 @@ jobs: if-no-files-found: error retention-days: 1 - # If this build is NOT a PR and passed in a REDEPLOY_SANDBOX_URL secret, - # Then redeploy https://sandbox.dspace.org if this build is for our deployment architecture and 'main' branch. - - name: Redeploy sandbox.dspace.org (based on main branch) - if: | - !matrix.isPR && - env.REDEPLOY_SANDBOX_URL != '' && - matrix.arch == env.DEPLOY_ARCH && - github.ref_name == github.event.repository.default_branch - run: | - curl -X POST $REDEPLOY_SANDBOX_URL - - # If this build is NOT a PR and passed in a REDEPLOY_DEMO_URL secret, - # Then redeploy https://demo.dspace.org if this build is for our deployment architecture and demo branch. - - name: Redeploy demo.dspace.org (based on maintenance branch) - if: | - !matrix.isPR && - env.REDEPLOY_DEMO_URL != '' && - matrix.arch == env.DEPLOY_ARCH && - github.ref_name == env.DEPLOY_DEMO_BRANCH - run: | - curl -X POST $REDEPLOY_DEMO_URL - - #------------------------------------------------------------- - # Shared Build steps. - # These are used for PRs as well as new commits to a branch (non-PRs) + #------------------------------------------------------------------------------ + # Second, we build the image again in order to store it in a local TAR file. + # This TAR of the image is cached/saved as an artifact, so that it can be used + # by later jobs to install the brand-new images for automated testing. + # This TAR build is performed BOTH for PRs and for branch commits (non-PRs). # - # These steps build the images and cache/store as a build artifact. - # These artifacts can then be used by later jobs to install the - # brand-new images for automated testing. For non-PRs, this cache is - # also used to avoid pulling the images we just built from DockerHub. - #-------------------------------------------------------------- - + # (This approach has the advantage of avoiding having to download the newly built + # image from DockerHub or GHCR during automated testing.) + # + # See the 'docker-deploy' job in docker.yml as an example of where this TAR is used. + #------------------------------------------------------------------------------- # Build local image (again) and store in a TAR file in /tmp directory - # NOTE: This build is run for both PRs and non-PRs as it's used to "cache" our built images as artifacts. - # NOTE #2: This cannot be combined with push to DockerHub registry above as it's a different type of output. + # This step is only done for AMD64, as that's the only image we use in our automated testing (at this time). + # NOTE: This step cannot be combined with the build above as it's a different type of output. - name: Build and push image to local TAR file + if: ${{ matrix.arch == 'linux/amd64'}} uses: docker/build-push-action@v5 with: build-contexts: | ${{ inputs.dockerfile_additional_contexts }} context: ${{ inputs.dockerfile_context }} file: ${{ inputs.dockerfile_path }} + # Tell DSpace's Docker files to use the build registry instead of DockerHub + build-args: + DOCKER_REGISTRY=${{ env.DOCKER_BUILD_REGISTRY }} platforms: ${{ matrix.arch }} tags: ${{ steps.meta_build.outputs.tags }} labels: ${{ steps.meta_build.outputs.labels }} @@ -233,7 +227,9 @@ jobs: outputs: type=docker,dest=/tmp/${{ inputs.build_id }}.tar # Upload the local docker image (in TAR file) to a build Artifact + # This step is only done for AMD64, as that's the only image we use in our automated testing (at this time). - name: Upload local image TAR to artifact + if: ${{ matrix.arch == 'linux/amd64'}} uses: actions/upload-artifact@v4 with: name: docker-image-${{ inputs.build_id }}-${{ env.ARCH_NAME }} @@ -241,10 +237,12 @@ jobs: if-no-files-found: error retention-days: 1 - # Merge Docker digests (from various architectures) into a manifest. - # This runs after all Docker builds complete above, and it tells hub.docker.com - # that these builds should be all included in the manifest for this tag. - # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) + ########################################################################################## + # Merge Docker digests (from various architectures) into a single manifest. + # This runs after all Docker builds complete above. The purpose is to include all builds + # under a single manifest for this tag. + # (e.g. both linux/amd64 and linux/arm64 should be listed under the same tagged Docker image) + ########################################################################################## docker-build_manifest: # Only run if this is NOT a PR if: ${{ github.event_name != 'pull_request' }} @@ -260,11 +258,12 @@ jobs: pattern: digests-${{ inputs.build_id }}-* merge-multiple: true - - name: Login to Docker Hub + - name: Login to ${{ env.DOCKER_BUILD_REGISTRY }} uses: docker/login-action@v3 with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + registry: ${{ env.DOCKER_BUILD_REGISTRY }} + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -273,16 +272,88 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.IMAGE_NAME }} + images: ${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }} tags: ${{ env.IMAGE_TAGS }} flavor: ${{ env.TAGS_FLAVOR }} - - name: Create manifest list from digests and push + - name: Create manifest list from digests and push to ${{ env.DOCKER_BUILD_REGISTRY }} working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *) + $(printf '${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) + + - name: Inspect manifest in ${{ env.DOCKER_BUILD_REGISTRY }} + run: | + docker buildx imagetools inspect ${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} + + ########################################################################################## + # Copy images / manifest to DockerHub. + # This MUST run after *both* images (AMD64 and ARM64) are built and uploaded to GitHub + # Container Registry (GHCR). Attempting to run this in parallel to GHCR builds can result + # in a race condition...i.e. the copy to DockerHub may fail if GHCR image has been updated + # at the moment when the copy occurs. + ########################################################################################## + docker-copy_to_dockerhub: + # Only run if this is NOT a PR + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + - docker-build_manifest + + steps: + # 'regctl' is used to more easily copy the image to DockerHub and obtain the digest from DockerHub + # See https://github.com/regclient/regclient/blob/main/docs/regctl.md + - name: Install regctl for Docker registry tools + uses: regclient/actions/regctl-installer@main + with: + release: 'v0.8.0' - - name: Inspect image + # This recreates Docker tags for DockerHub + - name: Add Docker metadata for image + id: meta_dockerhub + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + tags: ${{ env.IMAGE_TAGS }} + flavor: ${{ env.TAGS_FLAVOR }} + + # Login to source registry first, as this is where we are copying *from* + - name: Login to ${{ env.DOCKER_BUILD_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_BUILD_REGISTRY }} + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Login to DockerHub, since this is where we are copying *to* + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + # Copy the image from source to DockerHub + - name: Copy image from ${{ env.DOCKER_BUILD_REGISTRY }} to docker.io + run: | + regctl image copy ${{ env.DOCKER_BUILD_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta_dockerhub.outputs.version }} docker.io/${{ env.IMAGE_NAME }}:${{ steps.meta_dockerhub.outputs.version }} + + #-------------------------------------------------------------------- + # Finally, check whether demo.dspace.org or sandbox.dspace.org need + # to be redeployed based on these new DockerHub images. + #-------------------------------------------------------------------- + # If this build is for the branch that Sandbox uses and passed in a REDEPLOY_SANDBOX_URL secret, + # Then redeploy https://sandbox.dspace.org + - name: Redeploy sandbox.dspace.org (based on main branch) + if: | + env.REDEPLOY_SANDBOX_URL != '' && + github.ref_name == env.DEPLOY_SANDBOX_BRANCH + run: | + curl -X POST $REDEPLOY_SANDBOX_URL + # If this build is for the branch that Demo uses and passed in a REDEPLOY_DEMO_URL secret, + # Then redeploy https://demo.dspace.org + - name: Redeploy demo.dspace.org (based on maintenance branch) + if: | + env.REDEPLOY_DEMO_URL != '' && + github.ref_name == env.DEPLOY_DEMO_BRANCH run: | - docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} + curl -X POST $REDEPLOY_DEMO_URL \ No newline at end of file From 296c9a12f489d779c15bf07fd8c38fac6bc6d233 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 16 Dec 2024 12:05:41 -0600 Subject: [PATCH 225/632] PRs must also login to ghcr.io in order to read private images for the build process --- .github/workflows/reusable-docker-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index 36546af3a5da..3b74f250b539 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -114,9 +114,9 @@ jobs: uses: actions/checkout@v4 # https://github.com/docker/login-action + # NOTE: This login occurs for BOTH non-PRs or PRs. PRs *must* also login to access private images from GHCR + # during the build process - name: Login to ${{ env.DOCKER_BUILD_REGISTRY }} - # Only login if not a PR, as PRs only trigger a Docker build and not a push - if: ${{ ! matrix.isPr }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_BUILD_REGISTRY }} From a27f1ed1757b193cf6f831a0fd27585b655bacc2 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 16 Dec 2024 12:28:16 -0600 Subject: [PATCH 226/632] Ensure "docker-deploy" job also uses ghcr.io by default. --- .github/workflows/docker.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index fceea6403d2a..815aec5cf6b4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -176,6 +176,9 @@ jobs: # Else, just use the branch name. # NOTE: DSPACE_VER is used because our docker compose scripts default to using the "-test" image. DSPACE_VER: ${{ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == github.event.repository.default_branch && 'latest') || (github.event_name == 'pull_request' && github.event.pull_request.base.ref) || (github.ref_name == github.event.repository.default_branch && 'latest') || github.ref_name }} + # Docker Registry to use for Docker compose scripts below. + # We use GitHub's Container Registry to avoid aggressive rate limits at DockerHub. + DOCKER_REGISTRY: ghcr.io steps: # Checkout our codebase (to get access to Docker Compose scripts) - name: Checkout codebase From c6ecdaf29376409bcea60abb4b634de7d0294c45 Mon Sep 17 00:00:00 2001 From: autavares-dev Date: Wed, 7 Aug 2024 16:34:38 -0300 Subject: [PATCH 227/632] Changes Group2GroupCache computation (cherry picked from commit 2bcea0f860db9a3dc915119a5e111d057d2b2936) --- .../org/dspace/eperson/Group2GroupCache.java | 3 +- .../org/dspace/eperson/GroupServiceImpl.java | 72 +++++++++--------- .../eperson/dao/Group2GroupCacheDAO.java | 74 +++++++++++++++++-- .../dao/impl/Group2GroupCacheDAOImpl.java | 34 +++++++++ 4 files changed, 143 insertions(+), 40 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java b/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java index a1c12371f5ff..0c6ea58b1977 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java +++ b/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java @@ -15,6 +15,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import org.dspace.core.HibernateProxyHelper; /** @@ -23,7 +24,7 @@ * @author kevinvandevelde at atmire.com */ @Entity -@Table(name = "group2groupcache") +@Table(name = "group2groupcache", uniqueConstraints = { @UniqueConstraint(columnNames = {"parent_id", "child_id"}) }) public class Group2GroupCache implements Serializable { @Id diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java index 3fb20e2f1e6f..b52f17a5c692 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java @@ -20,6 +20,7 @@ import java.util.UUID; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.SetUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; @@ -673,15 +674,14 @@ protected boolean isEPersonInGroup(Context context, Group group, EPerson ePerson /** - * Regenerate the group cache AKA the group2groupcache table in the database - - * meant to be called when a group is added or removed from another group + * Returns a set with pairs of parent and child group UUIDs, representing the new cache table rows. * - * @param context The relevant DSpace Context. - * @param flushQueries flushQueries Flush all pending queries + * @param context The relevant DSpace Context. + * @param flushQueries flushQueries Flush all pending queries + * @return Pairs of parent and child group UUID of the new cache. * @throws SQLException An exception that provides information on a database access error or other errors. */ - protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { - + private Set> computeNewCache(Context context, boolean flushQueries) throws SQLException { Map> parents = new HashMap<>(); List> group2groupResults = groupDAO.getGroup2GroupResults(context, flushQueries); @@ -689,19 +689,8 @@ protected void rethinkGroupCache(Context context, boolean flushQueries) throws S UUID parent = group2groupResult.getLeft(); UUID child = group2groupResult.getRight(); - // if parent doesn't have an entry, create one - if (!parents.containsKey(parent)) { - Set children = new HashSet<>(); - - // add child id to the list - children.add(child); - parents.put(parent, children); - } else { - // parent has an entry, now add the child to the parent's record - // of children - Set children = parents.get(parent); - children.add(child); - } + parents.putIfAbsent(parent, new HashSet<>()); + parents.get(parent).add(child); } // now parents is a hash of all of the IDs of groups that are parents @@ -714,27 +703,42 @@ protected void rethinkGroupCache(Context context, boolean flushQueries) throws S parent.getValue().addAll(myChildren); } - // empty out group2groupcache table - group2GroupCacheDAO.deleteAll(context); - - // write out new one + // write out new cache IN MEMORY ONLY and returns it + Set> newCache = new HashSet<>(); for (Map.Entry> parent : parents.entrySet()) { UUID key = parent.getKey(); - for (UUID child : parent.getValue()) { + newCache.add(Pair.of(key, child)); + } + } + return newCache; + } - Group parentGroup = find(context, key); - Group childGroup = find(context, child); + /** + * Regenerate the group cache AKA the group2groupcache table in the database - + * meant to be called when a group is added or removed from another group + * + * @param context The relevant DSpace Context. + * @param flushQueries flushQueries Flush all pending queries + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { + // current cache in the database + var oldCache = group2GroupCacheDAO.getCache(context); - if (parentGroup != null && childGroup != null && group2GroupCacheDAO - .find(context, parentGroup, childGroup) == null) { - Group2GroupCache group2GroupCache = group2GroupCacheDAO.create(context, new Group2GroupCache()); - group2GroupCache.setParent(parentGroup); - group2GroupCache.setChild(childGroup); - group2GroupCacheDAO.save(context, group2GroupCache); - } - } + // correct cache, computed from the Group table + var newCache = computeNewCache(context, flushQueries); + + var toDelete = SetUtils.difference(oldCache, newCache); + var toCreate = SetUtils.difference(newCache, oldCache); + + for (var pair : toDelete ) { + group2GroupCacheDAO.deleteFromCache(context, pair.getLeft(), pair.getRight()); + } + + for (var pair : toCreate ) { + group2GroupCacheDAO.addToCache(context, pair.getLeft(), pair.getRight()); } } diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java b/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java index 7db569a59e2b..d41d52c7e618 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java @@ -9,7 +9,10 @@ import java.sql.SQLException; import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.apache.commons.lang3.tuple.Pair; import org.dspace.core.Context; import org.dspace.core.GenericDAO; import org.dspace.eperson.Group; @@ -25,13 +28,74 @@ */ public interface Group2GroupCacheDAO extends GenericDAO { - public List findByParent(Context context, Group group) throws SQLException; + /** + * Returns the current cache table as a set of UUID pairs. + * @param context The relevant DSpace Context. + * @return Set of UUID pairs, where the first element is the parent UUID and the second one is the child UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Set> getCache(Context context) throws SQLException; - public List findByChildren(Context context, Iterable groups) throws SQLException; + /** + * Returns all cache entities that are children of a given parent Group entity. + * @param context The relevant DSpace Context. + * @param group Parent group to perform the search. + * @return List of cached groups that are children of the parent group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + List findByParent(Context context, Group group) throws SQLException; - public Group2GroupCache findByParentAndChild(Context context, Group parent, Group child) throws SQLException; + /** + * Returns all cache entities that are parents of at least one group from a children groups list. + * @param context The relevant DSpace Context. + * @param groups Children groups to perform the search. + * @return List of cached groups that are parents of at least one group from the children groups list. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + List findByChildren(Context context, Iterable groups) throws SQLException; - public Group2GroupCache find(Context context, Group parent, Group child) throws SQLException; + /** + * Returns the cache entity given specific parent and child groups. + * @param context The relevant DSpace Context. + * @param parent Parent group. + * @param child Child gruoup. + * @return Cached group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Group2GroupCache findByParentAndChild(Context context, Group parent, Group child) throws SQLException; - public void deleteAll(Context context) throws SQLException; + /** + * Returns the cache entity given specific parent and child groups. + * @param context The relevant DSpace Context. + * @param parent Parent group. + * @param child Child gruoup. + * @return Cached group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Group2GroupCache find(Context context, Group parent, Group child) throws SQLException; + + /** + * Completely deletes the current cache table. + * @param context The relevant DSpace Context. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void deleteAll(Context context) throws SQLException; + + /** + * Deletes a specific cache row given parent and child groups UUIDs. + * @param context The relevant DSpace Context. + * @param parent Parent group UUID. + * @param child Child group UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void deleteFromCache(Context context, UUID parent, UUID child) throws SQLException; + + /** + * Adds a single row to the cache table given parent and child groups UUIDs. + * @param context The relevant DSpace Context. + * @param parent Parent group UUID. + * @param child Child group UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void addToCache(Context context, UUID parent, UUID child) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java index 1cd359188ca3..adbd776ffab6 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java @@ -8,14 +8,18 @@ package org.dspace.eperson.dao.impl; import java.sql.SQLException; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; +import java.util.UUID; import jakarta.persistence.Query; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; +import org.apache.commons.lang3.tuple.Pair; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.Group; @@ -35,6 +39,16 @@ protected Group2GroupCacheDAOImpl() { super(); } + @Override + public Set> getCache(Context context) throws SQLException { + Query query = createQuery( + context, + "SELECT new org.apache.commons.lang3.tuple.ImmutablePair(g.parent.id, g.child.id) FROM Group2GroupCache g" + ); + List> results = query.getResultList(); + return new HashSet>(results); + } + @Override public List findByParent(Context context, Group group) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); @@ -90,4 +104,24 @@ public Group2GroupCache find(Context context, Group parent, Group child) throws public void deleteAll(Context context) throws SQLException { createQuery(context, "delete from Group2GroupCache").executeUpdate(); } + + @Override + public void deleteFromCache(Context context, UUID parent, UUID child) throws SQLException { + Query query = getHibernateSession(context).createNativeQuery( + "delete from group2groupcache g WHERE g.parent_id = :parent AND g.child_id = :child" + ); + query.setParameter("parent", parent); + query.setParameter("child", child); + query.executeUpdate(); + } + + @Override + public void addToCache(Context context, UUID parent, UUID child) throws SQLException { + Query query = getHibernateSession(context).createNativeQuery( + "insert into group2groupcache (parent_id, child_id) VALUES (:parent, :child)" + ); + query.setParameter("parent", parent); + query.setParameter("child", child); + query.executeUpdate(); + } } From 5b8f7077b1004e550435f40ff690fdc82eb85921 Mon Sep 17 00:00:00 2001 From: autavares-dev Date: Thu, 8 Aug 2024 15:52:03 -0300 Subject: [PATCH 228/632] Refactor 'var' variables to explicit types (cherry picked from commit 743b7049cfeeabfd414c38526bcdbf2e52426739) --- .../java/org/dspace/eperson/GroupServiceImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java index b52f17a5c692..4cec4c9c0d93 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java @@ -725,19 +725,19 @@ private Set> computeNewCache(Context context, boolean flushQuer */ protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { // current cache in the database - var oldCache = group2GroupCacheDAO.getCache(context); + Set> oldCache = group2GroupCacheDAO.getCache(context); // correct cache, computed from the Group table - var newCache = computeNewCache(context, flushQueries); + Set> newCache = computeNewCache(context, flushQueries); - var toDelete = SetUtils.difference(oldCache, newCache); - var toCreate = SetUtils.difference(newCache, oldCache); + SetUtils.SetView> toDelete = SetUtils.difference(oldCache, newCache); + SetUtils.SetView> toCreate = SetUtils.difference(newCache, oldCache); - for (var pair : toDelete ) { + for (Pair pair : toDelete ) { group2GroupCacheDAO.deleteFromCache(context, pair.getLeft(), pair.getRight()); } - for (var pair : toCreate ) { + for (Pair pair : toCreate ) { group2GroupCacheDAO.addToCache(context, pair.getLeft(), pair.getRight()); } } From 64cb3bda0034d8e3051c31290a3eeea8a560d939 Mon Sep 17 00:00:00 2001 From: autavares-dev Date: Wed, 7 Aug 2024 16:34:38 -0300 Subject: [PATCH 229/632] Changes Group2GroupCache computation --- .../org/dspace/eperson/Group2GroupCache.java | 3 +- .../org/dspace/eperson/GroupServiceImpl.java | 72 +++++++++--------- .../eperson/dao/Group2GroupCacheDAO.java | 74 +++++++++++++++++-- .../dao/impl/Group2GroupCacheDAOImpl.java | 34 +++++++++ 4 files changed, 143 insertions(+), 40 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java b/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java index 09bdf34d4cad..58781cd402fa 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java +++ b/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java @@ -14,6 +14,7 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; +import javax.persistence.UniqueConstraint; import org.hibernate.proxy.HibernateProxyHelper; @@ -23,7 +24,7 @@ * @author kevinvandevelde at atmire.com */ @Entity -@Table(name = "group2groupcache") +@Table(name = "group2groupcache", uniqueConstraints = { @UniqueConstraint(columnNames = {"parent_id", "child_id"}) }) public class Group2GroupCache implements Serializable { @Id diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java index 3fb20e2f1e6f..b52f17a5c692 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java @@ -20,6 +20,7 @@ import java.util.UUID; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.SetUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; @@ -673,15 +674,14 @@ protected boolean isEPersonInGroup(Context context, Group group, EPerson ePerson /** - * Regenerate the group cache AKA the group2groupcache table in the database - - * meant to be called when a group is added or removed from another group + * Returns a set with pairs of parent and child group UUIDs, representing the new cache table rows. * - * @param context The relevant DSpace Context. - * @param flushQueries flushQueries Flush all pending queries + * @param context The relevant DSpace Context. + * @param flushQueries flushQueries Flush all pending queries + * @return Pairs of parent and child group UUID of the new cache. * @throws SQLException An exception that provides information on a database access error or other errors. */ - protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { - + private Set> computeNewCache(Context context, boolean flushQueries) throws SQLException { Map> parents = new HashMap<>(); List> group2groupResults = groupDAO.getGroup2GroupResults(context, flushQueries); @@ -689,19 +689,8 @@ protected void rethinkGroupCache(Context context, boolean flushQueries) throws S UUID parent = group2groupResult.getLeft(); UUID child = group2groupResult.getRight(); - // if parent doesn't have an entry, create one - if (!parents.containsKey(parent)) { - Set children = new HashSet<>(); - - // add child id to the list - children.add(child); - parents.put(parent, children); - } else { - // parent has an entry, now add the child to the parent's record - // of children - Set children = parents.get(parent); - children.add(child); - } + parents.putIfAbsent(parent, new HashSet<>()); + parents.get(parent).add(child); } // now parents is a hash of all of the IDs of groups that are parents @@ -714,27 +703,42 @@ protected void rethinkGroupCache(Context context, boolean flushQueries) throws S parent.getValue().addAll(myChildren); } - // empty out group2groupcache table - group2GroupCacheDAO.deleteAll(context); - - // write out new one + // write out new cache IN MEMORY ONLY and returns it + Set> newCache = new HashSet<>(); for (Map.Entry> parent : parents.entrySet()) { UUID key = parent.getKey(); - for (UUID child : parent.getValue()) { + newCache.add(Pair.of(key, child)); + } + } + return newCache; + } - Group parentGroup = find(context, key); - Group childGroup = find(context, child); + /** + * Regenerate the group cache AKA the group2groupcache table in the database - + * meant to be called when a group is added or removed from another group + * + * @param context The relevant DSpace Context. + * @param flushQueries flushQueries Flush all pending queries + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { + // current cache in the database + var oldCache = group2GroupCacheDAO.getCache(context); - if (parentGroup != null && childGroup != null && group2GroupCacheDAO - .find(context, parentGroup, childGroup) == null) { - Group2GroupCache group2GroupCache = group2GroupCacheDAO.create(context, new Group2GroupCache()); - group2GroupCache.setParent(parentGroup); - group2GroupCache.setChild(childGroup); - group2GroupCacheDAO.save(context, group2GroupCache); - } - } + // correct cache, computed from the Group table + var newCache = computeNewCache(context, flushQueries); + + var toDelete = SetUtils.difference(oldCache, newCache); + var toCreate = SetUtils.difference(newCache, oldCache); + + for (var pair : toDelete ) { + group2GroupCacheDAO.deleteFromCache(context, pair.getLeft(), pair.getRight()); + } + + for (var pair : toCreate ) { + group2GroupCacheDAO.addToCache(context, pair.getLeft(), pair.getRight()); } } diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java b/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java index 7db569a59e2b..d41d52c7e618 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java @@ -9,7 +9,10 @@ import java.sql.SQLException; import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.apache.commons.lang3.tuple.Pair; import org.dspace.core.Context; import org.dspace.core.GenericDAO; import org.dspace.eperson.Group; @@ -25,13 +28,74 @@ */ public interface Group2GroupCacheDAO extends GenericDAO { - public List findByParent(Context context, Group group) throws SQLException; + /** + * Returns the current cache table as a set of UUID pairs. + * @param context The relevant DSpace Context. + * @return Set of UUID pairs, where the first element is the parent UUID and the second one is the child UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Set> getCache(Context context) throws SQLException; - public List findByChildren(Context context, Iterable groups) throws SQLException; + /** + * Returns all cache entities that are children of a given parent Group entity. + * @param context The relevant DSpace Context. + * @param group Parent group to perform the search. + * @return List of cached groups that are children of the parent group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + List findByParent(Context context, Group group) throws SQLException; - public Group2GroupCache findByParentAndChild(Context context, Group parent, Group child) throws SQLException; + /** + * Returns all cache entities that are parents of at least one group from a children groups list. + * @param context The relevant DSpace Context. + * @param groups Children groups to perform the search. + * @return List of cached groups that are parents of at least one group from the children groups list. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + List findByChildren(Context context, Iterable groups) throws SQLException; - public Group2GroupCache find(Context context, Group parent, Group child) throws SQLException; + /** + * Returns the cache entity given specific parent and child groups. + * @param context The relevant DSpace Context. + * @param parent Parent group. + * @param child Child gruoup. + * @return Cached group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Group2GroupCache findByParentAndChild(Context context, Group parent, Group child) throws SQLException; - public void deleteAll(Context context) throws SQLException; + /** + * Returns the cache entity given specific parent and child groups. + * @param context The relevant DSpace Context. + * @param parent Parent group. + * @param child Child gruoup. + * @return Cached group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Group2GroupCache find(Context context, Group parent, Group child) throws SQLException; + + /** + * Completely deletes the current cache table. + * @param context The relevant DSpace Context. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void deleteAll(Context context) throws SQLException; + + /** + * Deletes a specific cache row given parent and child groups UUIDs. + * @param context The relevant DSpace Context. + * @param parent Parent group UUID. + * @param child Child group UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void deleteFromCache(Context context, UUID parent, UUID child) throws SQLException; + + /** + * Adds a single row to the cache table given parent and child groups UUIDs. + * @param context The relevant DSpace Context. + * @param parent Parent group UUID. + * @param child Child group UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void addToCache(Context context, UUID parent, UUID child) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java index 83fb48aaf03d..42ca2bb5d48c 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java @@ -8,14 +8,18 @@ package org.dspace.eperson.dao.impl; import java.sql.SQLException; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; +import java.util.UUID; import javax.persistence.Query; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import org.apache.commons.lang3.tuple.Pair; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.Group; @@ -35,6 +39,16 @@ protected Group2GroupCacheDAOImpl() { super(); } + @Override + public Set> getCache(Context context) throws SQLException { + Query query = createQuery( + context, + "SELECT new org.apache.commons.lang3.tuple.ImmutablePair(g.parent.id, g.child.id) FROM Group2GroupCache g" + ); + List> results = query.getResultList(); + return new HashSet>(results); + } + @Override public List findByParent(Context context, Group group) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); @@ -90,4 +104,24 @@ public Group2GroupCache find(Context context, Group parent, Group child) throws public void deleteAll(Context context) throws SQLException { createQuery(context, "delete from Group2GroupCache").executeUpdate(); } + + @Override + public void deleteFromCache(Context context, UUID parent, UUID child) throws SQLException { + Query query = getHibernateSession(context).createNativeQuery( + "delete from group2groupcache g WHERE g.parent_id = :parent AND g.child_id = :child" + ); + query.setParameter("parent", parent); + query.setParameter("child", child); + query.executeUpdate(); + } + + @Override + public void addToCache(Context context, UUID parent, UUID child) throws SQLException { + Query query = getHibernateSession(context).createNativeQuery( + "insert into group2groupcache (parent_id, child_id) VALUES (:parent, :child)" + ); + query.setParameter("parent", parent); + query.setParameter("child", child); + query.executeUpdate(); + } } From 05bac14716e1b011ab56abc7b9d662e9d689e546 Mon Sep 17 00:00:00 2001 From: autavares-dev Date: Thu, 8 Aug 2024 15:52:03 -0300 Subject: [PATCH 230/632] Refactor 'var' variables to explicit types --- .../java/org/dspace/eperson/GroupServiceImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java index b52f17a5c692..4cec4c9c0d93 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java @@ -725,19 +725,19 @@ private Set> computeNewCache(Context context, boolean flushQuer */ protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { // current cache in the database - var oldCache = group2GroupCacheDAO.getCache(context); + Set> oldCache = group2GroupCacheDAO.getCache(context); // correct cache, computed from the Group table - var newCache = computeNewCache(context, flushQueries); + Set> newCache = computeNewCache(context, flushQueries); - var toDelete = SetUtils.difference(oldCache, newCache); - var toCreate = SetUtils.difference(newCache, oldCache); + SetUtils.SetView> toDelete = SetUtils.difference(oldCache, newCache); + SetUtils.SetView> toCreate = SetUtils.difference(newCache, oldCache); - for (var pair : toDelete ) { + for (Pair pair : toDelete ) { group2GroupCacheDAO.deleteFromCache(context, pair.getLeft(), pair.getRight()); } - for (var pair : toCreate ) { + for (Pair pair : toCreate ) { group2GroupCacheDAO.addToCache(context, pair.getLeft(), pair.getRight()); } } From aa027aefae2e39558273fcdbd511c288f8b0def3 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 17 Dec 2024 13:11:43 -0600 Subject: [PATCH 231/632] Improve Apache Ant download process. Switch to using curl so that we can retry the request if it initially fails. (cherry picked from commit e236634a4c758a6c0d81e929b2f36d49e81b0835) --- Dockerfile | 10 ++++------ Dockerfile.cli | 10 ++++------ Dockerfile.test | 10 ++++------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index ff35f2a2e3a7..102f00abe1f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,14 +42,12 @@ WORKDIR /dspace-src ENV ANT_VERSION=1.10.13 ENV ANT_HOME=/tmp/ant-$ANT_VERSION ENV PATH=$ANT_HOME/bin:$PATH -# Need wget to install ant -RUN apt-get update \ - && apt-get install -y --no-install-recommends wget \ - && apt-get purge -y --auto-remove \ - && rm -rf /var/lib/apt/lists/* # Download and install 'ant' RUN mkdir $ANT_HOME && \ - wget -qO- "https://archive.apache.org/dist/ant/binaries/apache-ant-$ANT_VERSION-bin.tar.gz" | tar -zx --strip-components=1 -C $ANT_HOME + curl --silent --show-error --location --fail --retry 5 --output /tmp/apache-ant.tar.gz \ + https://archive.apache.org/dist/ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.gz && \ + tar -zx --strip-components=1 -f /tmp/apache-ant.tar.gz -C $ANT_HOME && \ + rm /tmp/apache-ant.tar.gz # Run necessary 'ant' deploy scripts RUN ant init_installation update_configs update_code update_webapps diff --git a/Dockerfile.cli b/Dockerfile.cli index be03e8922b2c..e208e3d92145 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -38,14 +38,12 @@ WORKDIR /dspace-src ENV ANT_VERSION=1.10.13 ENV ANT_HOME=/tmp/ant-$ANT_VERSION ENV PATH=$ANT_HOME/bin:$PATH -# Need wget to install ant -RUN apt-get update \ - && apt-get install -y --no-install-recommends wget \ - && apt-get purge -y --auto-remove \ - && rm -rf /var/lib/apt/lists/* # Download and install 'ant' RUN mkdir $ANT_HOME && \ - wget -qO- "https://archive.apache.org/dist/ant/binaries/apache-ant-$ANT_VERSION-bin.tar.gz" | tar -zx --strip-components=1 -C $ANT_HOME + curl --silent --show-error --location --fail --retry 5 --output /tmp/apache-ant.tar.gz \ + https://archive.apache.org/dist/ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.gz && \ + tar -zx --strip-components=1 -f /tmp/apache-ant.tar.gz -C $ANT_HOME && \ + rm /tmp/apache-ant.tar.gz # Run necessary 'ant' deploy scripts RUN ant init_installation update_configs update_code diff --git a/Dockerfile.test b/Dockerfile.test index 08b6b3018b80..cc73c655b637 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -41,14 +41,12 @@ WORKDIR /dspace-src ENV ANT_VERSION=1.10.12 ENV ANT_HOME=/tmp/ant-$ANT_VERSION ENV PATH=$ANT_HOME/bin:$PATH -# Need wget to install ant -RUN apt-get update \ - && apt-get install -y --no-install-recommends wget \ - && apt-get purge -y --auto-remove \ - && rm -rf /var/lib/apt/lists/* # Download and install 'ant' RUN mkdir $ANT_HOME && \ - wget -qO- "https://archive.apache.org/dist/ant/binaries/apache-ant-$ANT_VERSION-bin.tar.gz" | tar -zx --strip-components=1 -C $ANT_HOME + curl --silent --show-error --location --fail --retry 5 --output /tmp/apache-ant.tar.gz \ + https://archive.apache.org/dist/ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.gz && \ + tar -zx --strip-components=1 -f /tmp/apache-ant.tar.gz -C $ANT_HOME && \ + rm /tmp/apache-ant.tar.gz # Run necessary 'ant' deploy scripts RUN ant init_installation update_configs update_code update_webapps From 58af9fd224ba37a8f3a9c8b354c04d772d6f3ee2 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 17 Dec 2024 14:13:21 -0600 Subject: [PATCH 232/632] Significantly speed up build of dspace-dependencies by only copying over POM files (cherry picked from commit 6d7a3fcb725bbb5e42790ba5c57292477f2f3f01) --- Dockerfile.dependencies | 58 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/Dockerfile.dependencies b/Dockerfile.dependencies index 794dfa9a66a8..d3ca9d5e3c87 100644 --- a/Dockerfile.dependencies +++ b/Dockerfile.dependencies @@ -6,7 +6,7 @@ # To build with JDK17, use "--build-arg JDK_VERSION=17" ARG JDK_VERSION=11 -# Step 1 - Run Maven Build +# Step 1 - Download all Dependencies FROM docker.io/maven:3-eclipse-temurin-${JDK_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app @@ -19,16 +19,60 @@ RUN chown -Rv dspace: /app # Switch to dspace user & run below commands as that user USER dspace -# Copy the DSpace source code (from local machine) into the workdir (excluding .dockerignore contents) -ADD --chown=dspace . /app/ +# This next part may look odd, but it speeds up the build of this image *significantly*. +# Copy ONLY the POMs to this image (from local machine). This will allow us to download all dependencies *without* +# performing any code compilation steps. + +# Parent POM +ADD --chown=dspace pom.xml /app/ +RUN mkdir -p /app/dspace + +# 'dspace' module POM. Includes 'additions' ONLY, as it's the only submodule that is required to exist. +ADD --chown=dspace dspace/pom.xml /app/dspace/ +RUN mkdir -p /app/dspace/modules/ +ADD --chown=dspace dspace/modules/pom.xml /app/dspace/modules/ +RUN mkdir -p /app/dspace/modules/additions +ADD --chown=dspace dspace/modules/additions/pom.xml /app/dspace/modules/additions/ + +# 'dspace-api' module POM +RUN mkdir -p /app/dspace-api +ADD --chown=dspace dspace-api/pom.xml /app/dspace-api/ + +# 'dspace-iiif' module POM +RUN mkdir -p /app/dspace-iiif +ADD --chown=dspace dspace-iiif/pom.xml /app/dspace-iiif/ + +# 'dspace-oai' module POM +RUN mkdir -p /app/dspace-oai +ADD --chown=dspace dspace-oai/pom.xml /app/dspace-oai/ + +# 'dspace-rdf' module POM +RUN mkdir -p /app/dspace-rdf +ADD --chown=dspace dspace-rdf/pom.xml /app/dspace-rdf/ + +# 'dspace-server-webapp' module POM +RUN mkdir -p /app/dspace-server-webapp +ADD --chown=dspace dspace-server-webapp/pom.xml /app/dspace-server-webapp/ + +# 'dspace-services' module POM +RUN mkdir -p /app/dspace-services +ADD --chown=dspace dspace-services/pom.xml /app/dspace-services/ + +# 'dspace-sword' module POM +RUN mkdir -p /app/dspace-sword +ADD --chown=dspace dspace-sword/pom.xml /app/dspace-sword/ + +# 'dspace-swordv2' module POM +RUN mkdir -p /app/dspace-swordv2 +ADD --chown=dspace dspace-swordv2/pom.xml /app/dspace-swordv2/ # Trigger the installation of all maven dependencies (hide download progress messages) # Maven flags here ensure that we skip final assembly, skip building test environment and skip all code verification checks. -# These flags speed up this installation as much as reasonably possible. -ENV MAVEN_FLAGS="-P-assembly -P-test-environment -Denforcer.skip=true -Dcheckstyle.skip=true -Dlicense.skip=true -Dxml.skip=true" -RUN mvn --no-transfer-progress install ${MAVEN_FLAGS} +# These flags speed up this installation and skip tasks we cannot perform as we don't have the full source code. +ENV MAVEN_FLAGS="-P-assembly -P-test-environment -Denforcer.skip=true -Dcheckstyle.skip=true -Dlicense.skip=true -Dxjc.skip=true -Dxml.skip=true" +RUN mvn --no-transfer-progress verify ${MAVEN_FLAGS} -# Clear the contents of the /app directory (including all maven builds), so no artifacts remain. +# Clear the contents of the /app directory (including all maven target folders), so no artifacts remain. # This ensures when dspace:dspace is built, it will use the Maven local cache (~/.m2) for dependencies USER root RUN rm -rf /app/* From 3c4fd4274aebf882cf1233a8d5f2eb8a7b1e8e24 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 17 Dec 2024 13:11:43 -0600 Subject: [PATCH 233/632] Improve Apache Ant download process. Switch to using curl so that we can retry the request if it initially fails. (cherry picked from commit e236634a4c758a6c0d81e929b2f36d49e81b0835) --- Dockerfile | 10 ++++------ Dockerfile.cli | 10 ++++------ Dockerfile.test | 10 ++++------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0b844a1b26c2..eb90299ccd7d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,14 +44,12 @@ WORKDIR /dspace-src ENV ANT_VERSION=1.10.13 ENV ANT_HOME=/tmp/ant-$ANT_VERSION ENV PATH=$ANT_HOME/bin:$PATH -# Need wget to install ant -RUN apt-get update \ - && apt-get install -y --no-install-recommends wget \ - && apt-get purge -y --auto-remove \ - && rm -rf /var/lib/apt/lists/* # Download and install 'ant' RUN mkdir $ANT_HOME && \ - wget -qO- "https://archive.apache.org/dist/ant/binaries/apache-ant-$ANT_VERSION-bin.tar.gz" | tar -zx --strip-components=1 -C $ANT_HOME + curl --silent --show-error --location --fail --retry 5 --output /tmp/apache-ant.tar.gz \ + https://archive.apache.org/dist/ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.gz && \ + tar -zx --strip-components=1 -f /tmp/apache-ant.tar.gz -C $ANT_HOME && \ + rm /tmp/apache-ant.tar.gz # Run necessary 'ant' deploy scripts RUN ant init_installation update_configs update_code update_webapps diff --git a/Dockerfile.cli b/Dockerfile.cli index b0b056dfc99e..1f08357b3bba 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -38,14 +38,12 @@ WORKDIR /dspace-src ENV ANT_VERSION=1.10.13 ENV ANT_HOME=/tmp/ant-$ANT_VERSION ENV PATH=$ANT_HOME/bin:$PATH -# Need wget to install ant -RUN apt-get update \ - && apt-get install -y --no-install-recommends wget \ - && apt-get purge -y --auto-remove \ - && rm -rf /var/lib/apt/lists/* # Download and install 'ant' RUN mkdir $ANT_HOME && \ - wget -qO- "https://archive.apache.org/dist/ant/binaries/apache-ant-$ANT_VERSION-bin.tar.gz" | tar -zx --strip-components=1 -C $ANT_HOME + curl --silent --show-error --location --fail --retry 5 --output /tmp/apache-ant.tar.gz \ + https://archive.apache.org/dist/ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.gz && \ + tar -zx --strip-components=1 -f /tmp/apache-ant.tar.gz -C $ANT_HOME && \ + rm /tmp/apache-ant.tar.gz # Run necessary 'ant' deploy scripts RUN ant init_installation update_configs update_code diff --git a/Dockerfile.test b/Dockerfile.test index 828d61e74708..1c36b31b66bb 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -43,14 +43,12 @@ WORKDIR /dspace-src ENV ANT_VERSION=1.10.12 ENV ANT_HOME=/tmp/ant-$ANT_VERSION ENV PATH=$ANT_HOME/bin:$PATH -# Need wget to install ant -RUN apt-get update \ - && apt-get install -y --no-install-recommends wget \ - && apt-get purge -y --auto-remove \ - && rm -rf /var/lib/apt/lists/* # Download and install 'ant' RUN mkdir $ANT_HOME && \ - wget -qO- "https://archive.apache.org/dist/ant/binaries/apache-ant-$ANT_VERSION-bin.tar.gz" | tar -zx --strip-components=1 -C $ANT_HOME + curl --silent --show-error --location --fail --retry 5 --output /tmp/apache-ant.tar.gz \ + https://archive.apache.org/dist/ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.gz && \ + tar -zx --strip-components=1 -f /tmp/apache-ant.tar.gz -C $ANT_HOME && \ + rm /tmp/apache-ant.tar.gz # Run necessary 'ant' deploy scripts RUN ant init_installation update_configs update_code update_webapps From 6792b8274de485c27801afb382ae9840f68081ec Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 17 Dec 2024 14:13:21 -0600 Subject: [PATCH 234/632] Significantly speed up build of dspace-dependencies by only copying over POM files (cherry picked from commit 6d7a3fcb725bbb5e42790ba5c57292477f2f3f01) --- Dockerfile.dependencies | 58 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/Dockerfile.dependencies b/Dockerfile.dependencies index 34bfbc3b8c78..04233cd415fa 100644 --- a/Dockerfile.dependencies +++ b/Dockerfile.dependencies @@ -6,7 +6,7 @@ # To build with other versions, use "--build-arg JDK_VERSION=[value]" ARG JDK_VERSION=17 -# Step 1 - Run Maven Build +# Step 1 - Download all Dependencies FROM docker.io/maven:3-eclipse-temurin-${JDK_VERSION} AS build ARG TARGET_DIR=dspace-installer WORKDIR /app @@ -19,16 +19,60 @@ RUN chown -Rv dspace: /app # Switch to dspace user & run below commands as that user USER dspace -# Copy the DSpace source code (from local machine) into the workdir (excluding .dockerignore contents) -ADD --chown=dspace . /app/ +# This next part may look odd, but it speeds up the build of this image *significantly*. +# Copy ONLY the POMs to this image (from local machine). This will allow us to download all dependencies *without* +# performing any code compilation steps. + +# Parent POM +ADD --chown=dspace pom.xml /app/ +RUN mkdir -p /app/dspace + +# 'dspace' module POM. Includes 'additions' ONLY, as it's the only submodule that is required to exist. +ADD --chown=dspace dspace/pom.xml /app/dspace/ +RUN mkdir -p /app/dspace/modules/ +ADD --chown=dspace dspace/modules/pom.xml /app/dspace/modules/ +RUN mkdir -p /app/dspace/modules/additions +ADD --chown=dspace dspace/modules/additions/pom.xml /app/dspace/modules/additions/ + +# 'dspace-api' module POM +RUN mkdir -p /app/dspace-api +ADD --chown=dspace dspace-api/pom.xml /app/dspace-api/ + +# 'dspace-iiif' module POM +RUN mkdir -p /app/dspace-iiif +ADD --chown=dspace dspace-iiif/pom.xml /app/dspace-iiif/ + +# 'dspace-oai' module POM +RUN mkdir -p /app/dspace-oai +ADD --chown=dspace dspace-oai/pom.xml /app/dspace-oai/ + +# 'dspace-rdf' module POM +RUN mkdir -p /app/dspace-rdf +ADD --chown=dspace dspace-rdf/pom.xml /app/dspace-rdf/ + +# 'dspace-server-webapp' module POM +RUN mkdir -p /app/dspace-server-webapp +ADD --chown=dspace dspace-server-webapp/pom.xml /app/dspace-server-webapp/ + +# 'dspace-services' module POM +RUN mkdir -p /app/dspace-services +ADD --chown=dspace dspace-services/pom.xml /app/dspace-services/ + +# 'dspace-sword' module POM +RUN mkdir -p /app/dspace-sword +ADD --chown=dspace dspace-sword/pom.xml /app/dspace-sword/ + +# 'dspace-swordv2' module POM +RUN mkdir -p /app/dspace-swordv2 +ADD --chown=dspace dspace-swordv2/pom.xml /app/dspace-swordv2/ # Trigger the installation of all maven dependencies (hide download progress messages) # Maven flags here ensure that we skip final assembly, skip building test environment and skip all code verification checks. -# These flags speed up this installation as much as reasonably possible. -ENV MAVEN_FLAGS="-P-assembly -P-test-environment -Denforcer.skip=true -Dcheckstyle.skip=true -Dlicense.skip=true -Dxml.skip=true" -RUN mvn --no-transfer-progress install ${MAVEN_FLAGS} +# These flags speed up this installation and skip tasks we cannot perform as we don't have the full source code. +ENV MAVEN_FLAGS="-P-assembly -P-test-environment -Denforcer.skip=true -Dcheckstyle.skip=true -Dlicense.skip=true -Dxjc.skip=true -Dxml.skip=true" +RUN mvn --no-transfer-progress verify ${MAVEN_FLAGS} -# Clear the contents of the /app directory (including all maven builds), so no artifacts remain. +# Clear the contents of the /app directory (including all maven target folders), so no artifacts remain. # This ensures when dspace:dspace is built, it will use the Maven local cache (~/.m2) for dependencies USER root RUN rm -rf /app/* From e5568157c87370531e6b86cbf582e160504858fb Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 17 Sep 2024 08:47:54 -0400 Subject: [PATCH 235/632] More information about failed DOI registrations. (cherry picked from commit b8f4ab0eb3e90b080eaae057fb5ee673d3477dc2) --- .../dspace/identifier/doi/DOIOrganiser.java | 3 ++- .../identifier/doi/DataCiteConnector.java | 22 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index 088e2b1cbc87..12f6d7c4fca4 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -577,7 +577,8 @@ public void update(DOI doiRow) { } } catch (IdentifierException ex) { if (!(ex instanceof DOIIdentifierException)) { - LOG.error("It wasn't possible to register the identifier online. ", ex); + LOG.error("Registering DOI {} for object {}: the registrar returned an error.", + doiRow.getDoi(), dso.getID(), ex); } DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index a15e3f7fdbfe..5bb37add2d9a 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -464,6 +464,10 @@ public void reserveDOI(Context context, DSpaceObject dso, String doi) log.warn("While reserving the DOI {}, we got a http status code " + "{} and the message \"{}\".", doi, Integer.toString(resp.statusCode), resp.getContent()); + Format format = Format.getCompactFormat(); + format.setEncoding("UTF-8"); + XMLOutputter xout = new XMLOutputter(format); + log.info("We send the following XML:\n{}", xout.outputString(root)); throw new DOIIdentifierException("Unable to parse an answer from " + "DataCite API. Please have a look into DSpace logs.", DOIIdentifierException.BAD_ANSWER); @@ -635,6 +639,14 @@ protected DataCiteResponse sendGetRequest(String doi, String path) return sendHttpRequest(httpget, doi); } + /** + * Send a DataCite metadata document to the registrar. + * + * @param doi identify the object. + * @param metadataRoot describe the object. The root element of the document. + * @return the registrar's response. + * @throws DOIIdentifierException passed through. + */ protected DataCiteResponse sendMetadataPostRequest(String doi, Element metadataRoot) throws DOIIdentifierException { Format format = Format.getCompactFormat(); @@ -643,6 +655,14 @@ protected DataCiteResponse sendMetadataPostRequest(String doi, Element metadataR return sendMetadataPostRequest(doi, xout.outputString(new Document(metadataRoot))); } + /** + * Send a DataCite metadata document to the registrar. + * + * @param doi identify the object. + * @param metadata describe the object. + * @return the registrar's response. + * @throws DOIIdentifierException passed through. + */ protected DataCiteResponse sendMetadataPostRequest(String doi, String metadata) throws DOIIdentifierException { // post mds/metadata/ @@ -690,7 +710,7 @@ protected DataCiteResponse sendMetadataPostRequest(String doi, String metadata) * properties such as request URI and method type. * @param doi DOI string to operate on * @return response from DataCite - * @throws DOIIdentifierException if DOI error + * @throws DOIIdentifierException if registrar returns an error. */ protected DataCiteResponse sendHttpRequest(HttpUriRequest req, String doi) throws DOIIdentifierException { From 8b468a171635bfdfeaf9530ba59cc7ed541070f3 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 17 Sep 2024 08:47:54 -0400 Subject: [PATCH 236/632] More information about failed DOI registrations. (cherry picked from commit b8f4ab0eb3e90b080eaae057fb5ee673d3477dc2) --- .../dspace/identifier/doi/DOIOrganiser.java | 3 ++- .../identifier/doi/DataCiteConnector.java | 22 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index 78507a0edf13..05769e94bce5 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -577,7 +577,8 @@ public void update(DOI doiRow) { } } catch (IdentifierException ex) { if (!(ex instanceof DOIIdentifierException)) { - LOG.error("It wasn't possible to register the identifier online. ", ex); + LOG.error("Registering DOI {} for object {}: the registrar returned an error.", + doiRow.getDoi(), dso.getID(), ex); } DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index b4cdac96303a..3fc55ec146c7 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -461,6 +461,10 @@ public void reserveDOI(Context context, DSpaceObject dso, String doi) log.warn("While reserving the DOI {}, we got a http status code " + "{} and the message \"{}\".", doi, Integer.toString(resp.statusCode), resp.getContent()); + Format format = Format.getCompactFormat(); + format.setEncoding("UTF-8"); + XMLOutputter xout = new XMLOutputter(format); + log.info("We send the following XML:\n{}", xout.outputString(root)); throw new DOIIdentifierException("Unable to parse an answer from " + "DataCite API. Please have a look into DSpace logs.", DOIIdentifierException.BAD_ANSWER); @@ -632,6 +636,14 @@ protected DataCiteResponse sendGetRequest(String doi, String path) return sendHttpRequest(httpget, doi); } + /** + * Send a DataCite metadata document to the registrar. + * + * @param doi identify the object. + * @param metadataRoot describe the object. The root element of the document. + * @return the registrar's response. + * @throws DOIIdentifierException passed through. + */ protected DataCiteResponse sendMetadataPostRequest(String doi, Element metadataRoot) throws DOIIdentifierException { Format format = Format.getCompactFormat(); @@ -640,6 +652,14 @@ protected DataCiteResponse sendMetadataPostRequest(String doi, Element metadataR return sendMetadataPostRequest(doi, xout.outputString(new Document(metadataRoot))); } + /** + * Send a DataCite metadata document to the registrar. + * + * @param doi identify the object. + * @param metadata describe the object. + * @return the registrar's response. + * @throws DOIIdentifierException passed through. + */ protected DataCiteResponse sendMetadataPostRequest(String doi, String metadata) throws DOIIdentifierException { // post mds/metadata/ @@ -687,7 +707,7 @@ protected DataCiteResponse sendMetadataPostRequest(String doi, String metadata) * properties such as request URI and method type. * @param doi DOI string to operate on * @return response from DataCite - * @throws DOIIdentifierException if DOI error + * @throws DOIIdentifierException if registrar returns an error. */ protected DataCiteResponse sendHttpRequest(HttpUriRequest req, String doi) throws DOIIdentifierException { From fcc650e1a6fbc1311e905a349fc5ed3957dd1db7 Mon Sep 17 00:00:00 2001 From: Toni Prieto Date: Sat, 26 Oct 2024 23:33:13 +0200 Subject: [PATCH 237/632] Add limit, offset, and a new parameter to calculate the total entry count in the Solr query used for the metadata navigation index (cherry picked from commit e71de8a4d075d897f68c145233ac19ba0ec3718b) --- .../java/org/dspace/browse/BrowseEngine.java | 30 ++-------------- .../java/org/dspace/browse/SolrBrowseDAO.java | 32 ++++++++++++----- .../org/dspace/discovery/DiscoverResult.java | 11 ++++++ .../org/dspace/discovery/SolrServiceImpl.java | 36 ++++++++++++++++++- 4 files changed, 73 insertions(+), 36 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java b/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java index 351c36248209..be7a34086a46 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java @@ -422,9 +422,6 @@ private BrowseInfo browseByValue(BrowserScope bs) } } - // this is the total number of results in answer to the query - int total = getTotalResults(true); - // set the ordering field (there is only one option) dao.setOrderField("sort_value"); @@ -444,6 +441,9 @@ private BrowseInfo browseByValue(BrowserScope bs) dao.setOffset(offset); dao.setLimit(scope.getResultsPerPage()); + // this is the total number of results in answer to the query + int total = getTotalResults(true); + // Holder for the results List results = null; @@ -680,33 +680,9 @@ private int getTotalResults(boolean distinct) // tell the browse query whether we are distinct dao.setDistinct(distinct); - // ensure that the select is set to "*" - String[] select = {"*"}; - dao.setCountValues(select); - - // FIXME: it would be nice to have a good way of doing this in the DAO - // now reset all of the fields that we don't want to have constraining - // our count, storing them locally to reinstate later - String focusField = dao.getJumpToField(); - String focusValue = dao.getJumpToValue(); - int limit = dao.getLimit(); - int offset = dao.getOffset(); - - dao.setJumpToField(null); - dao.setJumpToValue(null); - dao.setLimit(-1); - dao.setOffset(-1); - // perform the query and get the result int count = dao.doCountQuery(); - // now put back the values we removed for this method - dao.setJumpToField(focusField); - dao.setJumpToValue(focusValue); - dao.setLimit(limit); - dao.setOffset(offset); - dao.setCountValues(null); - log.debug(LogHelper.getHeader(context, "get_total_results_return", "return=" + count)); return count; diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java index f99aab852bf5..1917dec423ec 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java +++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java @@ -13,6 +13,8 @@ import java.util.Comparator; import java.util.List; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.apache.solr.client.solrj.util.ClientUtils; @@ -180,18 +182,33 @@ private DiscoverResult getSolrResponse() throws BrowseException { addDefaultFilterQueries(query); if (distinct) { DiscoverFacetField dff; + + // To get the number of distinct values we use the next "json.facet" query param + // {"entries_count": {"type":"terms","field": "_filter", "limit":0, "numBuckets":true}}" + ObjectNode jsonFacet = JsonNodeFactory.instance.objectNode(); + ObjectNode entriesCount = JsonNodeFactory.instance.objectNode(); + entriesCount.put("type", "terms"); + entriesCount.put("field", facetField + "_filter"); + entriesCount.put("limit", 0); + entriesCount.put("numBuckets", true); + jsonFacet.set("entries_count", entriesCount); + if (StringUtils.isNotBlank(startsWith)) { dff = new DiscoverFacetField(facetField, - DiscoveryConfigurationParameters.TYPE_TEXT, -1, - DiscoveryConfigurationParameters.SORT.VALUE, startsWith); + DiscoveryConfigurationParameters.TYPE_TEXT, limit, + DiscoveryConfigurationParameters.SORT.VALUE, startsWith, offset); + + // Add the prefix to the json facet query + entriesCount.put("prefix", startsWith); } else { dff = new DiscoverFacetField(facetField, - DiscoveryConfigurationParameters.TYPE_TEXT, -1, - DiscoveryConfigurationParameters.SORT.VALUE); + DiscoveryConfigurationParameters.TYPE_TEXT, limit, + DiscoveryConfigurationParameters.SORT.VALUE, offset); } query.addFacetField(dff); query.setFacetMinCount(1); query.setMaxResults(0); + query.addProperty("json.facet", jsonFacet.toString()); } else { query.setMaxResults(limit/* > 0 ? limit : 20*/); if (offset > 0) { @@ -248,8 +265,7 @@ public int doCountQuery() throws BrowseException { DiscoverResult resp = getSolrResponse(); int count = 0; if (distinct) { - List facetResults = resp.getFacetResult(facetField); - count = facetResults.size(); + count = (int) resp.getTotalEntries(); } else { // we need to cast to int to respect the BrowseDAO contract... count = (int) resp.getTotalSearchResults(); @@ -266,8 +282,8 @@ public List doValueQuery() throws BrowseException { DiscoverResult resp = getSolrResponse(); List facet = resp.getFacetResult(facetField); int count = doCountQuery(); - int start = offset > 0 ? offset : 0; - int max = limit > 0 ? limit : count; //if negative, return everything + int start = 0; + int max = facet.size(); List result = new ArrayList<>(); if (ascending) { for (int i = start; i < (start + max) && i < count; i++) { diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java index 00236d2bfe32..a56804e3e7ea 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java @@ -32,6 +32,9 @@ public class DiscoverResult { private List indexableObjects; private Map> facetResults; + // Total count of facet entries calculated for a metadata browsing query + private long totalEntries; + /** * A map that contains all the documents sougth after, the key is a string representation of the Indexable Object */ @@ -64,6 +67,14 @@ public void setTotalSearchResults(long totalSearchResults) { this.totalSearchResults = totalSearchResults; } + public long getTotalEntries() { + return totalEntries; + } + + public void setTotalEntries(long totalEntries) { + this.totalEntries = totalEntries; + } + public int getStart() { return start; } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index cd3797e3e34e..9339b574b578 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -1055,6 +1055,8 @@ protected DiscoverResult retrieveResult(Context context, DiscoverQuery query) } //Resolve our facet field values resolveFacetFields(context, query, result, skipLoadingResponse, solrQueryResponse); + //Add total entries count for metadata browsing + resolveEntriesCount(result, solrQueryResponse); } // If any stale entries are found in the current page of results, // we remove those stale entries and rerun the same query again. @@ -1080,7 +1082,39 @@ protected DiscoverResult retrieveResult(Context context, DiscoverQuery query) return result; } - + /** + * Stores the total count of entries for metadata index browsing. The count is calculated by the + * json.facet parameter with the following value: + * + *
    
    +     * {
    +     *     "entries_count": {
    +     *         "type": "terms",
    +     *         "field": "facetNameField_filter",
    +     *         "limit": 0,
    +     *         "prefix": "prefix_value",
    +     *         "numBuckets": true
    +     *     }
    +     * }
    +     * 
    + * + * This value is returned in the facets field of the Solr response. + * + * @param result DiscoverResult object where the total entries count will be stored + * @param solrQueryResponse QueryResponse object containing the solr response + */ + private void resolveEntriesCount(DiscoverResult result, QueryResponse solrQueryResponse) { + + Object facetsObj = solrQueryResponse.getResponse().get("facets"); + if (facetsObj instanceof NamedList) { + NamedList facets = (NamedList) facetsObj; + Object bucketsInfoObj = facets.get("entries_count"); + if (bucketsInfoObj instanceof NamedList) { + NamedList bucketsInfo = (NamedList) bucketsInfoObj; + result.setTotalEntries((int) bucketsInfo.get("numBuckets")); + } + } + } private void resolveFacetFields(Context context, DiscoverQuery query, DiscoverResult result, boolean skipLoadingResponse, QueryResponse solrQueryResponse) throws SQLException { From 75647de90e4664a297cac2672fabe1d33306d195 Mon Sep 17 00:00:00 2001 From: Toni Prieto Date: Sat, 26 Oct 2024 23:33:13 +0200 Subject: [PATCH 238/632] Add limit, offset, and a new parameter to calculate the total entry count in the Solr query used for the metadata navigation index (cherry picked from commit e71de8a4d075d897f68c145233ac19ba0ec3718b) --- .../java/org/dspace/browse/BrowseEngine.java | 30 ++-------------- .../java/org/dspace/browse/SolrBrowseDAO.java | 32 ++++++++++++----- .../org/dspace/discovery/DiscoverResult.java | 11 ++++++ .../org/dspace/discovery/SolrServiceImpl.java | 36 ++++++++++++++++++- 4 files changed, 73 insertions(+), 36 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java b/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java index 351c36248209..be7a34086a46 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java @@ -422,9 +422,6 @@ private BrowseInfo browseByValue(BrowserScope bs) } } - // this is the total number of results in answer to the query - int total = getTotalResults(true); - // set the ordering field (there is only one option) dao.setOrderField("sort_value"); @@ -444,6 +441,9 @@ private BrowseInfo browseByValue(BrowserScope bs) dao.setOffset(offset); dao.setLimit(scope.getResultsPerPage()); + // this is the total number of results in answer to the query + int total = getTotalResults(true); + // Holder for the results List results = null; @@ -680,33 +680,9 @@ private int getTotalResults(boolean distinct) // tell the browse query whether we are distinct dao.setDistinct(distinct); - // ensure that the select is set to "*" - String[] select = {"*"}; - dao.setCountValues(select); - - // FIXME: it would be nice to have a good way of doing this in the DAO - // now reset all of the fields that we don't want to have constraining - // our count, storing them locally to reinstate later - String focusField = dao.getJumpToField(); - String focusValue = dao.getJumpToValue(); - int limit = dao.getLimit(); - int offset = dao.getOffset(); - - dao.setJumpToField(null); - dao.setJumpToValue(null); - dao.setLimit(-1); - dao.setOffset(-1); - // perform the query and get the result int count = dao.doCountQuery(); - // now put back the values we removed for this method - dao.setJumpToField(focusField); - dao.setJumpToValue(focusValue); - dao.setLimit(limit); - dao.setOffset(offset); - dao.setCountValues(null); - log.debug(LogHelper.getHeader(context, "get_total_results_return", "return=" + count)); return count; diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java index f99aab852bf5..1917dec423ec 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java +++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java @@ -13,6 +13,8 @@ import java.util.Comparator; import java.util.List; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.apache.solr.client.solrj.util.ClientUtils; @@ -180,18 +182,33 @@ private DiscoverResult getSolrResponse() throws BrowseException { addDefaultFilterQueries(query); if (distinct) { DiscoverFacetField dff; + + // To get the number of distinct values we use the next "json.facet" query param + // {"entries_count": {"type":"terms","field": "_filter", "limit":0, "numBuckets":true}}" + ObjectNode jsonFacet = JsonNodeFactory.instance.objectNode(); + ObjectNode entriesCount = JsonNodeFactory.instance.objectNode(); + entriesCount.put("type", "terms"); + entriesCount.put("field", facetField + "_filter"); + entriesCount.put("limit", 0); + entriesCount.put("numBuckets", true); + jsonFacet.set("entries_count", entriesCount); + if (StringUtils.isNotBlank(startsWith)) { dff = new DiscoverFacetField(facetField, - DiscoveryConfigurationParameters.TYPE_TEXT, -1, - DiscoveryConfigurationParameters.SORT.VALUE, startsWith); + DiscoveryConfigurationParameters.TYPE_TEXT, limit, + DiscoveryConfigurationParameters.SORT.VALUE, startsWith, offset); + + // Add the prefix to the json facet query + entriesCount.put("prefix", startsWith); } else { dff = new DiscoverFacetField(facetField, - DiscoveryConfigurationParameters.TYPE_TEXT, -1, - DiscoveryConfigurationParameters.SORT.VALUE); + DiscoveryConfigurationParameters.TYPE_TEXT, limit, + DiscoveryConfigurationParameters.SORT.VALUE, offset); } query.addFacetField(dff); query.setFacetMinCount(1); query.setMaxResults(0); + query.addProperty("json.facet", jsonFacet.toString()); } else { query.setMaxResults(limit/* > 0 ? limit : 20*/); if (offset > 0) { @@ -248,8 +265,7 @@ public int doCountQuery() throws BrowseException { DiscoverResult resp = getSolrResponse(); int count = 0; if (distinct) { - List facetResults = resp.getFacetResult(facetField); - count = facetResults.size(); + count = (int) resp.getTotalEntries(); } else { // we need to cast to int to respect the BrowseDAO contract... count = (int) resp.getTotalSearchResults(); @@ -266,8 +282,8 @@ public List doValueQuery() throws BrowseException { DiscoverResult resp = getSolrResponse(); List facet = resp.getFacetResult(facetField); int count = doCountQuery(); - int start = offset > 0 ? offset : 0; - int max = limit > 0 ? limit : count; //if negative, return everything + int start = 0; + int max = facet.size(); List result = new ArrayList<>(); if (ascending) { for (int i = start; i < (start + max) && i < count; i++) { diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java index 00236d2bfe32..a56804e3e7ea 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java @@ -32,6 +32,9 @@ public class DiscoverResult { private List indexableObjects; private Map> facetResults; + // Total count of facet entries calculated for a metadata browsing query + private long totalEntries; + /** * A map that contains all the documents sougth after, the key is a string representation of the Indexable Object */ @@ -64,6 +67,14 @@ public void setTotalSearchResults(long totalSearchResults) { this.totalSearchResults = totalSearchResults; } + public long getTotalEntries() { + return totalEntries; + } + + public void setTotalEntries(long totalEntries) { + this.totalEntries = totalEntries; + } + public int getStart() { return start; } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index a0c1188d7132..0769310b8175 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -1055,6 +1055,8 @@ protected DiscoverResult retrieveResult(Context context, DiscoverQuery query) } //Resolve our facet field values resolveFacetFields(context, query, result, skipLoadingResponse, solrQueryResponse); + //Add total entries count for metadata browsing + resolveEntriesCount(result, solrQueryResponse); } // If any stale entries are found in the current page of results, // we remove those stale entries and rerun the same query again. @@ -1080,7 +1082,39 @@ protected DiscoverResult retrieveResult(Context context, DiscoverQuery query) return result; } - + /** + * Stores the total count of entries for metadata index browsing. The count is calculated by the + * json.facet parameter with the following value: + * + *
    
    +     * {
    +     *     "entries_count": {
    +     *         "type": "terms",
    +     *         "field": "facetNameField_filter",
    +     *         "limit": 0,
    +     *         "prefix": "prefix_value",
    +     *         "numBuckets": true
    +     *     }
    +     * }
    +     * 
    + * + * This value is returned in the facets field of the Solr response. + * + * @param result DiscoverResult object where the total entries count will be stored + * @param solrQueryResponse QueryResponse object containing the solr response + */ + private void resolveEntriesCount(DiscoverResult result, QueryResponse solrQueryResponse) { + + Object facetsObj = solrQueryResponse.getResponse().get("facets"); + if (facetsObj instanceof NamedList) { + NamedList facets = (NamedList) facetsObj; + Object bucketsInfoObj = facets.get("entries_count"); + if (bucketsInfoObj instanceof NamedList) { + NamedList bucketsInfo = (NamedList) bucketsInfoObj; + result.setTotalEntries((int) bucketsInfo.get("numBuckets")); + } + } + } private void resolveFacetFields(Context context, DiscoverQuery query, DiscoverResult result, boolean skipLoadingResponse, QueryResponse solrQueryResponse) throws SQLException { From 95742fe4f38842fc0747188ec941b05364ec7797 Mon Sep 17 00:00:00 2001 From: Jukka Lipka <3710455+jlipka@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:11:08 +0200 Subject: [PATCH 239/632] fix(submission): Submission scope naming fixed According to the documentation, the value for the property is 'submission' in the 'submission-forms.xml'. Without this change, an empty input field will never be marked as an error, even if the field is marked as 'required'. (cherry picked from commit 02f52c7d5c245eaae09dbd636fc8c7935d7cc242) --- dspace-api/src/main/java/org/dspace/app/util/DCInput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java index 11f9aadd869b..a3d1ba208b56 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java @@ -163,7 +163,7 @@ public class DCInput { * The scope of the input sets, this restricts hidden metadata fields from * view by the end user during submission. */ - public static final String SUBMISSION_SCOPE = "submit"; + public static final String SUBMISSION_SCOPE = "submission"; /** * Class constructor for creating a DCInput object based on the contents of From 31faf809d15d968a021a64720b620faf5f47bf0e Mon Sep 17 00:00:00 2001 From: Jukka Lipka <3710455+jlipka@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:50:59 +0100 Subject: [PATCH 240/632] fix(submission): Submission scope naming fixed Corrected wording in related code comment (cherry picked from commit ec2187ea6532d7db5f5ffa38e20e971a49b90871) --- dspace-api/src/main/java/org/dspace/app/util/DCInput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java index a3d1ba208b56..0a1e77ee7292 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java @@ -262,7 +262,7 @@ protected void initRegex(String regex) { /** * Is this DCInput for display in the given scope? The scope should be - * either "workflow" or "submit", as per the input forms definition. If the + * either "workflow" or "submission", as per the input forms definition. If the * internal visibility is set to "null" then this will always return true. * * @param scope String identifying the scope that this input's visibility From 4dcf17314c3d694d42d7442315bcac6d2010f85f Mon Sep 17 00:00:00 2001 From: Jukka Lipka <3710455+jlipka@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:11:08 +0200 Subject: [PATCH 241/632] fix(submission): Submission scope naming fixed According to the documentation, the value for the property is 'submission' in the 'submission-forms.xml'. Without this change, an empty input field will never be marked as an error, even if the field is marked as 'required'. (cherry picked from commit 02f52c7d5c245eaae09dbd636fc8c7935d7cc242) --- dspace-api/src/main/java/org/dspace/app/util/DCInput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java index dd88390cb856..846a74cad5d5 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java @@ -163,7 +163,7 @@ public class DCInput { * The scope of the input sets, this restricts hidden metadata fields from * view by the end user during submission. */ - public static final String SUBMISSION_SCOPE = "submit"; + public static final String SUBMISSION_SCOPE = "submission"; /** * Class constructor for creating a DCInput object based on the contents of From d34b55996479de15fbc449ebce8180c00c221972 Mon Sep 17 00:00:00 2001 From: Jukka Lipka <3710455+jlipka@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:50:59 +0100 Subject: [PATCH 242/632] fix(submission): Submission scope naming fixed Corrected wording in related code comment (cherry picked from commit ec2187ea6532d7db5f5ffa38e20e971a49b90871) --- dspace-api/src/main/java/org/dspace/app/util/DCInput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java index 846a74cad5d5..c96be33d0132 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java @@ -262,7 +262,7 @@ protected void initRegex(String regex) { /** * Is this DCInput for display in the given scope? The scope should be - * either "workflow" or "submit", as per the input forms definition. If the + * either "workflow" or "submission", as per the input forms definition. If the * internal visibility is set to "null" then this will always return true. * * @param scope String identifying the scope that this input's visibility From 973beee2ce5f8dc993ef5eb91711b595c7786789 Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 18:44:15 -0300 Subject: [PATCH 243/632] fix: properly type in field id, adjust use of getProperty and add error handling when dbPath is null (when property usage-statistics.dbfile is commented (cherry picked from commit 412d5751f29f31bbdd872820a62b74970333f066) --- .../org/dspace/statistics/util/StatisticsImporter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java index 95736a8bd6d9..1bd97a6f5ec9 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java @@ -357,7 +357,7 @@ protected void load(String filename, Context context, boolean verbose) { SolrInputDocument sid = new SolrInputDocument(); sid.addField("ip", ip); sid.addField("type", dso.getType()); - sid.addField("id", dso.getID()); + sid.addField("id", dso.getID().toString()); sid.addField("time", DateFormatUtils.format(date, SolrLoggerServiceImpl.DATE_FORMAT_8601)); sid.addField("continent", continent); sid.addField("country", country); @@ -471,13 +471,13 @@ public static void main(String[] args) throws Exception { boolean verbose = line.hasOption('v'); // Find our solr server - String sserver = configurationService.getProperty("solr-statistics", "server"); + String sserver = configurationService.getProperty("solr-statistics.server"); if (verbose) { System.out.println("Writing to solr server at: " + sserver); } solr = new HttpSolrClient.Builder(sserver).build(); - String dbPath = configurationService.getProperty("usage-statistics", "dbfile"); + String dbPath = configurationService.getProperty("usage-statistics.dbfile"); try { File dbFile = new File(dbPath); geoipLookup = new DatabaseReader.Builder(dbFile).build(); @@ -492,6 +492,10 @@ public static void main(String[] args) throws Exception { "Unable to load GeoLite Database file (" + dbPath + ")! You may need to reinstall it. See the DSpace " + "installation instructions for more details.", e); + } catch (NullPointerException e) { + log.error( + "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite Database file and/or uncomment the property in the config file!", + e); } From 3a223e3fefec9172538e7defa34ce982b0d72762 Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 20:16:47 -0300 Subject: [PATCH 244/632] fix line length checkstyle (cherry picked from commit 338f3b1d3efaa0f7f3852654121cf1f93adeae7e) --- .../java/org/dspace/statistics/util/StatisticsImporter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java index 1bd97a6f5ec9..354c803fe2ae 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java @@ -494,7 +494,8 @@ public static void main(String[] args) throws Exception { e); } catch (NullPointerException e) { log.error( - "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite Database file and/or uncomment the property in the config file!", + "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite " + + "Database file and/or uncomment the property in the config file!", e); } From f0a514ae73fa8e469531572c2fa6931b491b0533 Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 18:44:15 -0300 Subject: [PATCH 245/632] fix: properly type in field id, adjust use of getProperty and add error handling when dbPath is null (when property usage-statistics.dbfile is commented (cherry picked from commit 412d5751f29f31bbdd872820a62b74970333f066) --- .../org/dspace/statistics/util/StatisticsImporter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java index 95736a8bd6d9..1bd97a6f5ec9 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java @@ -357,7 +357,7 @@ protected void load(String filename, Context context, boolean verbose) { SolrInputDocument sid = new SolrInputDocument(); sid.addField("ip", ip); sid.addField("type", dso.getType()); - sid.addField("id", dso.getID()); + sid.addField("id", dso.getID().toString()); sid.addField("time", DateFormatUtils.format(date, SolrLoggerServiceImpl.DATE_FORMAT_8601)); sid.addField("continent", continent); sid.addField("country", country); @@ -471,13 +471,13 @@ public static void main(String[] args) throws Exception { boolean verbose = line.hasOption('v'); // Find our solr server - String sserver = configurationService.getProperty("solr-statistics", "server"); + String sserver = configurationService.getProperty("solr-statistics.server"); if (verbose) { System.out.println("Writing to solr server at: " + sserver); } solr = new HttpSolrClient.Builder(sserver).build(); - String dbPath = configurationService.getProperty("usage-statistics", "dbfile"); + String dbPath = configurationService.getProperty("usage-statistics.dbfile"); try { File dbFile = new File(dbPath); geoipLookup = new DatabaseReader.Builder(dbFile).build(); @@ -492,6 +492,10 @@ public static void main(String[] args) throws Exception { "Unable to load GeoLite Database file (" + dbPath + ")! You may need to reinstall it. See the DSpace " + "installation instructions for more details.", e); + } catch (NullPointerException e) { + log.error( + "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite Database file and/or uncomment the property in the config file!", + e); } From de3e8baebed0e25ed60c613ec75b1f21fe488f01 Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 20:16:47 -0300 Subject: [PATCH 246/632] fix line length checkstyle (cherry picked from commit 338f3b1d3efaa0f7f3852654121cf1f93adeae7e) --- .../java/org/dspace/statistics/util/StatisticsImporter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java index 1bd97a6f5ec9..354c803fe2ae 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java @@ -494,7 +494,8 @@ public static void main(String[] args) throws Exception { e); } catch (NullPointerException e) { log.error( - "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite Database file and/or uncomment the property in the config file!", + "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite " + + "Database file and/or uncomment the property in the config file!", e); } From c86d082d5f6fe4a76eae018bbe6890cc0b72ff33 Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 13:10:14 -0300 Subject: [PATCH 247/632] fix: set default configFile (cherry picked from commit a5e8d7aa15bc56c268ba67f19657f19edaa45253) --- .../java/org/dspace/app/statistics/LogAnalyser.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java b/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java index 2e4ed69b268e..c787261419f8 100644 --- a/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java +++ b/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java @@ -281,10 +281,14 @@ public class LogAnalyser { */ private static String fileTemplate = "dspace\\.log.*"; + private static final ConfigurationService configurationService = + DSpaceServicesFactory.getInstance().getConfigurationService(); + /** * the configuration file from which to configure the analyser */ - private static String configFile; + private static String configFile = configurationService.getProperty("dspace.dir") + + File.separator + "config" + File.separator + "dstat.cfg"; /** * the output file to which to write aggregation data @@ -616,8 +620,6 @@ public static String processLogs(Context context, String myLogDir, } // now do the host name and url lookup - ConfigurationService configurationService - = DSpaceServicesFactory.getInstance().getConfigurationService(); hostName = Utils.getHostName(configurationService.getProperty("dspace.ui.url")); name = configurationService.getProperty("dspace.name").trim(); url = configurationService.getProperty("dspace.ui.url").trim(); @@ -658,8 +660,6 @@ public static void setParameters(String myLogDir, String myFileTemplate, String myConfigFile, String myOutFile, Date myStartDate, Date myEndDate, boolean myLookUp) { - ConfigurationService configurationService - = DSpaceServicesFactory.getInstance().getConfigurationService(); if (myLogDir != null) { logDir = myLogDir; @@ -673,9 +673,6 @@ public static void setParameters(String myLogDir, String myFileTemplate, if (myConfigFile != null) { configFile = myConfigFile; - } else { - configFile = configurationService.getProperty("dspace.dir") - + File.separator + "config" + File.separator + "dstat.cfg"; } if (myStartDate != null) { From d2ab46b0ae34a00de6bc99d1b5e0a2240cde74bb Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 13:10:14 -0300 Subject: [PATCH 248/632] fix: set default configFile (cherry picked from commit a5e8d7aa15bc56c268ba67f19657f19edaa45253) --- .../java/org/dspace/app/statistics/LogAnalyser.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java b/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java index 2e4ed69b268e..c787261419f8 100644 --- a/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java +++ b/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java @@ -281,10 +281,14 @@ public class LogAnalyser { */ private static String fileTemplate = "dspace\\.log.*"; + private static final ConfigurationService configurationService = + DSpaceServicesFactory.getInstance().getConfigurationService(); + /** * the configuration file from which to configure the analyser */ - private static String configFile; + private static String configFile = configurationService.getProperty("dspace.dir") + + File.separator + "config" + File.separator + "dstat.cfg"; /** * the output file to which to write aggregation data @@ -616,8 +620,6 @@ public static String processLogs(Context context, String myLogDir, } // now do the host name and url lookup - ConfigurationService configurationService - = DSpaceServicesFactory.getInstance().getConfigurationService(); hostName = Utils.getHostName(configurationService.getProperty("dspace.ui.url")); name = configurationService.getProperty("dspace.name").trim(); url = configurationService.getProperty("dspace.ui.url").trim(); @@ -658,8 +660,6 @@ public static void setParameters(String myLogDir, String myFileTemplate, String myConfigFile, String myOutFile, Date myStartDate, Date myEndDate, boolean myLookUp) { - ConfigurationService configurationService - = DSpaceServicesFactory.getInstance().getConfigurationService(); if (myLogDir != null) { logDir = myLogDir; @@ -673,9 +673,6 @@ public static void setParameters(String myLogDir, String myFileTemplate, if (myConfigFile != null) { configFile = myConfigFile; - } else { - configFile = configurationService.getProperty("dspace.dir") - + File.separator + "config" + File.separator + "dstat.cfg"; } if (myStartDate != null) { From 2d57d7f626dbe433d4581d3ef8114ab775cd8088 Mon Sep 17 00:00:00 2001 From: DSpace Bot <68393067+dspace-bot@users.noreply.github.com> Date: Wed, 18 Dec 2024 15:57:16 -0600 Subject: [PATCH 249/632] [Port dspace-8_x] Fix issue with submission sections visibility (#10141) * README.md: v8 is the current release, not v7 (cherry picked from commit 2b698eff609d510c487ad2331d4e11cd28f64e9a) (cherry picked from commit 83460afb3700a2ddaabce16069b2094e4edbe8fa) * Update README.md (cherry picked from commit 671234b08f909810d798dd950f87d1818b098363) (cherry picked from commit 7a6785b1c353cbc45c4dfaad89f5252064ef1e4e) * [DURACOM-291] Expose section scope attribute (cherry picked from commit 4107f937fda1b49da2b6a81dc91026ebf4b1cd37) * README.md: v8 is the current release, not v7 (cherry picked from commit 2b698eff609d510c487ad2331d4e11cd28f64e9a) (cherry picked from commit d98499a39416d026c0b45199e90ddb9bbfc1cd9c) * Update README.md (cherry picked from commit 671234b08f909810d798dd950f87d1818b098363) (cherry picked from commit 6a707548ffa6929e8a36775063ce05e2dc02a586) --------- Co-authored-by: Christian Clauss Co-authored-by: Giuseppe Digilio --- .../dspace/app/rest/converter/SubmissionSectionConverter.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionSectionConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionSectionConverter.java index 0391cbce7a2d..3cd263493b5d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionSectionConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionSectionConverter.java @@ -10,6 +10,7 @@ import java.sql.SQLException; import org.apache.logging.log4j.Logger; +import org.dspace.app.rest.model.ScopeEnum; import org.dspace.app.rest.model.SubmissionSectionRest; import org.dspace.app.rest.model.SubmissionVisibilityRest; import org.dspace.app.rest.model.VisibilityEnum; @@ -41,6 +42,7 @@ public SubmissionSectionRest convert(SubmissionStepConfig step, Projection proje sp.setHeader(step.getHeading()); sp.setSectionType(step.getType()); sp.setId(step.getId()); + sp.setScope(ScopeEnum.fromString(step.getScope())); sp.setVisibility(new SubmissionVisibilityRest(VisibilityEnum.fromString(step.getVisibility()), VisibilityEnum.fromString(step.getVisibilityOutside()))); return sp; From 1ce4e08333559bffadde8d266a1009c1c875df33 Mon Sep 17 00:00:00 2001 From: DSpace Bot <68393067+dspace-bot@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:45:16 -0600 Subject: [PATCH 250/632] [Port dspace-7_x] Fix issue with submission sections visibility (#10140) * README.md: v8 is the current release, not v7 (cherry picked from commit 2b698eff609d510c487ad2331d4e11cd28f64e9a) (cherry picked from commit 83460afb3700a2ddaabce16069b2094e4edbe8fa) * Update README.md (cherry picked from commit 671234b08f909810d798dd950f87d1818b098363) (cherry picked from commit 7a6785b1c353cbc45c4dfaad89f5252064ef1e4e) * [DURACOM-291] Expose section scope attribute (cherry picked from commit 4107f937fda1b49da2b6a81dc91026ebf4b1cd37) * README.md: v8 is the current release, not v7 (cherry picked from commit 2b698eff609d510c487ad2331d4e11cd28f64e9a) (cherry picked from commit d98499a39416d026c0b45199e90ddb9bbfc1cd9c) * Update README.md (cherry picked from commit 671234b08f909810d798dd950f87d1818b098363) (cherry picked from commit 6a707548ffa6929e8a36775063ce05e2dc02a586) --------- Co-authored-by: Christian Clauss Co-authored-by: Giuseppe Digilio --- .../dspace/app/rest/converter/SubmissionSectionConverter.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionSectionConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionSectionConverter.java index 0391cbce7a2d..3cd263493b5d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionSectionConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionSectionConverter.java @@ -10,6 +10,7 @@ import java.sql.SQLException; import org.apache.logging.log4j.Logger; +import org.dspace.app.rest.model.ScopeEnum; import org.dspace.app.rest.model.SubmissionSectionRest; import org.dspace.app.rest.model.SubmissionVisibilityRest; import org.dspace.app.rest.model.VisibilityEnum; @@ -41,6 +42,7 @@ public SubmissionSectionRest convert(SubmissionStepConfig step, Projection proje sp.setHeader(step.getHeading()); sp.setSectionType(step.getType()); sp.setId(step.getId()); + sp.setScope(ScopeEnum.fromString(step.getScope())); sp.setVisibility(new SubmissionVisibilityRest(VisibilityEnum.fromString(step.getVisibility()), VisibilityEnum.fromString(step.getVisibilityOutside()))); return sp; From 51df5c1fe67b7660dafa85d57f688347ca7f024d Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 2 Dec 2024 15:35:10 +0100 Subject: [PATCH 251/632] 119664: Search event scope fix (cherry picked from commit 48956d90b7619bdb336632b454ac62ca62967a39) --- .../org/dspace/app/rest/converter/SearchEventConverter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java index 978ae2ca9230..f2fb12f2bda9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java @@ -67,8 +67,8 @@ public UsageSearchEvent convert(Context context, HttpServletRequest request, Sea if (searchEventRest.getScope() != null) { IndexableObject scopeObject = scopeResolver.resolveScope(context, String.valueOf(searchEventRest.getScope())); - if (scopeObject instanceof DSpaceObject) { - usageSearchEvent.setScope((DSpaceObject) scopeObject); + if (scopeObject != null && scopeObject.getIndexedObject() instanceof DSpaceObject) { + usageSearchEvent.setScope((DSpaceObject) scopeObject.getIndexedObject()); } } usageSearchEvent.setConfiguration(searchEventRest.getConfiguration()); From fa209881b15b5abfac522b9df8e302ad02a44c9c Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 2 Dec 2024 15:35:10 +0100 Subject: [PATCH 252/632] 119664: Search event scope fix (cherry picked from commit 48956d90b7619bdb336632b454ac62ca62967a39) --- .../org/dspace/app/rest/converter/SearchEventConverter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java index d781d255df11..dcf42f099821 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SearchEventConverter.java @@ -67,8 +67,8 @@ public UsageSearchEvent convert(Context context, HttpServletRequest request, Sea if (searchEventRest.getScope() != null) { IndexableObject scopeObject = scopeResolver.resolveScope(context, String.valueOf(searchEventRest.getScope())); - if (scopeObject instanceof DSpaceObject) { - usageSearchEvent.setScope((DSpaceObject) scopeObject); + if (scopeObject != null && scopeObject.getIndexedObject() instanceof DSpaceObject) { + usageSearchEvent.setScope((DSpaceObject) scopeObject.getIndexedObject()); } } usageSearchEvent.setConfiguration(searchEventRest.getConfiguration()); From 9cca67de0e95b272523bbbac9f982ce9594b20d9 Mon Sep 17 00:00:00 2001 From: Brian Keese Date: Tue, 15 Oct 2024 11:38:54 -0500 Subject: [PATCH 253/632] Fix full-text indexing for files over the character limit The error handler for files over the limit logged the correct message, but never actually added the full text to the index doc. (cherry picked from commit 4a4a8bcb22796e5b22c9bbb1796e3458b48f1c07) --- .../indexobject/IndexFactoryImpl.java | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java index f1ae137b9163..c9a865ec85b2 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java @@ -118,20 +118,10 @@ protected void writeDocument(SolrInputDocument doc, FullTextContentStreams strea ParseContext tikaContext = new ParseContext(); // Use Apache Tika to parse the full text stream(s) + boolean extractionSucceeded = false; try (InputStream fullTextStreams = streams.getStream()) { tikaParser.parse(fullTextStreams, tikaHandler, tikaMetadata, tikaContext); - - // Write Tika metadata to "tika_meta_*" fields. - // This metadata is not very useful right now, - // but we'll keep it just in case it becomes more useful. - for (String name : tikaMetadata.names()) { - for (String value : tikaMetadata.getValues(name)) { - doc.addField("tika_meta_" + name, value); - } - } - - // Save (parsed) full text to "fulltext" field - doc.addField("fulltext", tikaHandler.toString()); + extractionSucceeded = true; } catch (SAXException saxe) { // Check if this SAXException is just a notice that this file was longer than the character limit. // Unfortunately there is not a unique, public exception type to catch here. This error is thrown @@ -141,6 +131,7 @@ protected void writeDocument(SolrInputDocument doc, FullTextContentStreams strea // log that we only indexed up to that configured limit log.info("Full text is larger than the configured limit (discovery.solr.fulltext.charLimit)." + " Only the first {} characters were indexed.", charLimit); + extractionSucceeded = true; } else { log.error("Tika parsing error. Could not index full text.", saxe); throw new IOException("Tika parsing error. Could not index full text.", saxe); @@ -148,11 +139,19 @@ protected void writeDocument(SolrInputDocument doc, FullTextContentStreams strea } catch (TikaException | IOException ex) { log.error("Tika parsing error. Could not index full text.", ex); throw new IOException("Tika parsing error. Could not index full text.", ex); - } finally { - // Add document to index - solr.add(doc); } - return; + if (extractionSucceeded) { + // Write Tika metadata to "tika_meta_*" fields. + // This metadata is not very useful right now, + // but we'll keep it just in case it becomes more useful. + for (String name : tikaMetadata.names()) { + for (String value : tikaMetadata.getValues(name)) { + doc.addField("tika_meta_" + name, value); + } + } + // Save (parsed) full text to "fulltext" field + doc.addField("fulltext", tikaHandler.toString()); + } } // Add document to index solr.add(doc); From 8849212895d987abaca92865178c6b4d2f99452d Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Wed, 28 Apr 2021 09:29:36 -0400 Subject: [PATCH 254/632] Add Context method to uncache all entities (cherry picked from commit 8ea664adb2161b04ab8b6171bbb426d8875fe27f) --- .../main/java/org/dspace/core/Context.java | 14 +++++++- .../java/org/dspace/core/DBConnection.java | 32 ++++++++++++------- .../dspace/core/HibernateDBConnection.java | 5 +++ .../java/org/dspace/core/ContextTest.java | 25 +++++++++++++++ .../core/HibernateDBConnectionTest.java | 22 +++++++++++++ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/Context.java b/dspace-api/src/main/java/org/dspace/core/Context.java index 02a3fee09f8a..dab6ab7fbd66 100644 --- a/dspace-api/src/main/java/org/dspace/core/Context.java +++ b/dspace-api/src/main/java/org/dspace/core/Context.java @@ -883,7 +883,19 @@ public E reloadEntity(E entity) throws SQLException } /** - * Remove an entity from the cache. This is necessary when batch processing a large number of items. + * Remove all entities from the cache and reload the current user entity. This is useful when batch processing + * a large number of entities when the calling code requires the cache to be completely cleared before continuing. + * + * @throws SQLException if a database error occurs. + */ + public void uncacheEntities() throws SQLException { + dbConnection.uncacheEntities(); + reloadContextBoundEntities(); + } + + /** + * Remove an entity from the cache. This is useful when batch processing a large number of entities + * when the calling code needs to retain some items in the cache while removing others. * * @param entity The entity to reload * @param The class of the entity. The entity must implement the {@link ReloadableEntity} interface. diff --git a/dspace-api/src/main/java/org/dspace/core/DBConnection.java b/dspace-api/src/main/java/org/dspace/core/DBConnection.java index 66e4a65dbfe1..c9c4ce0953e4 100644 --- a/dspace-api/src/main/java/org/dspace/core/DBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/DBConnection.java @@ -124,28 +124,38 @@ public interface DBConnection { public long getCacheSize() throws SQLException; /** - * Reload a DSpace object from the database. This will make sure the object + * Reload an entity from the database. This will make sure the object * is valid and stored in the cache. The returned object should be used * henceforth instead of the passed object. * - * @param type of {@link entity} - * @param entity The DSpace object to reload + * @param type of entity. + * @param entity The entity to reload. * @return the reloaded entity. - * @throws java.sql.SQLException passed through. + * @throws SQLException passed through. */ public E reloadEntity(E entity) throws SQLException; /** - * Remove a DSpace object from the session cache when batch processing a - * large number of objects. + * Remove all entities from the session cache. * - *

    Objects removed from cache are not saved in any way. Therefore, if you - * have modified an object, you should be sure to {@link commit()} changes + *

    Entities removed from cache are not saved in any way. Therefore, if you + * have modified any entities, you should be sure to {@link #commit()} changes * before calling this method. * - * @param Type of {@link entity} - * @param entity The DSpace object to decache. - * @throws java.sql.SQLException passed through. + * @throws SQLException passed through. + */ + public void uncacheEntities() throws SQLException; + + /** + * Remove an entity from the session cache. + * + *

    Entities removed from cache are not saved in any way. Therefore, if you + * have modified the entity, you should be sure to {@link #commit()} changes + * before calling this method. + * + * @param Type of entity. + * @param entity The entity to decache. + * @throws SQLException passed through. */ public void uncacheEntity(E entity) throws SQLException; diff --git a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java index b371af80eede..bd00b844ba9a 100644 --- a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java @@ -243,6 +243,11 @@ private void configureDatabaseMode() throws SQLException { } } + @Override + public void uncacheEntities() throws SQLException { + getSession().clear(); + } + /** * Evict an entity from the hibernate cache. *

    diff --git a/dspace-api/src/test/java/org/dspace/core/ContextTest.java b/dspace-api/src/test/java/org/dspace/core/ContextTest.java index c6cd849d2110..ccc1d2f732cc 100644 --- a/dspace-api/src/test/java/org/dspace/core/ContextTest.java +++ b/dspace-api/src/test/java/org/dspace/core/ContextTest.java @@ -558,4 +558,29 @@ protected void init() { cleanupContext(instance); } + @Test + public void testUncacheEntities() throws Throwable { + // To set up the test, ensure the cache contains more than the current user entity + groupService.findByName(context, Group.ANONYMOUS); + assertTrue("Cache size should be greater than one", context.getDBConnection().getCacheSize() > 1); + + context.uncacheEntities(); + + assertThat("Cache size should be one (current user)", context.getDBConnection().getCacheSize(), equalTo(1L)); + context.reloadEntity(context.getCurrentUser()); + assertThat("Cache should only contain the current user", context.getDBConnection().getCacheSize(), equalTo(1L)); + } + + @Test + public void testUncacheEntity() throws Throwable { + // Remember the cache size after loading an entity + Group group = groupService.findByName(context, Group.ANONYMOUS); + long oldCacheSize = context.getDBConnection().getCacheSize(); + + // Uncache the entity + context.uncacheEntity(group); + + long newCacheSize = context.getDBConnection().getCacheSize(); + assertThat("Cache size should be reduced by one", newCacheSize, equalTo(oldCacheSize - 1)); + } } diff --git a/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java b/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java index 093f693d567f..302844ce62ac 100644 --- a/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java +++ b/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java @@ -205,6 +205,28 @@ public void testReloadEntityAfterCommit() throws SQLException { .contains(person)); } + /** + * Test of uncacheEntities method + */ + @Test + public void testUncacheEntities() throws SQLException { + // Get DBConnection associated with DSpace Context + HibernateDBConnection dbConnection = (HibernateDBConnection) context.getDBConnection(); + EPerson person = context.getCurrentUser(); + + assertTrue("Current user should be cached in session", dbConnection.getSession() + .contains(person)); + + dbConnection.uncacheEntities(); + assertFalse("Current user should be gone from cache", dbConnection.getSession() + .contains(person)); + + // Test ability to reload an uncached entity + person = dbConnection.reloadEntity(person); + assertTrue("Current user should be cached back in session", dbConnection.getSession() + .contains(person)); + } + /** * Test of uncacheEntity method */ From 9d01b87c4f3b8bf925d5526e7292f113975c9499 Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Wed, 28 Apr 2021 09:29:36 -0400 Subject: [PATCH 255/632] Add Context method to uncache all entities (cherry picked from commit 8ea664adb2161b04ab8b6171bbb426d8875fe27f) --- .../main/java/org/dspace/core/Context.java | 14 +++++++- .../java/org/dspace/core/DBConnection.java | 32 ++++++++++++------- .../dspace/core/HibernateDBConnection.java | 5 +++ .../java/org/dspace/core/ContextTest.java | 25 +++++++++++++++ .../core/HibernateDBConnectionTest.java | 22 +++++++++++++ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/Context.java b/dspace-api/src/main/java/org/dspace/core/Context.java index 02a3fee09f8a..dab6ab7fbd66 100644 --- a/dspace-api/src/main/java/org/dspace/core/Context.java +++ b/dspace-api/src/main/java/org/dspace/core/Context.java @@ -883,7 +883,19 @@ public E reloadEntity(E entity) throws SQLException } /** - * Remove an entity from the cache. This is necessary when batch processing a large number of items. + * Remove all entities from the cache and reload the current user entity. This is useful when batch processing + * a large number of entities when the calling code requires the cache to be completely cleared before continuing. + * + * @throws SQLException if a database error occurs. + */ + public void uncacheEntities() throws SQLException { + dbConnection.uncacheEntities(); + reloadContextBoundEntities(); + } + + /** + * Remove an entity from the cache. This is useful when batch processing a large number of entities + * when the calling code needs to retain some items in the cache while removing others. * * @param entity The entity to reload * @param The class of the entity. The entity must implement the {@link ReloadableEntity} interface. diff --git a/dspace-api/src/main/java/org/dspace/core/DBConnection.java b/dspace-api/src/main/java/org/dspace/core/DBConnection.java index 66e4a65dbfe1..c9c4ce0953e4 100644 --- a/dspace-api/src/main/java/org/dspace/core/DBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/DBConnection.java @@ -124,28 +124,38 @@ public interface DBConnection { public long getCacheSize() throws SQLException; /** - * Reload a DSpace object from the database. This will make sure the object + * Reload an entity from the database. This will make sure the object * is valid and stored in the cache. The returned object should be used * henceforth instead of the passed object. * - * @param type of {@link entity} - * @param entity The DSpace object to reload + * @param type of entity. + * @param entity The entity to reload. * @return the reloaded entity. - * @throws java.sql.SQLException passed through. + * @throws SQLException passed through. */ public E reloadEntity(E entity) throws SQLException; /** - * Remove a DSpace object from the session cache when batch processing a - * large number of objects. + * Remove all entities from the session cache. * - *

    Objects removed from cache are not saved in any way. Therefore, if you - * have modified an object, you should be sure to {@link commit()} changes + *

    Entities removed from cache are not saved in any way. Therefore, if you + * have modified any entities, you should be sure to {@link #commit()} changes * before calling this method. * - * @param Type of {@link entity} - * @param entity The DSpace object to decache. - * @throws java.sql.SQLException passed through. + * @throws SQLException passed through. + */ + public void uncacheEntities() throws SQLException; + + /** + * Remove an entity from the session cache. + * + *

    Entities removed from cache are not saved in any way. Therefore, if you + * have modified the entity, you should be sure to {@link #commit()} changes + * before calling this method. + * + * @param Type of entity. + * @param entity The entity to decache. + * @throws SQLException passed through. */ public void uncacheEntity(E entity) throws SQLException; diff --git a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java index a867849077a3..806930d0364a 100644 --- a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java @@ -242,6 +242,11 @@ private void configureDatabaseMode() throws SQLException { } } + @Override + public void uncacheEntities() throws SQLException { + getSession().clear(); + } + /** * Evict an entity from the hibernate cache. *

    diff --git a/dspace-api/src/test/java/org/dspace/core/ContextTest.java b/dspace-api/src/test/java/org/dspace/core/ContextTest.java index c6cd849d2110..ccc1d2f732cc 100644 --- a/dspace-api/src/test/java/org/dspace/core/ContextTest.java +++ b/dspace-api/src/test/java/org/dspace/core/ContextTest.java @@ -558,4 +558,29 @@ protected void init() { cleanupContext(instance); } + @Test + public void testUncacheEntities() throws Throwable { + // To set up the test, ensure the cache contains more than the current user entity + groupService.findByName(context, Group.ANONYMOUS); + assertTrue("Cache size should be greater than one", context.getDBConnection().getCacheSize() > 1); + + context.uncacheEntities(); + + assertThat("Cache size should be one (current user)", context.getDBConnection().getCacheSize(), equalTo(1L)); + context.reloadEntity(context.getCurrentUser()); + assertThat("Cache should only contain the current user", context.getDBConnection().getCacheSize(), equalTo(1L)); + } + + @Test + public void testUncacheEntity() throws Throwable { + // Remember the cache size after loading an entity + Group group = groupService.findByName(context, Group.ANONYMOUS); + long oldCacheSize = context.getDBConnection().getCacheSize(); + + // Uncache the entity + context.uncacheEntity(group); + + long newCacheSize = context.getDBConnection().getCacheSize(); + assertThat("Cache size should be reduced by one", newCacheSize, equalTo(oldCacheSize - 1)); + } } diff --git a/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java b/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java index 093f693d567f..302844ce62ac 100644 --- a/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java +++ b/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java @@ -205,6 +205,28 @@ public void testReloadEntityAfterCommit() throws SQLException { .contains(person)); } + /** + * Test of uncacheEntities method + */ + @Test + public void testUncacheEntities() throws SQLException { + // Get DBConnection associated with DSpace Context + HibernateDBConnection dbConnection = (HibernateDBConnection) context.getDBConnection(); + EPerson person = context.getCurrentUser(); + + assertTrue("Current user should be cached in session", dbConnection.getSession() + .contains(person)); + + dbConnection.uncacheEntities(); + assertFalse("Current user should be gone from cache", dbConnection.getSession() + .contains(person)); + + // Test ability to reload an uncached entity + person = dbConnection.reloadEntity(person); + assertTrue("Current user should be cached back in session", dbConnection.getSession() + .contains(person)); + } + /** * Test of uncacheEntity method */ From e856ae3291831feac74f01133f7e235d8513cba0 Mon Sep 17 00:00:00 2001 From: Toni Prieto Date: Sun, 27 Oct 2024 08:56:10 +0100 Subject: [PATCH 256/632] Uncache all entities during OAI indexing to reduce memory usage (cherry picked from commit 9af2e2e17cf289a2a6921d27a21d90db6ca8b9f9) --- dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java index c6aaaa34b539..2d2679577802 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java @@ -334,6 +334,11 @@ private int index(Iterator iterator) throws DSpaceSolrIndexerException { server.add(list); server.commit(); list.clear(); + try { + context.uncacheEntities(); + } catch (SQLException ex) { + log.error("Error uncaching entities", ex); + } } } System.out.println("Total: " + i + " items"); From 79ef831c87d0b73c3e891d447f35f73af09a86f4 Mon Sep 17 00:00:00 2001 From: Toni Prieto Date: Sun, 27 Oct 2024 08:56:10 +0100 Subject: [PATCH 257/632] Uncache all entities during OAI indexing to reduce memory usage (cherry picked from commit 9af2e2e17cf289a2a6921d27a21d90db6ca8b9f9) --- dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java index ad138ca9f2ad..5c29b259deab 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java @@ -334,6 +334,11 @@ private int index(Iterator iterator) throws DSpaceSolrIndexerException { server.add(list); server.commit(); list.clear(); + try { + context.uncacheEntities(); + } catch (SQLException ex) { + log.error("Error uncaching entities", ex); + } } } System.out.println("Total: " + i + " items"); From 964e4bf476b9cb49ce07c5d05242c63e9ae638d4 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 23 Dec 2024 12:26:58 +0100 Subject: [PATCH 258/632] remove usage of deprecated constructor call (cherry picked from commit 45cdb4d9d47d3151a4672e99152a0b3bedb6cd18) --- dspace-api/src/main/java/org/dspace/curate/Curation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/curate/Curation.java b/dspace-api/src/main/java/org/dspace/curate/Curation.java index 4d70286e79e0..ea47d817c07d 100644 --- a/dspace-api/src/main/java/org/dspace/curate/Curation.java +++ b/dspace-api/src/main/java/org/dspace/curate/Curation.java @@ -185,7 +185,7 @@ private Curator initCurator() throws FileNotFoundException { Curator curator = new Curator(handler); OutputStream reporterStream; if (null == this.reporter) { - reporterStream = new NullOutputStream(); + reporterStream = NullOutputStream.NULL_OUTPUT_STREAM; } else if ("-".equals(this.reporter)) { reporterStream = System.out; } else { From 7f26447a8dc98aca168b9da4f250d2f123a8a73a Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 23 Dec 2024 12:26:58 +0100 Subject: [PATCH 259/632] remove usage of deprecated constructor call (cherry picked from commit 45cdb4d9d47d3151a4672e99152a0b3bedb6cd18) --- dspace-api/src/main/java/org/dspace/curate/Curation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/curate/Curation.java b/dspace-api/src/main/java/org/dspace/curate/Curation.java index 4d70286e79e0..ea47d817c07d 100644 --- a/dspace-api/src/main/java/org/dspace/curate/Curation.java +++ b/dspace-api/src/main/java/org/dspace/curate/Curation.java @@ -185,7 +185,7 @@ private Curator initCurator() throws FileNotFoundException { Curator curator = new Curator(handler); OutputStream reporterStream; if (null == this.reporter) { - reporterStream = new NullOutputStream(); + reporterStream = NullOutputStream.NULL_OUTPUT_STREAM; } else if ("-".equals(this.reporter)) { reporterStream = System.out; } else { From 214c669e8063f93eca2f878610647cc3b87346bd Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 11 Dec 2024 15:35:26 +0100 Subject: [PATCH 260/632] fix missing +1 offset (cherry picked from commit ab00de05b46fe98306e0047af7d6d98bba9d0077) --- dspace-oai/src/main/resources/static/style.xsl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dspace-oai/src/main/resources/static/style.xsl b/dspace-oai/src/main/resources/static/style.xsl index 17eb865e8f1f..67aeb975b26b 100644 --- a/dspace-oai/src/main/resources/static/style.xsl +++ b/dspace-oai/src/main/resources/static/style.xsl @@ -522,15 +522,14 @@ - + - - + - - + From 27e557662369e02b545580f48c616974510c4c74 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 11 Dec 2024 15:35:26 +0100 Subject: [PATCH 261/632] fix missing +1 offset (cherry picked from commit ab00de05b46fe98306e0047af7d6d98bba9d0077) --- dspace-oai/src/main/resources/static/style.xsl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dspace-oai/src/main/resources/static/style.xsl b/dspace-oai/src/main/resources/static/style.xsl index 17eb865e8f1f..67aeb975b26b 100644 --- a/dspace-oai/src/main/resources/static/style.xsl +++ b/dspace-oai/src/main/resources/static/style.xsl @@ -522,15 +522,14 @@ - + - - + - - + From 7cfc0aa106568f3f9bb143fe3330008bbaf6ac0e Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Tue, 7 Jan 2025 15:51:28 +0100 Subject: [PATCH 262/632] Bugfix: Enforce unique item id in workspace table (#9340) * 106798 Enforce values in item_id column of workspaceitem table to be unique, both at database level and at WorkspaceItemService level * 106798 Removed Oracle SQL migration * 106798 workspaceitem table migration: delete duplicate rows before introducing uniqueness constraint * 106798: update migration for H2 --------- Co-authored-by: Koen Pauwels Co-authored-by: wout --- .../content/WorkspaceItemServiceImpl.java | 8 +++ ...paceitem_add_item_id_unique_constraint.sql | 21 +++++++ ...paceitem_add_item_id_unique_constraint.sql | 21 +++++++ .../org/dspace/content/WorkspaceItemTest.java | 12 ++++ .../org/dspace/workflow/MockWorkflowItem.java | 62 +++++++++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql create mode 100644 dspace-api/src/test/java/org/dspace/workflow/MockWorkflowItem.java diff --git a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java index 1da9e6e44a6a..543f5a55efe2 100644 --- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java @@ -178,6 +178,14 @@ public WorkspaceItem create(Context context, Collection collection, UUID uuid, b @Override public WorkspaceItem create(Context c, WorkflowItem workflowItem) throws SQLException, AuthorizeException { + WorkspaceItem potentialDuplicate = findByItem(c, workflowItem.getItem()); + if (potentialDuplicate != null) { + throw new IllegalArgumentException(String.format( + "A workspace item referring to item %s already exists (%d)", + workflowItem.getItem().getID(), + potentialDuplicate.getID() + )); + } WorkspaceItem workspaceItem = workspaceItemDAO.create(c, new WorkspaceItem()); workspaceItem.setItem(workflowItem.getItem()); workspaceItem.setCollection(workflowItem.getCollection()); diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql new file mode 100644 index 000000000000..38389bf2d19b --- /dev/null +++ b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql @@ -0,0 +1,21 @@ +-- +-- The contents of this file are subject to the license and copyright +-- detailed in the LICENSE and NOTICE files at the root of the source +-- tree and available online at +-- +-- http://www.dspace.org/license/ +-- + +-- In the workspaceitem table, if there are multiple rows referring to the same item ID, keep only the first of them. +DELETE FROM workspaceitem WHERE EXISTS ( + SELECT item_id + FROM workspaceitem + GROUP BY item_id + HAVING COUNT(workspace_item_id) > 1 +) AND workspaceitem.workspace_item_id NOT IN ( + SELECT MIN(workspace_item_id) AS workspace_item_id + FROM workspaceitem + GROUP BY item_id +); +-- Identify which rows have duplicates, and compute their replacements. +ALTER TABLE workspaceitem ADD CONSTRAINT unique_item_id UNIQUE(item_id); diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql new file mode 100644 index 000000000000..20eb0f9119d3 --- /dev/null +++ b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql @@ -0,0 +1,21 @@ +-- +-- The contents of this file are subject to the license and copyright +-- detailed in the LICENSE and NOTICE files at the root of the source +-- tree and available online at +-- +-- http://www.dspace.org/license/ +-- + +-- In the workspaceitem table, if there are multiple rows referring to the same item ID, keep only the first of them. +WITH dedup AS ( + SELECT item_id, MIN(workspace_item_id) AS workspace_item_id + FROM workspaceitem + GROUP BY item_id + HAVING COUNT(workspace_item_id) > 1 +) +DELETE FROM workspaceitem +USING dedup +WHERE workspaceitem.item_id = dedup.item_id AND workspaceitem.workspace_item_id <> dedup.workspace_item_id; + +-- Enforce uniqueness of item_id in workspaceitem table. +ALTER TABLE workspaceitem ADD CONSTRAINT unique_item_id UNIQUE(item_id); diff --git a/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java b/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java index d018a15f9765..15d4720c9378 100644 --- a/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java @@ -12,6 +12,7 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -39,6 +40,7 @@ import org.dspace.eperson.EPerson; import org.dspace.eperson.factory.EPersonServiceFactory; import org.dspace.eperson.service.EPersonService; +import org.dspace.workflow.MockWorkflowItem; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -468,4 +470,14 @@ public void testSetPublishedBefore() { assertTrue("testSetPublishedBefore 0", wi.isPublishedBefore()); } + @Test + public void testDuplicateItemID() throws Exception { + context.turnOffAuthorisationSystem(); + Item item = wi.getItem(); + MockWorkflowItem wfItem = new MockWorkflowItem(); + wfItem.item = item; + wfItem.collection = collection; + assertThrows(IllegalArgumentException.class, () -> workspaceItemService.create(context, wfItem)); + context.restoreAuthSystemState(); + } } diff --git a/dspace-api/src/test/java/org/dspace/workflow/MockWorkflowItem.java b/dspace-api/src/test/java/org/dspace/workflow/MockWorkflowItem.java new file mode 100644 index 000000000000..d36ecf7331b8 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/workflow/MockWorkflowItem.java @@ -0,0 +1,62 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.workflow; + +import org.dspace.content.Collection; +import org.dspace.content.Item; +import org.dspace.eperson.EPerson; + +public class MockWorkflowItem implements WorkflowItem { + public Integer id; + public Item item; + public Collection collection; + public EPerson submitter; + boolean hasMultipleFiles; + boolean hasMultipleTitles; + boolean isPublishedBefore; + + public Integer getID() { + return id; + } + + public Item getItem() { + return item; + } + + public Collection getCollection() { + return collection; + } + + public EPerson getSubmitter() { + return submitter; + } + + public boolean hasMultipleFiles() { + return hasMultipleFiles; + } + + public void setMultipleFiles(boolean b) { + hasMultipleFiles = b; + } + + public boolean hasMultipleTitles() { + return hasMultipleTitles; + } + + public void setMultipleTitles(boolean b) { + hasMultipleTitles = b; + } + + public boolean isPublishedBefore() { + return isPublishedBefore; + } + + public void setPublishedBefore(boolean b) { + isPublishedBefore = b; + } +} From 6c82e2dba40e50e72ab8459995802a5d7f526a53 Mon Sep 17 00:00:00 2001 From: Koen Pauwels Date: Tue, 7 Jan 2025 15:51:28 +0100 Subject: [PATCH 263/632] Bugfix: Enforce unique item id in workspace table (#9340) * 106798 Enforce values in item_id column of workspaceitem table to be unique, both at database level and at WorkspaceItemService level * 106798 Removed Oracle SQL migration * 106798 workspaceitem table migration: delete duplicate rows before introducing uniqueness constraint * 106798: update migration for H2 --------- Co-authored-by: Koen Pauwels Co-authored-by: wout --- .../content/WorkspaceItemServiceImpl.java | 8 +++ ...paceitem_add_item_id_unique_constraint.sql | 21 +++++++ ...paceitem_add_item_id_unique_constraint.sql | 21 +++++++ .../org/dspace/content/WorkspaceItemTest.java | 12 ++++ .../org/dspace/workflow/MockWorkflowItem.java | 62 +++++++++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql create mode 100644 dspace-api/src/test/java/org/dspace/workflow/MockWorkflowItem.java diff --git a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java index 1da9e6e44a6a..543f5a55efe2 100644 --- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java @@ -178,6 +178,14 @@ public WorkspaceItem create(Context context, Collection collection, UUID uuid, b @Override public WorkspaceItem create(Context c, WorkflowItem workflowItem) throws SQLException, AuthorizeException { + WorkspaceItem potentialDuplicate = findByItem(c, workflowItem.getItem()); + if (potentialDuplicate != null) { + throw new IllegalArgumentException(String.format( + "A workspace item referring to item %s already exists (%d)", + workflowItem.getItem().getID(), + potentialDuplicate.getID() + )); + } WorkspaceItem workspaceItem = workspaceItemDAO.create(c, new WorkspaceItem()); workspaceItem.setItem(workflowItem.getItem()); workspaceItem.setCollection(workflowItem.getCollection()); diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql new file mode 100644 index 000000000000..38389bf2d19b --- /dev/null +++ b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql @@ -0,0 +1,21 @@ +-- +-- The contents of this file are subject to the license and copyright +-- detailed in the LICENSE and NOTICE files at the root of the source +-- tree and available online at +-- +-- http://www.dspace.org/license/ +-- + +-- In the workspaceitem table, if there are multiple rows referring to the same item ID, keep only the first of them. +DELETE FROM workspaceitem WHERE EXISTS ( + SELECT item_id + FROM workspaceitem + GROUP BY item_id + HAVING COUNT(workspace_item_id) > 1 +) AND workspaceitem.workspace_item_id NOT IN ( + SELECT MIN(workspace_item_id) AS workspace_item_id + FROM workspaceitem + GROUP BY item_id +); +-- Identify which rows have duplicates, and compute their replacements. +ALTER TABLE workspaceitem ADD CONSTRAINT unique_item_id UNIQUE(item_id); diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql new file mode 100644 index 000000000000..20eb0f9119d3 --- /dev/null +++ b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2024.12.17__workspaceitem_add_item_id_unique_constraint.sql @@ -0,0 +1,21 @@ +-- +-- The contents of this file are subject to the license and copyright +-- detailed in the LICENSE and NOTICE files at the root of the source +-- tree and available online at +-- +-- http://www.dspace.org/license/ +-- + +-- In the workspaceitem table, if there are multiple rows referring to the same item ID, keep only the first of them. +WITH dedup AS ( + SELECT item_id, MIN(workspace_item_id) AS workspace_item_id + FROM workspaceitem + GROUP BY item_id + HAVING COUNT(workspace_item_id) > 1 +) +DELETE FROM workspaceitem +USING dedup +WHERE workspaceitem.item_id = dedup.item_id AND workspaceitem.workspace_item_id <> dedup.workspace_item_id; + +-- Enforce uniqueness of item_id in workspaceitem table. +ALTER TABLE workspaceitem ADD CONSTRAINT unique_item_id UNIQUE(item_id); diff --git a/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java b/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java index d018a15f9765..15d4720c9378 100644 --- a/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java @@ -12,6 +12,7 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -39,6 +40,7 @@ import org.dspace.eperson.EPerson; import org.dspace.eperson.factory.EPersonServiceFactory; import org.dspace.eperson.service.EPersonService; +import org.dspace.workflow.MockWorkflowItem; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -468,4 +470,14 @@ public void testSetPublishedBefore() { assertTrue("testSetPublishedBefore 0", wi.isPublishedBefore()); } + @Test + public void testDuplicateItemID() throws Exception { + context.turnOffAuthorisationSystem(); + Item item = wi.getItem(); + MockWorkflowItem wfItem = new MockWorkflowItem(); + wfItem.item = item; + wfItem.collection = collection; + assertThrows(IllegalArgumentException.class, () -> workspaceItemService.create(context, wfItem)); + context.restoreAuthSystemState(); + } } diff --git a/dspace-api/src/test/java/org/dspace/workflow/MockWorkflowItem.java b/dspace-api/src/test/java/org/dspace/workflow/MockWorkflowItem.java new file mode 100644 index 000000000000..d36ecf7331b8 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/workflow/MockWorkflowItem.java @@ -0,0 +1,62 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.workflow; + +import org.dspace.content.Collection; +import org.dspace.content.Item; +import org.dspace.eperson.EPerson; + +public class MockWorkflowItem implements WorkflowItem { + public Integer id; + public Item item; + public Collection collection; + public EPerson submitter; + boolean hasMultipleFiles; + boolean hasMultipleTitles; + boolean isPublishedBefore; + + public Integer getID() { + return id; + } + + public Item getItem() { + return item; + } + + public Collection getCollection() { + return collection; + } + + public EPerson getSubmitter() { + return submitter; + } + + public boolean hasMultipleFiles() { + return hasMultipleFiles; + } + + public void setMultipleFiles(boolean b) { + hasMultipleFiles = b; + } + + public boolean hasMultipleTitles() { + return hasMultipleTitles; + } + + public void setMultipleTitles(boolean b) { + hasMultipleTitles = b; + } + + public boolean isPublishedBefore() { + return isPublishedBefore; + } + + public void setPublishedBefore(boolean b) { + isPublishedBefore = b; + } +} From 22511a17b67c8034b039634e7bf98d9e9a58ae5d Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 6 Nov 2024 12:03:31 -0600 Subject: [PATCH 264/632] Refactor identifier ITs to ensure they unregister all utilized IdentifierProviders which are non-default. Cannot use "getApplicationContext().refresh()" as that seems to result in empty test database in Hibernate 6.6. (cherry picked from commit cfca2adbb1d597761b3169a5a46170de8cabfa4f) --- .../general/CreateMissingIdentifiersIT.java | 48 +++---------- .../AbstractIdentifierProviderIT.java | 68 +++++++++++++++++++ .../VersionedHandleIdentifierProviderIT.java | 49 ++----------- 3 files changed, 84 insertions(+), 81 deletions(-) create mode 100644 dspace-api/src/test/java/org/dspace/identifier/AbstractIdentifierProviderIT.java diff --git a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java index 8038a7153325..4934404c3b3e 100644 --- a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java +++ b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java @@ -10,10 +10,7 @@ import static org.junit.Assert.assertEquals; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; @@ -21,13 +18,11 @@ import org.dspace.content.Item; import org.dspace.core.factory.CoreServiceFactory; import org.dspace.curate.Curator; -import org.dspace.identifier.IdentifierProvider; -import org.dspace.identifier.IdentifierServiceImpl; +import org.dspace.identifier.AbstractIdentifierProviderIT; +import org.dspace.identifier.VersionedHandleIdentifierProvider; import org.dspace.identifier.VersionedHandleIdentifierProviderWithCanonicalHandles; -import org.dspace.kernel.ServiceManager; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; -import org.junit.After; import org.junit.Test; /** @@ -36,30 +31,19 @@ * @author mwood */ public class CreateMissingIdentifiersIT - extends AbstractIntegrationTestWithDatabase { - private ServiceManager serviceManager; - private IdentifierServiceImpl identifierService; + extends AbstractIdentifierProviderIT { + private static final String P_TASK_DEF = "plugin.named.org.dspace.curate.CurationTask"; private static final String TASK_NAME = "test"; - @Override - public void setUp() throws Exception { - super.setUp(); - context.turnOffAuthorisationSystem(); - - serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); - identifierService = serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0); - // Clean out providers to avoid any being used for creation of community and collection - identifierService.setProviders(new ArrayList<>()); - } + private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); @Test public void testPerform() throws IOException { // Must remove any cached named plugins before creating a new one CoreServiceFactory.getInstance().getPluginService().clearNamedPluginClasses(); - ConfigurationService configurationService = kernelImpl.getConfigurationService(); // Define a new task dynamically configurationService.setProperty(P_TASK_DEF, CreateMissingIdentifiers.class.getCanonicalName() + " = " + TASK_NAME); @@ -76,7 +60,7 @@ public void testPerform() .build(); /* - * Curate with regular test configuration -- should succeed. + * Curate with default Handle Provider */ curator.curate(context, item); int status = curator.getStatus(TASK_NAME); @@ -92,22 +76,10 @@ public void testPerform() curator.getResult(TASK_NAME)); assertEquals("Curation should fail", Curator.CURATE_ERROR, curator.getStatus(TASK_NAME)); - } - - @Override - @After - public void destroy() throws Exception { - super.destroy(); - DSpaceServicesFactory.getInstance().getServiceManager().getApplicationContext().refresh(); - } - - private void registerProvider(Class type) { - // Register our new provider - serviceManager.registerServiceClass(type.getName(), type); - IdentifierProvider identifierProvider = - (IdentifierProvider) serviceManager.getServiceByName(type.getName(), type); - // Overwrite the identifier-service's providers with the new one to ensure only this provider is used - identifierService.setProviders(List.of(identifierProvider)); + // Unregister this non-default provider + unregisterProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); + // Re-register the default provider (for later tests which may depend on it) + registerProvider(VersionedHandleIdentifierProvider.class); } } diff --git a/dspace-api/src/test/java/org/dspace/identifier/AbstractIdentifierProviderIT.java b/dspace-api/src/test/java/org/dspace/identifier/AbstractIdentifierProviderIT.java new file mode 100644 index 000000000000..6ec9efddf5e2 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/identifier/AbstractIdentifierProviderIT.java @@ -0,0 +1,68 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.identifier; + +import java.util.ArrayList; +import java.util.List; + +import org.dspace.AbstractIntegrationTestWithDatabase; +import org.dspace.kernel.ServiceManager; +import org.dspace.services.factory.DSpaceServicesFactory; + +/** + * AbstractIdentifierProviderIT which contains a few useful utility methods for IdentifierProvider Integration Tests + */ +public class AbstractIdentifierProviderIT extends AbstractIntegrationTestWithDatabase { + + protected final ServiceManager serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); + protected final IdentifierServiceImpl identifierService = + serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0); + + /** + * Register a specific IdentifierProvider into the current IdentifierService (replacing any existing providers). + * This method will also ensure the IdentifierProvider service is registered in the DSpace Service Manager. + * @param type IdentifierProvider Class + */ + protected void registerProvider(Class type) { + // Register our new provider + IdentifierProvider identifierProvider = + (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + if (identifierProvider == null) { + DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); + identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + } + + identifierService.setProviders(List.of(identifierProvider)); + } + + /** + * Unregister a specific IdentifierProvider from the current IdentifierService (removing all existing providers). + * This method will also ensure the IdentifierProvider service is unregistered in the DSpace Service Manager, + * which ensures it does not conflict with other IdentifierProvider services. + * @param type IdentifierProvider Class + */ + protected void unregisterProvider(Class type) { + // Find the provider service + IdentifierProvider identifierProvider = + (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + // If found, unregister it + if (identifierProvider == null) { + DSpaceServicesFactory.getInstance().getServiceManager().unregisterService(type.getName()); + } + + // Overwrite the identifier-service's providers with an empty list + identifierService.setProviders(new ArrayList<>()); + } + +} + + + diff --git a/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java b/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java index 57acf1f1c453..8c0f7e5b5e10 100644 --- a/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java +++ b/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java @@ -11,10 +11,7 @@ import static org.junit.Assert.assertTrue; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.authorize.AuthorizeException; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; @@ -22,15 +19,10 @@ import org.dspace.builder.VersionBuilder; import org.dspace.content.Collection; import org.dspace.content.Item; -import org.dspace.kernel.ServiceManager; -import org.dspace.services.factory.DSpaceServicesFactory; -import org.junit.After; import org.junit.Before; import org.junit.Test; -public class VersionedHandleIdentifierProviderIT extends AbstractIntegrationTestWithDatabase { - private ServiceManager serviceManager; - private IdentifierServiceImpl identifierService; +public class VersionedHandleIdentifierProviderIT extends AbstractIdentifierProviderIT { private String firstHandle; @@ -44,12 +36,6 @@ public class VersionedHandleIdentifierProviderIT extends AbstractIntegrationTest public void setUp() throws Exception { super.setUp(); context.turnOffAuthorisationSystem(); - - serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); - identifierService = serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0); - // Clean out providers to avoid any being used for creation of community and collection - identifierService.setProviders(new ArrayList<>()); - parentCommunity = CommunityBuilder.createCommunity(context) .withName("Parent Community") .build(); @@ -58,33 +44,6 @@ public void setUp() throws Exception { .build(); } - @After - @Override - public void destroy() throws Exception { - super.destroy(); - // After this test has finished running, refresh application context and - // set the expected 'default' versioned handle provider back to ensure other tests don't fail - DSpaceServicesFactory.getInstance().getServiceManager().getApplicationContext().refresh(); - } - - private void registerProvider(Class type) { - // Register our new provider - IdentifierProvider identifierProvider = - (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() - .getServiceByName(type.getName(), type); - if (identifierProvider == null) { - DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); - identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() - .getServiceByName(type.getName(), type); - } - - // Overwrite the identifier-service's providers with the new one to ensure only this provider is used - identifierService = DSpaceServicesFactory.getInstance().getServiceManager() - .getServicesByType(IdentifierServiceImpl.class).get(0); - identifierService.setProviders(new ArrayList<>()); - identifierService.setProviders(List.of(identifierProvider)); - } - private void createVersions() throws SQLException, AuthorizeException { itemV1 = ItemBuilder.createItem(context, collection) .withTitle("First version") @@ -96,7 +55,6 @@ private void createVersions() throws SQLException, AuthorizeException { @Test public void testDefaultVersionedHandleProvider() throws Exception { - registerProvider(VersionedHandleIdentifierProvider.class); createVersions(); // Confirm the original item only has its original handle @@ -125,6 +83,11 @@ public void testCanonicalVersionedHandleProvider() throws Exception { assertEquals(firstHandle, itemV3.getHandle()); assertEquals(2, itemV3.getHandles().size()); containsHandle(itemV3, firstHandle + ".3"); + + // Unregister this non-default provider + unregisterProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); + // Re-register the default provider (for later tests) + registerProvider(VersionedHandleIdentifierProvider.class); } private void containsHandle(Item item, String handle) { From 41207d5dee23c78d9f8a8ef93be89ed331607b13 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 8 Nov 2024 10:17:31 -0600 Subject: [PATCH 265/632] Update CreateMissingIdentifiers to better identify when CanonicalHandles provider is enabled. Update CreateMissingIdentifiersIT to verify that we are accurately resetting to our default IdentifierProvider (cherry picked from commit 2385c13f2d48048306a1280d88da5d8c022cc24f) --- .../general/CreateMissingIdentifiers.java | 28 +++++++++---------- .../identifier/IdentifierServiceImpl.java | 5 ++++ .../identifier/service/IdentifierService.java | 6 ++++ .../general/CreateMissingIdentifiersIT.java | 17 +++++------ 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/CreateMissingIdentifiers.java b/dspace-api/src/main/java/org/dspace/ctask/general/CreateMissingIdentifiers.java index 9639461426ef..0734d60946bc 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/CreateMissingIdentifiers.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/CreateMissingIdentifiers.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.sql.SQLException; +import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -25,7 +26,6 @@ import org.dspace.identifier.VersionedHandleIdentifierProviderWithCanonicalHandles; import org.dspace.identifier.factory.IdentifierServiceFactory; import org.dspace.identifier.service.IdentifierService; -import org.dspace.services.factory.DSpaceServicesFactory; /** * Ensure that an object has all of the identifiers that it should, minting them @@ -45,20 +45,6 @@ public int perform(DSpaceObject dso) return Curator.CURATE_SKIP; } - // XXX Temporary escape when an incompatible provider is configured. - // XXX Remove this when the provider is fixed. - boolean compatible = DSpaceServicesFactory - .getInstance() - .getServiceManager() - .getServiceByName( - VersionedHandleIdentifierProviderWithCanonicalHandles.class.getCanonicalName(), - IdentifierProvider.class) == null; - if (!compatible) { - setResult("This task is not compatible with VersionedHandleIdentifierProviderWithCanonicalHandles"); - return Curator.CURATE_ERROR; - } - // XXX End of escape - String typeText = Constants.typeText[dso.getType()]; // Get a Context @@ -75,6 +61,18 @@ public int perform(DSpaceObject dso) .getInstance() .getIdentifierService(); + // XXX Temporary escape when an incompatible provider is configured. + // XXX Remove this when the provider is fixed. + List providerList = identifierService.getProviders(); + boolean compatible = + providerList.stream().noneMatch(p -> p instanceof VersionedHandleIdentifierProviderWithCanonicalHandles); + + if (!compatible) { + setResult("This task is not compatible with VersionedHandleIdentifierProviderWithCanonicalHandles"); + return Curator.CURATE_ERROR; + } + // XXX End of escape + // Register any missing identifiers. try { identifierService.register(context, dso); diff --git a/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java b/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java index b98aea24fa08..e6dcfcdda693 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java @@ -57,6 +57,11 @@ public void setProviders(List providers) { } } + @Override + public List getProviders() { + return this.providers; + } + /** * Reserves identifiers for the item * diff --git a/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java b/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java index 23005b657508..45bf3c6dea8a 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java +++ b/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java @@ -19,6 +19,7 @@ import org.dspace.identifier.IdentifierException; import org.dspace.identifier.IdentifierNotFoundException; import org.dspace.identifier.IdentifierNotResolvableException; +import org.dspace.identifier.IdentifierProvider; /** * @author Fabio Bolognesi (fabio at atmire dot com) @@ -194,4 +195,9 @@ void register(Context context, DSpaceObject dso, String identifier) void delete(Context context, DSpaceObject dso, String identifier) throws AuthorizeException, SQLException, IdentifierException; + /** + * Get List of currently enabled IdentifierProviders + * @return List of enabled IdentifierProvider objects. + */ + List getProviders(); } diff --git a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java index 4934404c3b3e..3b50258a5a23 100644 --- a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java +++ b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java @@ -60,14 +60,7 @@ public void testPerform() .build(); /* - * Curate with default Handle Provider - */ - curator.curate(context, item); - int status = curator.getStatus(TASK_NAME); - assertEquals("Curation should succeed", Curator.CURATE_SUCCESS, status); - - /* - * Now install an incompatible provider to make the task fail. + * First, install an incompatible provider to make the task fail. */ registerProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); @@ -81,5 +74,13 @@ public void testPerform() unregisterProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); // Re-register the default provider (for later tests which may depend on it) registerProvider(VersionedHandleIdentifierProvider.class); + + /* + * Now, verify curate with default Handle Provider works + * (and that our re-registration of the default provider above was successful) + */ + curator.curate(context, item); + int status = curator.getStatus(TASK_NAME); + assertEquals("Curation should succeed", Curator.CURATE_SUCCESS, status); } } From 7ee4ba1a281c379d4fceb205428948b6aea14955 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 6 Nov 2024 12:03:31 -0600 Subject: [PATCH 266/632] Refactor identifier ITs to ensure they unregister all utilized IdentifierProviders which are non-default. Cannot use "getApplicationContext().refresh()" as that seems to result in empty test database in Hibernate 6.6. (cherry picked from commit cfca2adbb1d597761b3169a5a46170de8cabfa4f) --- .../general/CreateMissingIdentifiersIT.java | 48 +++---------- .../AbstractIdentifierProviderIT.java | 68 +++++++++++++++++++ .../VersionedHandleIdentifierProviderIT.java | 49 ++----------- 3 files changed, 84 insertions(+), 81 deletions(-) create mode 100644 dspace-api/src/test/java/org/dspace/identifier/AbstractIdentifierProviderIT.java diff --git a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java index 8038a7153325..4934404c3b3e 100644 --- a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java +++ b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java @@ -10,10 +10,7 @@ import static org.junit.Assert.assertEquals; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; @@ -21,13 +18,11 @@ import org.dspace.content.Item; import org.dspace.core.factory.CoreServiceFactory; import org.dspace.curate.Curator; -import org.dspace.identifier.IdentifierProvider; -import org.dspace.identifier.IdentifierServiceImpl; +import org.dspace.identifier.AbstractIdentifierProviderIT; +import org.dspace.identifier.VersionedHandleIdentifierProvider; import org.dspace.identifier.VersionedHandleIdentifierProviderWithCanonicalHandles; -import org.dspace.kernel.ServiceManager; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; -import org.junit.After; import org.junit.Test; /** @@ -36,30 +31,19 @@ * @author mwood */ public class CreateMissingIdentifiersIT - extends AbstractIntegrationTestWithDatabase { - private ServiceManager serviceManager; - private IdentifierServiceImpl identifierService; + extends AbstractIdentifierProviderIT { + private static final String P_TASK_DEF = "plugin.named.org.dspace.curate.CurationTask"; private static final String TASK_NAME = "test"; - @Override - public void setUp() throws Exception { - super.setUp(); - context.turnOffAuthorisationSystem(); - - serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); - identifierService = serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0); - // Clean out providers to avoid any being used for creation of community and collection - identifierService.setProviders(new ArrayList<>()); - } + private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); @Test public void testPerform() throws IOException { // Must remove any cached named plugins before creating a new one CoreServiceFactory.getInstance().getPluginService().clearNamedPluginClasses(); - ConfigurationService configurationService = kernelImpl.getConfigurationService(); // Define a new task dynamically configurationService.setProperty(P_TASK_DEF, CreateMissingIdentifiers.class.getCanonicalName() + " = " + TASK_NAME); @@ -76,7 +60,7 @@ public void testPerform() .build(); /* - * Curate with regular test configuration -- should succeed. + * Curate with default Handle Provider */ curator.curate(context, item); int status = curator.getStatus(TASK_NAME); @@ -92,22 +76,10 @@ public void testPerform() curator.getResult(TASK_NAME)); assertEquals("Curation should fail", Curator.CURATE_ERROR, curator.getStatus(TASK_NAME)); - } - - @Override - @After - public void destroy() throws Exception { - super.destroy(); - DSpaceServicesFactory.getInstance().getServiceManager().getApplicationContext().refresh(); - } - - private void registerProvider(Class type) { - // Register our new provider - serviceManager.registerServiceClass(type.getName(), type); - IdentifierProvider identifierProvider = - (IdentifierProvider) serviceManager.getServiceByName(type.getName(), type); - // Overwrite the identifier-service's providers with the new one to ensure only this provider is used - identifierService.setProviders(List.of(identifierProvider)); + // Unregister this non-default provider + unregisterProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); + // Re-register the default provider (for later tests which may depend on it) + registerProvider(VersionedHandleIdentifierProvider.class); } } diff --git a/dspace-api/src/test/java/org/dspace/identifier/AbstractIdentifierProviderIT.java b/dspace-api/src/test/java/org/dspace/identifier/AbstractIdentifierProviderIT.java new file mode 100644 index 000000000000..6ec9efddf5e2 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/identifier/AbstractIdentifierProviderIT.java @@ -0,0 +1,68 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.identifier; + +import java.util.ArrayList; +import java.util.List; + +import org.dspace.AbstractIntegrationTestWithDatabase; +import org.dspace.kernel.ServiceManager; +import org.dspace.services.factory.DSpaceServicesFactory; + +/** + * AbstractIdentifierProviderIT which contains a few useful utility methods for IdentifierProvider Integration Tests + */ +public class AbstractIdentifierProviderIT extends AbstractIntegrationTestWithDatabase { + + protected final ServiceManager serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); + protected final IdentifierServiceImpl identifierService = + serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0); + + /** + * Register a specific IdentifierProvider into the current IdentifierService (replacing any existing providers). + * This method will also ensure the IdentifierProvider service is registered in the DSpace Service Manager. + * @param type IdentifierProvider Class + */ + protected void registerProvider(Class type) { + // Register our new provider + IdentifierProvider identifierProvider = + (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + if (identifierProvider == null) { + DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); + identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + } + + identifierService.setProviders(List.of(identifierProvider)); + } + + /** + * Unregister a specific IdentifierProvider from the current IdentifierService (removing all existing providers). + * This method will also ensure the IdentifierProvider service is unregistered in the DSpace Service Manager, + * which ensures it does not conflict with other IdentifierProvider services. + * @param type IdentifierProvider Class + */ + protected void unregisterProvider(Class type) { + // Find the provider service + IdentifierProvider identifierProvider = + (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(type.getName(), type); + // If found, unregister it + if (identifierProvider == null) { + DSpaceServicesFactory.getInstance().getServiceManager().unregisterService(type.getName()); + } + + // Overwrite the identifier-service's providers with an empty list + identifierService.setProviders(new ArrayList<>()); + } + +} + + + diff --git a/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java b/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java index 57acf1f1c453..8c0f7e5b5e10 100644 --- a/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java +++ b/dspace-api/src/test/java/org/dspace/identifier/VersionedHandleIdentifierProviderIT.java @@ -11,10 +11,7 @@ import static org.junit.Assert.assertTrue; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.authorize.AuthorizeException; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; @@ -22,15 +19,10 @@ import org.dspace.builder.VersionBuilder; import org.dspace.content.Collection; import org.dspace.content.Item; -import org.dspace.kernel.ServiceManager; -import org.dspace.services.factory.DSpaceServicesFactory; -import org.junit.After; import org.junit.Before; import org.junit.Test; -public class VersionedHandleIdentifierProviderIT extends AbstractIntegrationTestWithDatabase { - private ServiceManager serviceManager; - private IdentifierServiceImpl identifierService; +public class VersionedHandleIdentifierProviderIT extends AbstractIdentifierProviderIT { private String firstHandle; @@ -44,12 +36,6 @@ public class VersionedHandleIdentifierProviderIT extends AbstractIntegrationTest public void setUp() throws Exception { super.setUp(); context.turnOffAuthorisationSystem(); - - serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); - identifierService = serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0); - // Clean out providers to avoid any being used for creation of community and collection - identifierService.setProviders(new ArrayList<>()); - parentCommunity = CommunityBuilder.createCommunity(context) .withName("Parent Community") .build(); @@ -58,33 +44,6 @@ public void setUp() throws Exception { .build(); } - @After - @Override - public void destroy() throws Exception { - super.destroy(); - // After this test has finished running, refresh application context and - // set the expected 'default' versioned handle provider back to ensure other tests don't fail - DSpaceServicesFactory.getInstance().getServiceManager().getApplicationContext().refresh(); - } - - private void registerProvider(Class type) { - // Register our new provider - IdentifierProvider identifierProvider = - (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() - .getServiceByName(type.getName(), type); - if (identifierProvider == null) { - DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type); - identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager() - .getServiceByName(type.getName(), type); - } - - // Overwrite the identifier-service's providers with the new one to ensure only this provider is used - identifierService = DSpaceServicesFactory.getInstance().getServiceManager() - .getServicesByType(IdentifierServiceImpl.class).get(0); - identifierService.setProviders(new ArrayList<>()); - identifierService.setProviders(List.of(identifierProvider)); - } - private void createVersions() throws SQLException, AuthorizeException { itemV1 = ItemBuilder.createItem(context, collection) .withTitle("First version") @@ -96,7 +55,6 @@ private void createVersions() throws SQLException, AuthorizeException { @Test public void testDefaultVersionedHandleProvider() throws Exception { - registerProvider(VersionedHandleIdentifierProvider.class); createVersions(); // Confirm the original item only has its original handle @@ -125,6 +83,11 @@ public void testCanonicalVersionedHandleProvider() throws Exception { assertEquals(firstHandle, itemV3.getHandle()); assertEquals(2, itemV3.getHandles().size()); containsHandle(itemV3, firstHandle + ".3"); + + // Unregister this non-default provider + unregisterProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); + // Re-register the default provider (for later tests) + registerProvider(VersionedHandleIdentifierProvider.class); } private void containsHandle(Item item, String handle) { From ad6d2eb014ec0ae2a3e9ee81970c11e8809da210 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 8 Nov 2024 10:17:31 -0600 Subject: [PATCH 267/632] Update CreateMissingIdentifiers to better identify when CanonicalHandles provider is enabled. Update CreateMissingIdentifiersIT to verify that we are accurately resetting to our default IdentifierProvider (cherry picked from commit 2385c13f2d48048306a1280d88da5d8c022cc24f) --- .../general/CreateMissingIdentifiers.java | 28 +++++++++---------- .../identifier/IdentifierServiceImpl.java | 5 ++++ .../identifier/service/IdentifierService.java | 6 ++++ .../general/CreateMissingIdentifiersIT.java | 17 +++++------ 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/CreateMissingIdentifiers.java b/dspace-api/src/main/java/org/dspace/ctask/general/CreateMissingIdentifiers.java index 9639461426ef..0734d60946bc 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/CreateMissingIdentifiers.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/CreateMissingIdentifiers.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.sql.SQLException; +import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -25,7 +26,6 @@ import org.dspace.identifier.VersionedHandleIdentifierProviderWithCanonicalHandles; import org.dspace.identifier.factory.IdentifierServiceFactory; import org.dspace.identifier.service.IdentifierService; -import org.dspace.services.factory.DSpaceServicesFactory; /** * Ensure that an object has all of the identifiers that it should, minting them @@ -45,20 +45,6 @@ public int perform(DSpaceObject dso) return Curator.CURATE_SKIP; } - // XXX Temporary escape when an incompatible provider is configured. - // XXX Remove this when the provider is fixed. - boolean compatible = DSpaceServicesFactory - .getInstance() - .getServiceManager() - .getServiceByName( - VersionedHandleIdentifierProviderWithCanonicalHandles.class.getCanonicalName(), - IdentifierProvider.class) == null; - if (!compatible) { - setResult("This task is not compatible with VersionedHandleIdentifierProviderWithCanonicalHandles"); - return Curator.CURATE_ERROR; - } - // XXX End of escape - String typeText = Constants.typeText[dso.getType()]; // Get a Context @@ -75,6 +61,18 @@ public int perform(DSpaceObject dso) .getInstance() .getIdentifierService(); + // XXX Temporary escape when an incompatible provider is configured. + // XXX Remove this when the provider is fixed. + List providerList = identifierService.getProviders(); + boolean compatible = + providerList.stream().noneMatch(p -> p instanceof VersionedHandleIdentifierProviderWithCanonicalHandles); + + if (!compatible) { + setResult("This task is not compatible with VersionedHandleIdentifierProviderWithCanonicalHandles"); + return Curator.CURATE_ERROR; + } + // XXX End of escape + // Register any missing identifiers. try { identifierService.register(context, dso); diff --git a/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java b/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java index b98aea24fa08..e6dcfcdda693 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java @@ -57,6 +57,11 @@ public void setProviders(List providers) { } } + @Override + public List getProviders() { + return this.providers; + } + /** * Reserves identifiers for the item * diff --git a/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java b/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java index 23005b657508..45bf3c6dea8a 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java +++ b/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java @@ -19,6 +19,7 @@ import org.dspace.identifier.IdentifierException; import org.dspace.identifier.IdentifierNotFoundException; import org.dspace.identifier.IdentifierNotResolvableException; +import org.dspace.identifier.IdentifierProvider; /** * @author Fabio Bolognesi (fabio at atmire dot com) @@ -194,4 +195,9 @@ void register(Context context, DSpaceObject dso, String identifier) void delete(Context context, DSpaceObject dso, String identifier) throws AuthorizeException, SQLException, IdentifierException; + /** + * Get List of currently enabled IdentifierProviders + * @return List of enabled IdentifierProvider objects. + */ + List getProviders(); } diff --git a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java index 4934404c3b3e..3b50258a5a23 100644 --- a/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java +++ b/dspace-api/src/test/java/org/dspace/ctask/general/CreateMissingIdentifiersIT.java @@ -60,14 +60,7 @@ public void testPerform() .build(); /* - * Curate with default Handle Provider - */ - curator.curate(context, item); - int status = curator.getStatus(TASK_NAME); - assertEquals("Curation should succeed", Curator.CURATE_SUCCESS, status); - - /* - * Now install an incompatible provider to make the task fail. + * First, install an incompatible provider to make the task fail. */ registerProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); @@ -81,5 +74,13 @@ public void testPerform() unregisterProvider(VersionedHandleIdentifierProviderWithCanonicalHandles.class); // Re-register the default provider (for later tests which may depend on it) registerProvider(VersionedHandleIdentifierProvider.class); + + /* + * Now, verify curate with default Handle Provider works + * (and that our re-registration of the default provider above was successful) + */ + curator.curate(context, item); + int status = curator.getStatus(TASK_NAME); + assertEquals("Curation should succeed", Curator.CURATE_SUCCESS, status); } } From 97a5439e3aa23bfde4f9741282d48c10a873b387 Mon Sep 17 00:00:00 2001 From: "Gantner, Florian Klaus" Date: Thu, 9 Jan 2025 14:09:24 +0100 Subject: [PATCH 268/632] switch IT search core to MockSolrSearchCore https://github.com/DSpace/DSpace/issues/10188 (cherry picked from commit 6d781e8f83a912863af8d998d982e030db64a2ce) --- .../org/dspace/content/VersioningWithRelationshipsIT.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java index 3acc4ca146ee..9ff452f7895f 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java @@ -59,7 +59,7 @@ import org.dspace.content.virtual.VirtualMetadataConfiguration; import org.dspace.content.virtual.VirtualMetadataPopulator; import org.dspace.core.Constants; -import org.dspace.discovery.SolrSearchCore; +import org.dspace.discovery.MockSolrSearchCore; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.Version; @@ -79,8 +79,9 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa ContentServiceFactory.getInstance().getInstallItemService(); private final ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - private final SolrSearchCore solrSearchCore = - DSpaceServicesFactory.getInstance().getServiceManager().getServicesByType(SolrSearchCore.class).get(0); + private final MockSolrSearchCore solrSearchCore = + DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(null, MockSolrSearchCore.class); + protected Community community; protected Collection collection; protected EntityType publicationEntityType; From fb47b27a2b55f59b3cf3c3cf77401ec9ef0ea594 Mon Sep 17 00:00:00 2001 From: "Gantner, Florian Klaus" Date: Thu, 9 Jan 2025 14:09:24 +0100 Subject: [PATCH 269/632] switch IT search core to MockSolrSearchCore https://github.com/DSpace/DSpace/issues/10188 (cherry picked from commit 6d781e8f83a912863af8d998d982e030db64a2ce) --- .../org/dspace/content/VersioningWithRelationshipsIT.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java index 3acc4ca146ee..9ff452f7895f 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningWithRelationshipsIT.java @@ -59,7 +59,7 @@ import org.dspace.content.virtual.VirtualMetadataConfiguration; import org.dspace.content.virtual.VirtualMetadataPopulator; import org.dspace.core.Constants; -import org.dspace.discovery.SolrSearchCore; +import org.dspace.discovery.MockSolrSearchCore; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.Version; @@ -79,8 +79,9 @@ public class VersioningWithRelationshipsIT extends AbstractIntegrationTestWithDa ContentServiceFactory.getInstance().getInstallItemService(); private final ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - private final SolrSearchCore solrSearchCore = - DSpaceServicesFactory.getInstance().getServiceManager().getServicesByType(SolrSearchCore.class).get(0); + private final MockSolrSearchCore solrSearchCore = + DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(null, MockSolrSearchCore.class); + protected Community community; protected Collection collection; protected EntityType publicationEntityType; From 49b3deef77055a18daba21c0bf2812bb2daa3265 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 9 Jan 2025 15:42:25 -0600 Subject: [PATCH 270/632] Refactor AbstractIntegrationTestWithDatabase to use Builders to create test EPersons. (cherry picked from commit 0b8b7be22b88a411898bcb975e238e7cd96f40ab) --- .../AbstractIntegrationTestWithDatabase.java | 48 ++++++++----------- .../AbstractWebClientIntegrationTest.java | 16 +++++++ 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java b/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java index e27fb19a68eb..d5bb6ab8a4c8 100644 --- a/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java +++ b/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java @@ -17,8 +17,8 @@ import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; import org.dspace.authority.AuthoritySearchService; import org.dspace.authority.MockAuthoritySolrServiceImpl; -import org.dspace.authorize.AuthorizeException; import org.dspace.builder.AbstractBuilder; +import org.dspace.builder.EPersonBuilder; import org.dspace.content.Community; import org.dspace.core.Context; import org.dspace.core.I18nUtil; @@ -114,19 +114,16 @@ public void setUp() throws Exception { EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); eperson = ePersonService.findByEmail(context, "test@email.com"); if (eperson == null) { - // This EPerson creation should only happen once (i.e. for first test run) - log.info("Creating initial EPerson (email=test@email.com) for Unit Tests"); - eperson = ePersonService.create(context); - eperson.setFirstName(context, "first"); - eperson.setLastName(context, "last"); - eperson.setEmail("test@email.com"); - eperson.setCanLogIn(true); - eperson.setLanguage(context, I18nUtil.getDefaultLocale().getLanguage()); - ePersonService.setPassword(eperson, password); - // actually save the eperson to unit testing DB - ePersonService.update(context, eperson); + // Create test EPerson for usage in all tests + log.info("Creating Test EPerson (email=test@email.com) for Integration Tests"); + eperson = EPersonBuilder.createEPerson(context) + .withNameInMetadata("first", "last") + .withEmail("test@email.com") + .withCanLogin(true) + .withLanguage(I18nUtil.getDefaultLocale().getLanguage()) + .withPassword(password) + .build(); } - // Set our global test EPerson as the current user in DSpace context.setCurrentUser(eperson); @@ -135,26 +132,23 @@ public void setUp() throws Exception { admin = ePersonService.findByEmail(context, "admin@email.com"); if (admin == null) { - // This EPerson creation should only happen once (i.e. for first test run) - log.info("Creating initial EPerson (email=admin@email.com) for Unit Tests"); - admin = ePersonService.create(context); - admin.setFirstName(context, "first (admin)"); - admin.setLastName(context, "last (admin)"); - admin.setEmail("admin@email.com"); - admin.setCanLogIn(true); - admin.setLanguage(context, I18nUtil.getDefaultLocale().getLanguage()); - ePersonService.setPassword(admin, password); - // actually save the eperson to unit testing DB - ePersonService.update(context, admin); + // Create test Administrator for usage in all tests + log.info("Creating Test Admin EPerson (email=admin@email.com) for Integration Tests"); + admin = EPersonBuilder.createEPerson(context) + .withNameInMetadata("first (admin)", "last (admin)") + .withEmail("admin@email.com") + .withCanLogin(true) + .withLanguage(I18nUtil.getDefaultLocale().getLanguage()) + .withPassword(password) + .build(); + + // Add Test Administrator to the ADMIN group in test database GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); Group adminGroup = groupService.findByName(context, Group.ADMIN); groupService.addMember(context, adminGroup, admin); } context.restoreAuthSystemState(); - } catch (AuthorizeException ex) { - log.error("Error creating initial eperson or default groups", ex); - fail("Error creating initial eperson or default groups in AbstractUnitTest init()"); } catch (SQLException ex) { log.error(ex.getMessage(), ex); fail("SQL Error on AbstractUnitTest init()"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java index df6afcb16e32..fadebff7de5b 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java @@ -12,6 +12,7 @@ import org.dspace.app.rest.Application; import org.dspace.app.rest.utils.DSpaceConfigurationInitializer; import org.dspace.app.rest.utils.DSpaceKernelInitializer; +import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -64,6 +65,21 @@ public class AbstractWebClientIntegrationTest extends AbstractIntegrationTestWit @Autowired protected ApplicationContext applicationContext; + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + + // Because AbstractWebClientIntegrationTest starts a new webserver, we need to ensure *everything* created by + // the "super.setUp()" script is committed to the test database. Otherwise, the new webserver may not see the + // created test data in the database. + // NOTE: This commit() does NOT occur in AbstractIntegrationTestDatabase because it will remove newly created + // Hibernate entities from the current Hibernate session. For most ITs we don't want that as it may result + // in "could not initialize proxy - no Session" errors when using those entities in other tests (or other tests + // would need to reload each test entity back into the Hibernate session) + context.commit(); + } + /** * Get client TestRestTemplate for making HTTP requests to test webserver * @return TestRestTemplate From 391ba5d7a774e4aea8d1351229a83b58220afe51 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 9 Jan 2025 15:42:25 -0600 Subject: [PATCH 271/632] Refactor AbstractIntegrationTestWithDatabase to use Builders to create test EPersons. (cherry picked from commit 0b8b7be22b88a411898bcb975e238e7cd96f40ab) --- .../AbstractIntegrationTestWithDatabase.java | 48 ++++++++----------- .../AbstractWebClientIntegrationTest.java | 16 +++++++ 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java b/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java index 9bacbb97eec4..76b3fe131be0 100644 --- a/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java +++ b/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java @@ -20,8 +20,8 @@ import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; import org.dspace.authority.AuthoritySearchService; import org.dspace.authority.MockAuthoritySolrServiceImpl; -import org.dspace.authorize.AuthorizeException; import org.dspace.builder.AbstractBuilder; +import org.dspace.builder.EPersonBuilder; import org.dspace.content.Community; import org.dspace.core.Context; import org.dspace.core.I18nUtil; @@ -127,19 +127,16 @@ public void setUp() throws Exception { EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); eperson = ePersonService.findByEmail(context, "test@email.com"); if (eperson == null) { - // This EPerson creation should only happen once (i.e. for first test run) - log.info("Creating initial EPerson (email=test@email.com) for Unit Tests"); - eperson = ePersonService.create(context); - eperson.setFirstName(context, "first"); - eperson.setLastName(context, "last"); - eperson.setEmail("test@email.com"); - eperson.setCanLogIn(true); - eperson.setLanguage(context, I18nUtil.getDefaultLocale().getLanguage()); - ePersonService.setPassword(eperson, password); - // actually save the eperson to unit testing DB - ePersonService.update(context, eperson); + // Create test EPerson for usage in all tests + log.info("Creating Test EPerson (email=test@email.com) for Integration Tests"); + eperson = EPersonBuilder.createEPerson(context) + .withNameInMetadata("first", "last") + .withEmail("test@email.com") + .withCanLogin(true) + .withLanguage(I18nUtil.getDefaultLocale().getLanguage()) + .withPassword(password) + .build(); } - // Set our global test EPerson as the current user in DSpace context.setCurrentUser(eperson); @@ -148,26 +145,23 @@ public void setUp() throws Exception { admin = ePersonService.findByEmail(context, "admin@email.com"); if (admin == null) { - // This EPerson creation should only happen once (i.e. for first test run) - log.info("Creating initial EPerson (email=admin@email.com) for Unit Tests"); - admin = ePersonService.create(context); - admin.setFirstName(context, "first (admin)"); - admin.setLastName(context, "last (admin)"); - admin.setEmail("admin@email.com"); - admin.setCanLogIn(true); - admin.setLanguage(context, I18nUtil.getDefaultLocale().getLanguage()); - ePersonService.setPassword(admin, password); - // actually save the eperson to unit testing DB - ePersonService.update(context, admin); + // Create test Administrator for usage in all tests + log.info("Creating Test Admin EPerson (email=admin@email.com) for Integration Tests"); + admin = EPersonBuilder.createEPerson(context) + .withNameInMetadata("first (admin)", "last (admin)") + .withEmail("admin@email.com") + .withCanLogin(true) + .withLanguage(I18nUtil.getDefaultLocale().getLanguage()) + .withPassword(password) + .build(); + + // Add Test Administrator to the ADMIN group in test database GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); Group adminGroup = groupService.findByName(context, Group.ADMIN); groupService.addMember(context, adminGroup, admin); } context.restoreAuthSystemState(); - } catch (AuthorizeException ex) { - log.error("Error creating initial eperson or default groups", ex); - fail("Error creating initial eperson or default groups in AbstractUnitTest init()"); } catch (SQLException ex) { log.error(ex.getMessage(), ex); fail("SQL Error on AbstractUnitTest init()"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java index e4ef1c741f72..f7ec1e941d0e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java @@ -12,6 +12,7 @@ import org.dspace.app.TestApplication; import org.dspace.app.rest.utils.DSpaceConfigurationInitializer; import org.dspace.app.rest.utils.DSpaceKernelInitializer; +import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -64,6 +65,21 @@ public class AbstractWebClientIntegrationTest extends AbstractIntegrationTestWit @Autowired protected ApplicationContext applicationContext; + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + + // Because AbstractWebClientIntegrationTest starts a new webserver, we need to ensure *everything* created by + // the "super.setUp()" script is committed to the test database. Otherwise, the new webserver may not see the + // created test data in the database. + // NOTE: This commit() does NOT occur in AbstractIntegrationTestDatabase because it will remove newly created + // Hibernate entities from the current Hibernate session. For most ITs we don't want that as it may result + // in "could not initialize proxy - no Session" errors when using those entities in other tests (or other tests + // would need to reload each test entity back into the Hibernate session) + context.commit(); + } + /** * Get client TestRestTemplate for making HTTP requests to test webserver * @return TestRestTemplate From 5973c67eff7180496ee761a32fa1f9636b02c93e Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 16:58:00 +0200 Subject: [PATCH 272/632] put DOIs in dc.identifier.doi (cherry picked from commit 3d1bef9d0e3fe820da9705427c129b5cb49d66fb) --- dspace/config/spring/api/scopus-integration.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/spring/api/scopus-integration.xml b/dspace/config/spring/api/scopus-integration.xml index 47c5a4fbb900..6f7556574d09 100644 --- a/dspace/config/spring/api/scopus-integration.xml +++ b/dspace/config/spring/api/scopus-integration.xml @@ -128,7 +128,7 @@ - + @@ -264,4 +264,4 @@ - \ No newline at end of file + From 5d0e9871e9ec4cbacda577f9f2ae8cefcd961e27 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 17:37:07 +0200 Subject: [PATCH 273/632] fix broken test (cherry picked from commit 2eff833fab361d4ed3c7b602b681823911f989af) --- .../dspace/app/rest/ScopusImportMetadataSourceServiceIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java index 7f6cb53ce400..e81f662ad5a9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java @@ -124,7 +124,7 @@ private ArrayList getRecords() { ArrayList records = new ArrayList<>(); //define first record List metadatums = new ArrayList(); - MetadatumDTO doi = createMetadatumDTO("dc", "identifier", null, "10.3934/mine.2023004"); + MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023004"); MetadatumDTO title = createMetadatumDTO("dc","title", null, "Hardy potential versus lower order terms in Dirichlet problems: regularizing effects"); MetadatumDTO type = createMetadatumDTO("dc", "type", null, "Journal"); @@ -171,7 +171,7 @@ private ArrayList getRecords() { //define second record List metadatums2 = new ArrayList(); - MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", null, "10.3934/mine.2023001"); + MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023001"); MetadatumDTO title2 = createMetadatumDTO("dc","title", null, "Large deviations for a binary collision model: energy evaporation"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2023-01-01"); From 09a722a029ebc6e50835c360af8977d97cb1c033 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 17 Oct 2024 20:17:06 +0200 Subject: [PATCH 274/632] use dc.relation.hasversion for externally generated DOIs (cherry picked from commit 29067b6572b538650e4686e983edafcc355d87c5) --- dspace/config/spring/api/scopus-integration.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace/config/spring/api/scopus-integration.xml b/dspace/config/spring/api/scopus-integration.xml index 6f7556574d09..d3e8150c74b1 100644 --- a/dspace/config/spring/api/scopus-integration.xml +++ b/dspace/config/spring/api/scopus-integration.xml @@ -128,7 +128,7 @@ - + From d109eac2a0ad170b656e36028d84fc294ae6eb35 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 17 Oct 2024 20:19:04 +0200 Subject: [PATCH 275/632] use dc.relation.hasversion instead of dc.identifier.doi (cherry picked from commit d61dc8d911a4d226362d9a554226da5c304ad722) --- .../dspace/app/rest/ScopusImportMetadataSourceServiceIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java index e81f662ad5a9..f9164ddc5994 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java @@ -124,7 +124,7 @@ private ArrayList getRecords() { ArrayList records = new ArrayList<>(); //define first record List metadatums = new ArrayList(); - MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023004"); + MetadatumDTO doi = createMetadatumDTO("dc", "relation", "hasversion", "10.3934/mine.2023004"); MetadatumDTO title = createMetadatumDTO("dc","title", null, "Hardy potential versus lower order terms in Dirichlet problems: regularizing effects"); MetadatumDTO type = createMetadatumDTO("dc", "type", null, "Journal"); @@ -171,7 +171,7 @@ private ArrayList getRecords() { //define second record List metadatums2 = new ArrayList(); - MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023001"); + MetadatumDTO doi2 = createMetadatumDTO("dc", "relation", "hasversion", "10.3934/mine.2023001"); MetadatumDTO title2 = createMetadatumDTO("dc","title", null, "Large deviations for a binary collision model: energy evaporation"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2023-01-01"); From 07a478b31add75b1653c0e1f78971935b9353e81 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 16:58:00 +0200 Subject: [PATCH 276/632] put DOIs in dc.identifier.doi (cherry picked from commit 3d1bef9d0e3fe820da9705427c129b5cb49d66fb) --- dspace/config/spring/api/scopus-integration.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/spring/api/scopus-integration.xml b/dspace/config/spring/api/scopus-integration.xml index 47c5a4fbb900..6f7556574d09 100644 --- a/dspace/config/spring/api/scopus-integration.xml +++ b/dspace/config/spring/api/scopus-integration.xml @@ -128,7 +128,7 @@ - + @@ -264,4 +264,4 @@ - \ No newline at end of file + From 7a24605c0ac0426af6b3042d23bb28ab0e755727 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 17:37:07 +0200 Subject: [PATCH 277/632] fix broken test (cherry picked from commit 2eff833fab361d4ed3c7b602b681823911f989af) --- .../dspace/app/rest/ScopusImportMetadataSourceServiceIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java index 7f6cb53ce400..e81f662ad5a9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java @@ -124,7 +124,7 @@ private ArrayList getRecords() { ArrayList records = new ArrayList<>(); //define first record List metadatums = new ArrayList(); - MetadatumDTO doi = createMetadatumDTO("dc", "identifier", null, "10.3934/mine.2023004"); + MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023004"); MetadatumDTO title = createMetadatumDTO("dc","title", null, "Hardy potential versus lower order terms in Dirichlet problems: regularizing effects"); MetadatumDTO type = createMetadatumDTO("dc", "type", null, "Journal"); @@ -171,7 +171,7 @@ private ArrayList getRecords() { //define second record List metadatums2 = new ArrayList(); - MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", null, "10.3934/mine.2023001"); + MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023001"); MetadatumDTO title2 = createMetadatumDTO("dc","title", null, "Large deviations for a binary collision model: energy evaporation"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2023-01-01"); From 0416be3802e522638eb3012c52655f820303f76e Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 17 Oct 2024 20:17:06 +0200 Subject: [PATCH 278/632] use dc.relation.hasversion for externally generated DOIs (cherry picked from commit 29067b6572b538650e4686e983edafcc355d87c5) --- dspace/config/spring/api/scopus-integration.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace/config/spring/api/scopus-integration.xml b/dspace/config/spring/api/scopus-integration.xml index 6f7556574d09..d3e8150c74b1 100644 --- a/dspace/config/spring/api/scopus-integration.xml +++ b/dspace/config/spring/api/scopus-integration.xml @@ -128,7 +128,7 @@ - + From 8be99e47fa0acb8950ee53a9f2dad2bf39b5c8be Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 17 Oct 2024 20:19:04 +0200 Subject: [PATCH 279/632] use dc.relation.hasversion instead of dc.identifier.doi (cherry picked from commit d61dc8d911a4d226362d9a554226da5c304ad722) --- .../dspace/app/rest/ScopusImportMetadataSourceServiceIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java index e81f662ad5a9..f9164ddc5994 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java @@ -124,7 +124,7 @@ private ArrayList getRecords() { ArrayList records = new ArrayList<>(); //define first record List metadatums = new ArrayList(); - MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023004"); + MetadatumDTO doi = createMetadatumDTO("dc", "relation", "hasversion", "10.3934/mine.2023004"); MetadatumDTO title = createMetadatumDTO("dc","title", null, "Hardy potential versus lower order terms in Dirichlet problems: regularizing effects"); MetadatumDTO type = createMetadatumDTO("dc", "type", null, "Journal"); @@ -171,7 +171,7 @@ private ArrayList getRecords() { //define second record List metadatums2 = new ArrayList(); - MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023001"); + MetadatumDTO doi2 = createMetadatumDTO("dc", "relation", "hasversion", "10.3934/mine.2023001"); MetadatumDTO title2 = createMetadatumDTO("dc","title", null, "Large deviations for a binary collision model: energy evaporation"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2023-01-01"); From 7ed3d326a8cb682c8b39406966348d9eeee5ce05 Mon Sep 17 00:00:00 2001 From: "Gantner, Florian Klaus" Date: Tue, 8 Oct 2024 13:42:07 +0200 Subject: [PATCH 280/632] option to exclude the submitter being indexed to solr in archived items https://github.com/DSpace/DSpace/issues/9660 (cherry picked from commit 8ed2cdcff7bbefb14e6e48fbc2731f2c9da67e98) --- .../indexobject/ItemIndexFactoryImpl.java | 8 +- .../org/dspace/discovery/DiscoveryIT.java | 109 ++++++++++++++++++ dspace/config/modules/discovery.cfg | 7 +- 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java index 7cdb8b93d80e..5fb2f779783c 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java @@ -154,9 +154,11 @@ public SolrInputDocument buildDocument(Context context, IndexableItem indexableI doc.addField("latestVersion", isLatestVersion(context, item)); EPerson submitter = item.getSubmitter(); - if (submitter != null) { - addFacetIndex(doc, "submitter", submitter.getID().toString(), - submitter.getFullName()); + if (submitter != null && !(DSpaceServicesFactory.getInstance().getConfigurationService().getBooleanProperty( + "discovery.index.item.submitter.enabled", false))) { + doc.addField("submitter_authority", submitter.getID().toString()); + } else if (submitter != null) { + addFacetIndex(doc, "submitter", submitter.getID().toString(), submitter.getFullName()); } // Add the item metadata diff --git a/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java b/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java index 6bc79cad558b..63ff93b6f387 100644 --- a/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java +++ b/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java @@ -8,6 +8,10 @@ package org.dspace.discovery; import static org.dspace.discovery.SolrServiceWorkspaceWorkflowRestrictionPlugin.DISCOVER_WORKSPACE_CONFIGURATION_NAME; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -21,6 +25,10 @@ import java.util.stream.Collectors; import jakarta.servlet.http.HttpServletRequest; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.common.SolrDocument; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; @@ -99,6 +107,9 @@ public class DiscoveryIT extends AbstractIntegrationTestWithDatabase { MetadataAuthorityService metadataAuthorityService = ContentAuthorityServiceFactory.getInstance() .getMetadataAuthorityService(); + MockSolrSearchCore solrSearchCore = DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(null, MockSolrSearchCore.class); + @Override @Before public void setUp() throws Exception { @@ -796,6 +807,104 @@ public void searchWithDefaultSortServiceTest() throws SearchServiceException { } } + /** + * Test designed to check if the submitter is not indexed in all in solr documents for items + * and the submitter authority is still indexed + * @throws SearchServiceException + */ + @Test + public void searchWithNoSubmitterTest() throws SearchServiceException { + + configurationService.setProperty("discovery.index.item.submitter.enabled", false); + DiscoveryConfiguration defaultConf = SearchUtils.getDiscoveryConfiguration(context, "default", null); + + // Populate the testing objects: create items in eperson's workspace and perform search in it + int numberItems = 10; + context.turnOffAuthorisationSystem(); + EPerson submitter = null; + try { + submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.org") + .withNameInMetadata("Peter", "Funny").build(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + context.setCurrentUser(submitter); + Community community = CommunityBuilder.createCommunity(context).build(); + Collection collection = CollectionBuilder.createCollection(context, community).build(); + for (int i = 0; i < numberItems; i++) { + ItemBuilder.createItem(context, collection) + .withTitle("item " + i) + .build(); + } + context.restoreAuthSystemState(); + + // Build query with default parameters (except for workspaceConf) + QueryResponse result = null; + try { + result = solrSearchCore.getSolr().query(new SolrQuery(String.format( + "search.resourcetype:\"Item\""))); + } catch (SolrServerException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + assertEquals(result.getResults().size(), numberItems); + for (SolrDocument doc : result.getResults()) { + assertThat(doc.getFieldNames(), + not(hasItems("submitter_keyword", "submitter_ac", "submitter_acid", "submitter_filter"))); + assertThat(doc.getFieldNames(), hasItem("submitter_authority")); + } + } + + /** + * Test designed to check if the submitter is indexed in all in solr documents for items + * @throws SearchServiceException + */ + @Test + public void searchWithSubmitterTest() throws SearchServiceException { + + configurationService.setProperty("discovery.index.item.submitter.enabled", true); + DiscoveryConfiguration defaultConf = SearchUtils.getDiscoveryConfiguration(context, "default", null); + + // Populate the testing objects: create items in eperson's workspace and perform search in it + int numberItems = 10; + context.turnOffAuthorisationSystem(); + EPerson submitter = null; + try { + submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.org") + .withNameInMetadata("Peter", "Funny").build(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + context.setCurrentUser(submitter); + Community community = CommunityBuilder.createCommunity(context).build(); + Collection collection = CollectionBuilder.createCollection(context, community).build(); + for (int i = 0; i < numberItems; i++) { + ItemBuilder.createItem(context, collection) + .withTitle("item " + i) + .build(); + } + context.restoreAuthSystemState(); + + // Build query with default parameters (except for workspaceConf) + QueryResponse result = null; + try { + result = solrSearchCore.getSolr().query(new SolrQuery(String.format( + "search.resourcetype:\"Item\""))); + } catch (SolrServerException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + assertEquals(result.getResults().size(), numberItems); + for (SolrDocument doc : result.getResults()) { + for (String fieldname : doc.getFieldNames()) { + assertThat(doc.getFieldNames(), hasItems("submitter_keyword","submitter_ac", "submitter_filter", + "submitter_authority")); + } + } + } + private void assertSearchQuery(String resourceType, int size) throws SearchServiceException { assertSearchQuery(resourceType, size, size, 0, -1); } diff --git a/dspace/config/modules/discovery.cfg b/dspace/config/modules/discovery.cfg index 72088ddc49fa..cd8e8636c2e3 100644 --- a/dspace/config/modules/discovery.cfg +++ b/dspace/config/modules/discovery.cfg @@ -24,6 +24,11 @@ discovery.search.server = ${solr.server}/${solr.multicorePrefix}search # discovery.index.ignore-authority = false discovery.index.projection=dc.title,dc.contributor.*,dc.date.issued +# Restricts the indexing of the submitter for archived items +# By default the submitter information from the corresponding eperson is not indexed. +# If you set this value to true, than the submitter information is indexed and you will need to reindex search core +# discovery.index.item.submitter.enabled = false + # Allow auto-reindexing. # If any database migrations are applied to your database (via Flyway), then a # reindex flag is always written to '[dspace]/solr/search/conf/reindex.flag'. @@ -48,4 +53,4 @@ discovery.facet.namedtype.workflow.pooled = 004workflow\n|||\nWaiting for Contro # Set the number of retry of a query when stale objects are found. # Set to -1 if stale objects should be ignored. Set to 0 if you want to avoid extra query but take the chance to cleanup # the index each time that stale objects are found. Default 3 -discovery.removestale.attempts = 3 \ No newline at end of file +discovery.removestale.attempts = 3 From 62596ad86313053f56fa316fba62ff1156cbeb37 Mon Sep 17 00:00:00 2001 From: "Gantner, Florian Klaus" Date: Tue, 8 Oct 2024 13:42:07 +0200 Subject: [PATCH 281/632] option to exclude the submitter being indexed to solr in archived items https://github.com/DSpace/DSpace/issues/9660 --- .../indexobject/ItemIndexFactoryImpl.java | 8 +- .../org/dspace/discovery/DiscoveryIT.java | 109 ++++++++++++++++++ dspace/config/modules/discovery.cfg | 7 +- 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java index 7cdb8b93d80e..5fb2f779783c 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java @@ -154,9 +154,11 @@ public SolrInputDocument buildDocument(Context context, IndexableItem indexableI doc.addField("latestVersion", isLatestVersion(context, item)); EPerson submitter = item.getSubmitter(); - if (submitter != null) { - addFacetIndex(doc, "submitter", submitter.getID().toString(), - submitter.getFullName()); + if (submitter != null && !(DSpaceServicesFactory.getInstance().getConfigurationService().getBooleanProperty( + "discovery.index.item.submitter.enabled", false))) { + doc.addField("submitter_authority", submitter.getID().toString()); + } else if (submitter != null) { + addFacetIndex(doc, "submitter", submitter.getID().toString(), submitter.getFullName()); } // Add the item metadata diff --git a/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java b/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java index 55be531418ae..159f7a0ac5ae 100644 --- a/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java +++ b/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java @@ -8,6 +8,10 @@ package org.dspace.discovery; import static org.dspace.discovery.SolrServiceWorkspaceWorkflowRestrictionPlugin.DISCOVER_WORKSPACE_CONFIGURATION_NAME; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -21,6 +25,10 @@ import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.common.SolrDocument; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; @@ -99,6 +107,9 @@ public class DiscoveryIT extends AbstractIntegrationTestWithDatabase { MetadataAuthorityService metadataAuthorityService = ContentAuthorityServiceFactory.getInstance() .getMetadataAuthorityService(); + MockSolrSearchCore solrSearchCore = DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(null, MockSolrSearchCore.class); + @Override @Before public void setUp() throws Exception { @@ -796,6 +807,104 @@ public void searchWithDefaultSortServiceTest() throws SearchServiceException { } } + /** + * Test designed to check if the submitter is not indexed in all in solr documents for items + * and the submitter authority is still indexed + * @throws SearchServiceException + */ + @Test + public void searchWithNoSubmitterTest() throws SearchServiceException { + + configurationService.setProperty("discovery.index.item.submitter.enabled", false); + DiscoveryConfiguration defaultConf = SearchUtils.getDiscoveryConfiguration(context, "default", null); + + // Populate the testing objects: create items in eperson's workspace and perform search in it + int numberItems = 10; + context.turnOffAuthorisationSystem(); + EPerson submitter = null; + try { + submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.org") + .withNameInMetadata("Peter", "Funny").build(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + context.setCurrentUser(submitter); + Community community = CommunityBuilder.createCommunity(context).build(); + Collection collection = CollectionBuilder.createCollection(context, community).build(); + for (int i = 0; i < numberItems; i++) { + ItemBuilder.createItem(context, collection) + .withTitle("item " + i) + .build(); + } + context.restoreAuthSystemState(); + + // Build query with default parameters (except for workspaceConf) + QueryResponse result = null; + try { + result = solrSearchCore.getSolr().query(new SolrQuery(String.format( + "search.resourcetype:\"Item\""))); + } catch (SolrServerException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + assertEquals(result.getResults().size(), numberItems); + for (SolrDocument doc : result.getResults()) { + assertThat(doc.getFieldNames(), + not(hasItems("submitter_keyword", "submitter_ac", "submitter_acid", "submitter_filter"))); + assertThat(doc.getFieldNames(), hasItem("submitter_authority")); + } + } + + /** + * Test designed to check if the submitter is indexed in all in solr documents for items + * @throws SearchServiceException + */ + @Test + public void searchWithSubmitterTest() throws SearchServiceException { + + configurationService.setProperty("discovery.index.item.submitter.enabled", true); + DiscoveryConfiguration defaultConf = SearchUtils.getDiscoveryConfiguration(context, "default", null); + + // Populate the testing objects: create items in eperson's workspace and perform search in it + int numberItems = 10; + context.turnOffAuthorisationSystem(); + EPerson submitter = null; + try { + submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.org") + .withNameInMetadata("Peter", "Funny").build(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + context.setCurrentUser(submitter); + Community community = CommunityBuilder.createCommunity(context).build(); + Collection collection = CollectionBuilder.createCollection(context, community).build(); + for (int i = 0; i < numberItems; i++) { + ItemBuilder.createItem(context, collection) + .withTitle("item " + i) + .build(); + } + context.restoreAuthSystemState(); + + // Build query with default parameters (except for workspaceConf) + QueryResponse result = null; + try { + result = solrSearchCore.getSolr().query(new SolrQuery(String.format( + "search.resourcetype:\"Item\""))); + } catch (SolrServerException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + assertEquals(result.getResults().size(), numberItems); + for (SolrDocument doc : result.getResults()) { + for (String fieldname : doc.getFieldNames()) { + assertThat(doc.getFieldNames(), hasItems("submitter_keyword","submitter_ac", "submitter_filter", + "submitter_authority")); + } + } + } + private void assertSearchQuery(String resourceType, int size) throws SearchServiceException { assertSearchQuery(resourceType, size, size, 0, -1); } diff --git a/dspace/config/modules/discovery.cfg b/dspace/config/modules/discovery.cfg index 72088ddc49fa..cd8e8636c2e3 100644 --- a/dspace/config/modules/discovery.cfg +++ b/dspace/config/modules/discovery.cfg @@ -24,6 +24,11 @@ discovery.search.server = ${solr.server}/${solr.multicorePrefix}search # discovery.index.ignore-authority = false discovery.index.projection=dc.title,dc.contributor.*,dc.date.issued +# Restricts the indexing of the submitter for archived items +# By default the submitter information from the corresponding eperson is not indexed. +# If you set this value to true, than the submitter information is indexed and you will need to reindex search core +# discovery.index.item.submitter.enabled = false + # Allow auto-reindexing. # If any database migrations are applied to your database (via Flyway), then a # reindex flag is always written to '[dspace]/solr/search/conf/reindex.flag'. @@ -48,4 +53,4 @@ discovery.facet.namedtype.workflow.pooled = 004workflow\n|||\nWaiting for Contro # Set the number of retry of a query when stale objects are found. # Set to -1 if stale objects should be ignored. Set to 0 if you want to avoid extra query but take the chance to cleanup # the index each time that stale objects are found. Default 3 -discovery.removestale.attempts = 3 \ No newline at end of file +discovery.removestale.attempts = 3 From 59ea5cd0eea61f87a668a29d7233b45a33908586 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 28 Oct 2024 14:55:30 -0500 Subject: [PATCH 282/632] Create dependabot.yml --- .github/dependabot.yml | 115 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000000..6f4f3ae601a0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,115 @@ +#------------------- +# DSpace's dependabot rules. Enables maven updates for all dependencies on a weekly basis +# for main and any maintenance branches. Security updates only apply to main. +#------------------- +version: 2 +updates: + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "weekly" + # Allow up to 10 open PRs for dependencies + open-pull-requests-limit: 10 + # Group together some upgrades in a single PR + groups: + # Group together all Build Tools in a single PR + build-tools: + applies-to: version-updates + patterns: + - "org.apache.maven.plugins:*" + - "*:*-maven-plugin" + - "*:maven-*-plugin" + - "com.github.spotbugs:spotbugs" + - "com.google.code.findbugs:*" + - "com.google.errorprone:*" + - "com.puppycrawl.tools:checkstyle" + - "org.sonatype.plugins:*" + update-types: + - "minor" + - "patch" + test-tools: + applies-to: version-updates + patterns: + - "junit:*" + - "com.github.stefanbirker:system-rules" + - "com.h2database:*" + - "io.findify:s3mock*" + - "io.netty:*" + - "org.hamcrest:*" + - "org.mock-server:*" + - "org.mockito:*" + update-types: + - "minor" + - "patch" + # Group together all Apache Commons deps in a single PR + apache-commons: + applies-to: version-updates + patterns: + - "org.apache.commons:*" + - "commons-*:commons-*" + update-types: + - "minor" + - "patch" + # Group together all fasterxml deps in a single PR + fasterxml: + applies-to: version-updates + patterns: + - "com.fasterxml:*" + - "com.fasterxml.*:*" + update-types: + - "minor" + - "patch" + # Group together all Hibernate deps in a single PR + hibernate: + applies-to: version-updates + patterns: + - "org.hibernate.*:*" + update-types: + - "minor" + - "patch" + # Group together all Jakarta deps in a single PR + jakarta: + applies-to: version-updates + patterns: + - "jakarta.*:*" + - "org.eclipse.angus:jakarta.mail" + - "org.glassfish.jaxb:jaxb-runtime" + update-types: + - "minor" + - "patch" + # Group together all Google deps in a single PR + google-apis: + applies-to: version-updates + patterns: + - "com.google.apis:*" + - "com.google.api-client:*" + - "com.google.http-client:*" + - "com.google.oauth-client:*" + update-types: + - "minor" + - "patch" + # Group together all Spring deps in a single PR + spring: + applies-to: version-updates + patterns: + - "org.springframework:*" + - "org.springframework.*:*" + update-types: + - "minor" + - "patch" + # Group together all WebJARs deps in a single PR + webjars: + applies-to: version-updates + patterns: + - "org.webjars:*" + - "org.webjars.*:*" + update-types: + - "minor" + - "patch" + ignore: + # Don't try to auto-update any DSpace dependencies + - dependency-name: "org.dspace:*" + - dependency-name: "org.dspace.*:*" + # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. + - dependency-name: "*" + update-types: ["version-update:semver-major"] From 5b46c94bb4d398275abefc688e4a31dcda809b69 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Oct 2024 15:01:41 -0500 Subject: [PATCH 283/632] Exclude spring from build-tools group in dependabot.yml --- .github/dependabot.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6f4f3ae601a0..b6412b25b660 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -24,6 +24,9 @@ updates: - "com.google.errorprone:*" - "com.puppycrawl.tools:checkstyle" - "org.sonatype.plugins:*" + exclude-patterns: + # Exclude anything from Spring, as that is in a separate group + - "org.springframework.*:*" update-types: - "minor" - "patch" From e840ca27315ce8fb2772e8bcdf6c34c042a6cc99 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 28 Oct 2024 14:55:30 -0500 Subject: [PATCH 284/632] Create dependabot.yml --- .github/dependabot.yml | 115 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000000..6f4f3ae601a0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,115 @@ +#------------------- +# DSpace's dependabot rules. Enables maven updates for all dependencies on a weekly basis +# for main and any maintenance branches. Security updates only apply to main. +#------------------- +version: 2 +updates: + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "weekly" + # Allow up to 10 open PRs for dependencies + open-pull-requests-limit: 10 + # Group together some upgrades in a single PR + groups: + # Group together all Build Tools in a single PR + build-tools: + applies-to: version-updates + patterns: + - "org.apache.maven.plugins:*" + - "*:*-maven-plugin" + - "*:maven-*-plugin" + - "com.github.spotbugs:spotbugs" + - "com.google.code.findbugs:*" + - "com.google.errorprone:*" + - "com.puppycrawl.tools:checkstyle" + - "org.sonatype.plugins:*" + update-types: + - "minor" + - "patch" + test-tools: + applies-to: version-updates + patterns: + - "junit:*" + - "com.github.stefanbirker:system-rules" + - "com.h2database:*" + - "io.findify:s3mock*" + - "io.netty:*" + - "org.hamcrest:*" + - "org.mock-server:*" + - "org.mockito:*" + update-types: + - "minor" + - "patch" + # Group together all Apache Commons deps in a single PR + apache-commons: + applies-to: version-updates + patterns: + - "org.apache.commons:*" + - "commons-*:commons-*" + update-types: + - "minor" + - "patch" + # Group together all fasterxml deps in a single PR + fasterxml: + applies-to: version-updates + patterns: + - "com.fasterxml:*" + - "com.fasterxml.*:*" + update-types: + - "minor" + - "patch" + # Group together all Hibernate deps in a single PR + hibernate: + applies-to: version-updates + patterns: + - "org.hibernate.*:*" + update-types: + - "minor" + - "patch" + # Group together all Jakarta deps in a single PR + jakarta: + applies-to: version-updates + patterns: + - "jakarta.*:*" + - "org.eclipse.angus:jakarta.mail" + - "org.glassfish.jaxb:jaxb-runtime" + update-types: + - "minor" + - "patch" + # Group together all Google deps in a single PR + google-apis: + applies-to: version-updates + patterns: + - "com.google.apis:*" + - "com.google.api-client:*" + - "com.google.http-client:*" + - "com.google.oauth-client:*" + update-types: + - "minor" + - "patch" + # Group together all Spring deps in a single PR + spring: + applies-to: version-updates + patterns: + - "org.springframework:*" + - "org.springframework.*:*" + update-types: + - "minor" + - "patch" + # Group together all WebJARs deps in a single PR + webjars: + applies-to: version-updates + patterns: + - "org.webjars:*" + - "org.webjars.*:*" + update-types: + - "minor" + - "patch" + ignore: + # Don't try to auto-update any DSpace dependencies + - dependency-name: "org.dspace:*" + - dependency-name: "org.dspace.*:*" + # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. + - dependency-name: "*" + update-types: ["version-update:semver-major"] From fe28962e9672c01477059bcc2d2c8787a781dadf Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Oct 2024 15:01:41 -0500 Subject: [PATCH 285/632] Exclude spring from build-tools group in dependabot.yml --- .github/dependabot.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6f4f3ae601a0..b6412b25b660 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -24,6 +24,9 @@ updates: - "com.google.errorprone:*" - "com.puppycrawl.tools:checkstyle" - "org.sonatype.plugins:*" + exclude-patterns: + # Exclude anything from Spring, as that is in a separate group + - "org.springframework.*:*" update-types: - "minor" - "patch" From 0b46a0963c5cfe8189fe3b8764eb6450ec41664a Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 2 Apr 2024 11:15:49 +0200 Subject: [PATCH 286/632] 113811: cli logs should be written to a different file (cherry picked from commit d30468a09fbbd288df6cf2556e1a630f040801d1) --- dspace/bin/dspace | 2 + dspace/config/log4j2-cli.xml | 105 +++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 dspace/config/log4j2-cli.xml diff --git a/dspace/bin/dspace b/dspace/bin/dspace index 7d5d678d0f6e..24644aae9112 100644 --- a/dspace/bin/dspace +++ b/dspace/bin/dspace @@ -39,6 +39,8 @@ if [ "$JAVA_OPTS" = "" ]; then JAVA_OPTS="-Xmx256m -Dfile.encoding=UTF-8" fi +export JAVA_OPTS="$JAVA_OPTS -Dlog4j2.configurationFile=$DSPACEDIR/config/log4j2-cli.xml" + # Now invoke Java java $JAVA_OPTS \ -classpath $FULLPATH \ diff --git a/dspace/config/log4j2-cli.xml b/dspace/config/log4j2-cli.xml new file mode 100644 index 000000000000..24d36fd12efb --- /dev/null +++ b/dspace/config/log4j2-cli.xml @@ -0,0 +1,105 @@ + + + + + + + ${log4j:configParentLocation}/../log + + + INFO + + + INFO + + + + + + + + + yyyy-MM-dd + + + + + + + + + yyyy-MM-dd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 04ec6381cba0472f4fdbc0918588180393a89c5d Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Fri, 6 Sep 2024 10:15:08 +0200 Subject: [PATCH 287/632] Modifying it so that the cli file content is stored in a file using the date (cherry picked from commit 529c3a77c15f401fe623b2c9d04a438754a1d72d) --- dspace/config/log4j2-cli.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dspace/config/log4j2-cli.xml b/dspace/config/log4j2-cli.xml index 24d36fd12efb..73acab877f1f 100644 --- a/dspace/config/log4j2-cli.xml +++ b/dspace/config/log4j2-cli.xml @@ -25,8 +25,6 @@ From 1a6088388fa4bc0d01ecdea0b1fee7108a27bce5 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 4 Dec 2024 11:08:37 +0100 Subject: [PATCH 288/632] apply fix to windows env and remove duplicate logging for checksum checker (cherry picked from commit 9f39a3d6a53f9a815509d6a47abd176b07a6a86c) --- dspace/bin/dspace.bat | 3 +++ dspace/config/log4j2.xml | 27 --------------------------- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/dspace/bin/dspace.bat b/dspace/bin/dspace.bat index 2288127c447a..768b1061762d 100644 --- a/dspace/bin/dspace.bat +++ b/dspace/bin/dspace.bat @@ -38,6 +38,9 @@ REM If JAVA_OPTS specified, use those options REM Otherwise, default Java to using 256MB of memory if "%JAVA_OPTS%"=="" set "JAVA_OPTS=-Xmx256m -Dfile.encoding=UTF-8" +REM Add log4j2 configuration to JAVA_OPTS +set "JAVA_OPTS=%JAVA_OPTS% -Dlog4j2.configurationFile=%cd%\config\log4j2-cli.xml" + REM Execute Java java %JAVA_OPTS% -classpath "%DSPACE_CLASSPATH%" org.dspace.app.launcher.ScriptLauncher %* diff --git a/dspace/config/log4j2.xml b/dspace/config/log4j2.xml index 6e9a43e4f0fe..4f212d128dc6 100644 --- a/dspace/config/log4j2.xml +++ b/dspace/config/log4j2.xml @@ -44,26 +44,6 @@ --> - - - - - - yyyy-MM-dd - - - @@ -75,13 +55,6 @@ - - - - - From 666e146125bf63b4cb48876f30b76c54afb0eca3 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 2 Apr 2024 11:15:49 +0200 Subject: [PATCH 289/632] 113811: cli logs should be written to a different file (cherry picked from commit d30468a09fbbd288df6cf2556e1a630f040801d1) --- dspace/bin/dspace | 2 + dspace/config/log4j2-cli.xml | 105 +++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 dspace/config/log4j2-cli.xml diff --git a/dspace/bin/dspace b/dspace/bin/dspace index 7d5d678d0f6e..24644aae9112 100644 --- a/dspace/bin/dspace +++ b/dspace/bin/dspace @@ -39,6 +39,8 @@ if [ "$JAVA_OPTS" = "" ]; then JAVA_OPTS="-Xmx256m -Dfile.encoding=UTF-8" fi +export JAVA_OPTS="$JAVA_OPTS -Dlog4j2.configurationFile=$DSPACEDIR/config/log4j2-cli.xml" + # Now invoke Java java $JAVA_OPTS \ -classpath $FULLPATH \ diff --git a/dspace/config/log4j2-cli.xml b/dspace/config/log4j2-cli.xml new file mode 100644 index 000000000000..24d36fd12efb --- /dev/null +++ b/dspace/config/log4j2-cli.xml @@ -0,0 +1,105 @@ + + + + + + + ${log4j:configParentLocation}/../log + + + INFO + + + INFO + + + + + + + + + yyyy-MM-dd + + + + + + + + + yyyy-MM-dd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 5a2488ac48628ae906979aa064d5890be5e258f1 Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Fri, 6 Sep 2024 10:15:08 +0200 Subject: [PATCH 290/632] Modifying it so that the cli file content is stored in a file using the date (cherry picked from commit 529c3a77c15f401fe623b2c9d04a438754a1d72d) --- dspace/config/log4j2-cli.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dspace/config/log4j2-cli.xml b/dspace/config/log4j2-cli.xml index 24d36fd12efb..73acab877f1f 100644 --- a/dspace/config/log4j2-cli.xml +++ b/dspace/config/log4j2-cli.xml @@ -25,8 +25,6 @@ From 262be99d4e3b8cf5c1321eabc6072e40a4e3fdf7 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 4 Dec 2024 11:08:37 +0100 Subject: [PATCH 291/632] apply fix to windows env and remove duplicate logging for checksum checker (cherry picked from commit 9f39a3d6a53f9a815509d6a47abd176b07a6a86c) --- dspace/bin/dspace.bat | 3 +++ dspace/config/log4j2.xml | 27 --------------------------- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/dspace/bin/dspace.bat b/dspace/bin/dspace.bat index 2288127c447a..768b1061762d 100644 --- a/dspace/bin/dspace.bat +++ b/dspace/bin/dspace.bat @@ -38,6 +38,9 @@ REM If JAVA_OPTS specified, use those options REM Otherwise, default Java to using 256MB of memory if "%JAVA_OPTS%"=="" set "JAVA_OPTS=-Xmx256m -Dfile.encoding=UTF-8" +REM Add log4j2 configuration to JAVA_OPTS +set "JAVA_OPTS=%JAVA_OPTS% -Dlog4j2.configurationFile=%cd%\config\log4j2-cli.xml" + REM Execute Java java %JAVA_OPTS% -classpath "%DSPACE_CLASSPATH%" org.dspace.app.launcher.ScriptLauncher %* diff --git a/dspace/config/log4j2.xml b/dspace/config/log4j2.xml index 6e9a43e4f0fe..4f212d128dc6 100644 --- a/dspace/config/log4j2.xml +++ b/dspace/config/log4j2.xml @@ -44,26 +44,6 @@ --> - - - - - - yyyy-MM-dd - - - @@ -75,13 +55,6 @@ - - - - - From f99755852b0b8c7a80fda12d5d85d58e47f92ce4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:00:58 +0000 Subject: [PATCH 292/632] Bump the build-tools group with 24 updates Bumps the build-tools group with 24 updates: | Package | From | To | | --- | --- | --- | | [com.google.errorprone:error_prone_core](https://github.com/google/error-prone) | `2.10.0` | `2.36.0` | | [com.google.errorprone:error_prone_annotations](https://github.com/google/error-prone) | `2.10.0` | `2.36.0` | | [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `8.38` | `8.45.1` | | [com.github.spotbugs:spotbugs](https://github.com/spotbugs/spotbugs) | `4.8.2` | `4.8.6` | | [org.apache.maven.plugins:maven-enforcer-plugin](https://github.com/apache/maven-enforcer) | `3.4.1` | `3.5.0` | | [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) | `3.3.0` | `3.4.2` | | [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.2.5` | `3.5.2` | | [org.apache.maven.plugins:maven-failsafe-plugin](https://github.com/apache/maven-surefire) | `3.2.5` | `3.5.2` | | [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) | `3.3.1` | `3.6.0` | | [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) | `4.8.2.0` | `4.8.6.6` | | [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin) | `3.3.2` | `3.4.0` | | [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) | `3.6.1` | `3.8.1` | | org.sonatype.plugins:nexus-staging-maven-plugin | `1.6.13` | `1.7.0` | | [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) | `3.6.3` | `3.11.2` | | [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) | `3.3.0` | `3.3.1` | | [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) | `3.2.1` | `3.2.7` | | [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) | `0.8.11` | `0.8.12` | | [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) | `3.0.0` | `3.1.1` | | [org.codehaus.mojo:xml-maven-plugin](https://github.com/mojohaus/xml-maven-plugin) | `1.0.2` | `1.1.0` | | [org.codehaus.mojo:license-maven-plugin](https://github.com/mojohaus/license-maven-plugin) | `2.0.0` | `2.5.0` | | [org.codehaus.mojo:build-helper-maven-plugin](https://github.com/mojohaus/build-helper-maven-plugin) | `3.4.0` | `3.6.0` | | [org.codehaus.mojo:buildnumber-maven-plugin](https://github.com/mojohaus/buildnumber-maven-plugin) | `3.2.0` | `3.2.1` | | [org.codehaus.mojo:jaxb2-maven-plugin](https://github.com/mojohaus/jaxb2-maven-plugin) | `3.1.0` | `3.2.0` | | [org.codehaus.mojo:properties-maven-plugin](https://github.com/mojohaus/properties-maven-plugin) | `1.1.0` | `1.2.1` | Updates `com.google.errorprone:error_prone_core` from 2.10.0 to 2.36.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.10.0...v2.36.0) Updates `com.google.errorprone:error_prone_annotations` from 2.10.0 to 2.36.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.10.0...v2.36.0) Updates `com.puppycrawl.tools:checkstyle` from 8.38 to 8.45.1 - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-8.38...checkstyle-8.45.1) Updates `com.github.spotbugs:spotbugs` from 4.8.2 to 4.8.6 - [Release notes](https://github.com/spotbugs/spotbugs/releases) - [Changelog](https://github.com/spotbugs/spotbugs/blob/master/CHANGELOG.md) - [Commits](https://github.com/spotbugs/spotbugs/compare/4.8.2...4.8.6) Updates `com.google.errorprone:error_prone_annotations` from 2.10.0 to 2.36.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.10.0...v2.36.0) Updates `org.apache.maven.plugins:maven-enforcer-plugin` from 3.4.1 to 3.5.0 - [Release notes](https://github.com/apache/maven-enforcer/releases) - [Commits](https://github.com/apache/maven-enforcer/compare/enforcer-3.4.1...enforcer-3.5.0) Updates `org.apache.maven.plugins:maven-jar-plugin` from 3.3.0 to 3.4.2 - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.2) Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.2.5 to 3.5.2 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.5.2) Updates `org.apache.maven.plugins:maven-failsafe-plugin` from 3.2.5 to 3.5.2 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.5.2) Updates `org.apache.maven.plugins:maven-checkstyle-plugin` from 3.3.1 to 3.6.0 - [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.1...maven-checkstyle-plugin-3.6.0) Updates `com.github.spotbugs:spotbugs-maven-plugin` from 4.8.2.0 to 4.8.6.6 - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.8.2.0...spotbugs-maven-plugin-4.8.6.6) Updates `org.apache.maven.plugins:maven-clean-plugin` from 3.3.2 to 3.4.0 - [Release notes](https://github.com/apache/maven-clean-plugin/releases) - [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.3.2...maven-clean-plugin-3.4.0) Updates `org.apache.maven.plugins:maven-dependency-plugin` from 3.6.1 to 3.8.1 - [Release notes](https://github.com/apache/maven-dependency-plugin/releases) - [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.6.1...maven-dependency-plugin-3.8.1) Updates `org.sonatype.plugins:nexus-staging-maven-plugin` from 1.6.13 to 1.7.0 Updates `org.apache.maven.plugins:maven-javadoc-plugin` from 3.6.3 to 3.11.2 - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.3...maven-javadoc-plugin-3.11.2) Updates `org.apache.maven.plugins:maven-source-plugin` from 3.3.0 to 3.3.1 - [Release notes](https://github.com/apache/maven-source-plugin/releases) - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1) Updates `org.apache.maven.plugins:maven-gpg-plugin` from 3.2.1 to 3.2.7 - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.1...maven-gpg-plugin-3.2.7) Updates `org.jacoco:jacoco-maven-plugin` from 0.8.11 to 0.8.12 - [Release notes](https://github.com/jacoco/jacoco/releases) - [Commits](https://github.com/jacoco/jacoco/compare/v0.8.11...v0.8.12) Updates `org.apache.maven.plugins:maven-release-plugin` from 3.0.0 to 3.1.1 - [Release notes](https://github.com/apache/maven-release/releases) - [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.0...maven-release-3.1.1) Updates `org.codehaus.mojo:xml-maven-plugin` from 1.0.2 to 1.1.0 - [Release notes](https://github.com/mojohaus/xml-maven-plugin/releases) - [Commits](https://github.com/mojohaus/xml-maven-plugin/compare/xml-maven-plugin-1.0.2...1.1.0) Updates `org.codehaus.mojo:license-maven-plugin` from 2.0.0 to 2.5.0 - [Release notes](https://github.com/mojohaus/license-maven-plugin/releases) - [Commits](https://github.com/mojohaus/license-maven-plugin/compare/license-maven-plugin-2.0.0...2.5.0) Updates `org.codehaus.mojo:build-helper-maven-plugin` from 3.4.0 to 3.6.0 - [Release notes](https://github.com/mojohaus/build-helper-maven-plugin/releases) - [Commits](https://github.com/mojohaus/build-helper-maven-plugin/compare/3.4.0...3.6.0) Updates `org.codehaus.mojo:buildnumber-maven-plugin` from 3.2.0 to 3.2.1 - [Release notes](https://github.com/mojohaus/buildnumber-maven-plugin/releases) - [Commits](https://github.com/mojohaus/buildnumber-maven-plugin/compare/3.2.0...3.2.1) Updates `org.codehaus.mojo:jaxb2-maven-plugin` from 3.1.0 to 3.2.0 - [Release notes](https://github.com/mojohaus/jaxb2-maven-plugin/releases) - [Commits](https://github.com/mojohaus/jaxb2-maven-plugin/compare/jaxb2-maven-plugin-3.1.0...jaxb2-maven-plugin-3.2.0) Updates `org.codehaus.mojo:properties-maven-plugin` from 1.1.0 to 1.2.1 - [Release notes](https://github.com/mojohaus/properties-maven-plugin/releases) - [Commits](https://github.com/mojohaus/properties-maven-plugin/compare/properties-maven-plugin-1.1.0...1.2.1) --- updated-dependencies: - dependency-name: com.google.errorprone:error_prone_core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.github.spotbugs:spotbugs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-enforcer-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-jar-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-clean-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-dependency-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.jacoco:jacoco-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-release-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:xml-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:license-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:build-helper-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:buildnumber-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.codehaus.mojo:jaxb2-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:properties-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 6 +++--- dspace-server-webapp/pom.xml | 2 +- pom.xml | 38 ++++++++++++++++++------------------ 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 58bd8106e9af..d5e2f51b883b 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -102,7 +102,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.4.0 + 3.6.0 validate @@ -116,7 +116,7 @@ org.codehaus.mojo buildnumber-maven-plugin - 3.2.0 + 3.2.1 UNKNOWN_REVISION @@ -177,7 +177,7 @@ org.codehaus.mojo jaxb2-maven-plugin - 3.1.0 + 3.2.0 workflow-curation diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 290f8afb0dc6..7adf63aa01ef 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -31,7 +31,7 @@ org.codehaus.mojo properties-maven-plugin - 1.1.0 + 1.2.1 initialize diff --git a/pom.xml b/pom.xml index bb093621ff2f..7a2f9792aa7a 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 8.11.3 3.10.8 - 2.10.0 + 2.36.0 2.16.0 2.16.0 @@ -89,7 +89,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.4.1 + 3.5.0 enforce-java @@ -176,7 +176,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.2 @@ -207,7 +207,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.5.2 @@ -234,7 +234,7 @@ maven-failsafe-plugin - 3.2.5 + 3.5.2 @@ -266,7 +266,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.3.1 + 3.6.0 verify-style @@ -295,14 +295,14 @@ com.puppycrawl.tools checkstyle - 8.38 + 8.45.1 com.github.spotbugs spotbugs-maven-plugin - 4.8.2.0 + 4.8.6.6 Max Low @@ -312,7 +312,7 @@ com.github.spotbugs spotbugs - 4.8.2 + 4.8.6 @@ -328,7 +328,7 @@ maven-clean-plugin - 3.3.2 + 3.4.0 @@ -347,7 +347,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.6.1 + 3.8.1 org.apache.maven.plugins @@ -364,13 +364,13 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + 1.7.0 org.apache.maven.plugins maven-javadoc-plugin - 3.6.3 + 3.11.2 false @@ -385,7 +385,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + 3.3.1 @@ -398,13 +398,13 @@ org.apache.maven.plugins maven-gpg-plugin - 3.2.1 + 3.2.7 org.jacoco jacoco-maven-plugin - 0.8.11 + 0.8.12 @@ -416,7 +416,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.0 + 3.1.1 @@ -484,7 +484,7 @@ org.codehaus.mojo xml-maven-plugin - 1.0.2 + 1.1.0 validate-ALL-xml-and-xsl @@ -692,7 +692,7 @@ org.codehaus.mojo license-maven-plugin - 2.0.0 + 2.5.0 false From 3352a0a9c36c363f54505958a3e8ebf3d8be1949 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:01:11 +0000 Subject: [PATCH 293/632] Bump the test-tools group with 2 updates Bumps the test-tools group with 2 updates: [com.h2database:h2](https://github.com/h2database/h2database) and [org.mock-server:mockserver-junit-rule](https://github.com/jamesdbloom/mockservice). Updates `com.h2database:h2` from 2.2.224 to 2.3.232 - [Release notes](https://github.com/h2database/h2database/releases) - [Commits](https://github.com/h2database/h2database/compare/version-2.2.224...version-2.3.232) Updates `org.mock-server:mockserver-junit-rule` from 5.11.2 to 5.15.0 - [Changelog](https://github.com/mock-server/mockserver/blob/master/changelog.md) - [Commits](https://github.com/jamesdbloom/mockservice/compare/mockserver-5.11.2...mockserver-5.15.0) --- updated-dependencies: - dependency-name: com.h2database:h2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: test-tools - dependency-name: org.mock-server:mockserver-junit-rule dependency-type: direct:development update-type: version-update:semver-minor dependency-group: test-tools ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 58bd8106e9af..16704f7bf294 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -824,7 +824,7 @@ org.mock-server mockserver-junit-rule - 5.11.2 + 5.15.0 test diff --git a/pom.xml b/pom.xml index bb093621ff2f..0d8539ba5209 100644 --- a/pom.xml +++ b/pom.xml @@ -1708,7 +1708,7 @@ com.h2database h2 - 2.2.224 + 2.3.232 test From 1492ed7f61b5685e0e8e0f4365460887465bef88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:01:16 +0000 Subject: [PATCH 294/632] Bump the build-tools group with 21 updates Bumps the build-tools group with 21 updates: | Package | From | To | | --- | --- | --- | | [com.google.errorprone:error_prone_core](https://github.com/google/error-prone) | `2.10.0` | `2.36.0` | | [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `8.38` | `8.45.1` | | [com.github.spotbugs:spotbugs](https://github.com/spotbugs/spotbugs) | `4.8.2` | `4.8.6` | | [org.apache.maven.plugins:maven-enforcer-plugin](https://github.com/apache/maven-enforcer) | `3.0.0-M3` | `3.5.0` | | [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) | `3.8.1` | `3.13.0` | | [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) | `3.2.0` | `3.4.2` | | [org.apache.maven.plugins:maven-war-plugin](https://github.com/apache/maven-war-plugin) | `3.2.3` | `3.4.0` | | [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) | `3.3.1` | `3.6.0` | | [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) | `4.8.2.0` | `4.8.6.6` | | [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin) | `3.1.0` | `3.4.0` | | [org.apache.maven.plugins:maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) | `3.6.0` | `3.7.1` | | [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) | `3.1.2` | `3.8.1` | | [org.apache.maven.plugins:maven-resources-plugin](https://github.com/apache/maven-resources-plugin) | `3.1.0` | `3.3.1` | | org.sonatype.plugins:nexus-staging-maven-plugin | `1.6.8` | `1.7.0` | | [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) | `3.2.0` | `3.11.2` | | [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) | `3.2.1` | `3.3.1` | | [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) | `0.8.5` | `0.8.12` | | [org.codehaus.mojo:xml-maven-plugin](https://github.com/mojohaus/xml-maven-plugin) | `1.0.2` | `1.1.0` | | [org.codehaus.mojo:license-maven-plugin](https://github.com/mojohaus/license-maven-plugin) | `2.0.0` | `2.5.0` | | [org.codehaus.mojo:build-helper-maven-plugin](https://github.com/mojohaus/build-helper-maven-plugin) | `3.4.0` | `3.6.0` | | [org.codehaus.mojo:buildnumber-maven-plugin](https://github.com/mojohaus/buildnumber-maven-plugin) | `3.2.0` | `3.2.1` | Updates `com.google.errorprone:error_prone_core` from 2.10.0 to 2.36.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.10.0...v2.36.0) Updates `com.puppycrawl.tools:checkstyle` from 8.38 to 8.45.1 - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-8.38...checkstyle-8.45.1) Updates `com.github.spotbugs:spotbugs` from 4.8.2 to 4.8.6 - [Release notes](https://github.com/spotbugs/spotbugs/releases) - [Changelog](https://github.com/spotbugs/spotbugs/blob/master/CHANGELOG.md) - [Commits](https://github.com/spotbugs/spotbugs/compare/4.8.2...4.8.6) Updates `org.apache.maven.plugins:maven-enforcer-plugin` from 3.0.0-M3 to 3.5.0 - [Release notes](https://github.com/apache/maven-enforcer/releases) - [Commits](https://github.com/apache/maven-enforcer/compare/enforcer-3.0.0-M3...enforcer-3.5.0) Updates `org.apache.maven.plugins:maven-compiler-plugin` from 3.8.1 to 3.13.0 - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.8.1...maven-compiler-plugin-3.13.0) Updates `org.apache.maven.plugins:maven-jar-plugin` from 3.2.0 to 3.4.2 - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.2.0...maven-jar-plugin-3.4.2) Updates `org.apache.maven.plugins:maven-war-plugin` from 3.2.3 to 3.4.0 - [Commits](https://github.com/apache/maven-war-plugin/compare/maven-war-plugin-3.2.3...maven-war-plugin-3.4.0) Updates `org.apache.maven.plugins:maven-checkstyle-plugin` from 3.3.1 to 3.6.0 - [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.1...maven-checkstyle-plugin-3.6.0) Updates `com.github.spotbugs:spotbugs-maven-plugin` from 4.8.2.0 to 4.8.6.6 - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.8.2.0...spotbugs-maven-plugin-4.8.6.6) Updates `org.apache.maven.plugins:maven-clean-plugin` from 3.1.0 to 3.4.0 - [Release notes](https://github.com/apache/maven-clean-plugin/releases) - [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.1.0...maven-clean-plugin-3.4.0) Updates `org.apache.maven.plugins:maven-assembly-plugin` from 3.6.0 to 3.7.1 - [Release notes](https://github.com/apache/maven-assembly-plugin/releases) - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.6.0...maven-assembly-plugin-3.7.1) Updates `org.apache.maven.plugins:maven-dependency-plugin` from 3.1.2 to 3.8.1 - [Release notes](https://github.com/apache/maven-dependency-plugin/releases) - [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.1.2...maven-dependency-plugin-3.8.1) Updates `org.apache.maven.plugins:maven-resources-plugin` from 3.1.0 to 3.3.1 - [Release notes](https://github.com/apache/maven-resources-plugin/releases) - [Commits](https://github.com/apache/maven-resources-plugin/compare/maven-resources-plugin-3.1.0...maven-resources-plugin-3.3.1) Updates `org.sonatype.plugins:nexus-staging-maven-plugin` from 1.6.8 to 1.7.0 Updates `org.apache.maven.plugins:maven-javadoc-plugin` from 3.2.0 to 3.11.2 - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.2.0...maven-javadoc-plugin-3.11.2) Updates `org.apache.maven.plugins:maven-source-plugin` from 3.2.1 to 3.3.1 - [Release notes](https://github.com/apache/maven-source-plugin/releases) - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.1...maven-source-plugin-3.3.1) Updates `org.jacoco:jacoco-maven-plugin` from 0.8.5 to 0.8.12 - [Release notes](https://github.com/jacoco/jacoco/releases) - [Commits](https://github.com/jacoco/jacoco/compare/v0.8.5...v0.8.12) Updates `org.codehaus.mojo:xml-maven-plugin` from 1.0.2 to 1.1.0 - [Release notes](https://github.com/mojohaus/xml-maven-plugin/releases) - [Commits](https://github.com/mojohaus/xml-maven-plugin/compare/xml-maven-plugin-1.0.2...1.1.0) Updates `org.codehaus.mojo:license-maven-plugin` from 2.0.0 to 2.5.0 - [Release notes](https://github.com/mojohaus/license-maven-plugin/releases) - [Commits](https://github.com/mojohaus/license-maven-plugin/compare/license-maven-plugin-2.0.0...2.5.0) Updates `org.codehaus.mojo:build-helper-maven-plugin` from 3.4.0 to 3.6.0 - [Release notes](https://github.com/mojohaus/build-helper-maven-plugin/releases) - [Commits](https://github.com/mojohaus/build-helper-maven-plugin/compare/3.4.0...3.6.0) Updates `org.codehaus.mojo:buildnumber-maven-plugin` from 3.2.0 to 3.2.1 - [Release notes](https://github.com/mojohaus/buildnumber-maven-plugin/releases) - [Commits](https://github.com/mojohaus/buildnumber-maven-plugin/compare/3.2.0...3.2.1) --- updated-dependencies: - dependency-name: com.google.errorprone:error_prone_core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.github.spotbugs:spotbugs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-enforcer-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-jar-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-war-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-clean-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-assembly-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-dependency-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-resources-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.jacoco:jacoco-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.codehaus.mojo:xml-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:license-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:build-helper-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:buildnumber-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 4 ++-- pom.xml | 38 +++++++++++++++++++------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index c42895ab4c49..cf81408a2659 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -102,7 +102,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.4.0 + 3.6.0 validate @@ -116,7 +116,7 @@ org.codehaus.mojo buildnumber-maven-plugin - 3.2.0 + 3.2.1 UNKNOWN_REVISION diff --git a/pom.xml b/pom.xml index 50faf1f7372e..f496ed7e879d 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ 8.11.3 3.10.8 - 2.10.0 + 2.36.0 2.16.0 2.16.0 @@ -89,7 +89,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M3 + 3.5.0 enforce-java @@ -140,7 +140,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.13.0 11 @@ -173,7 +173,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + 3.4.2 @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-war-plugin - 3.2.3 + 3.4.0 false @@ -257,7 +257,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.3.1 + 3.6.0 verify-style @@ -287,14 +287,14 @@ com.puppycrawl.tools checkstyle - 8.38 + 8.45.1 com.github.spotbugs spotbugs-maven-plugin - 4.8.2.0 + 4.8.6.6 Max Low @@ -304,7 +304,7 @@ com.github.spotbugs spotbugs - 4.8.2 + 4.8.6 @@ -320,7 +320,7 @@ maven-clean-plugin - 3.1.0 + 3.4.0 @@ -334,17 +334,17 @@ maven-assembly-plugin - 3.6.0 + 3.7.1 org.apache.maven.plugins maven-dependency-plugin - 3.1.2 + 3.8.1 org.apache.maven.plugins maven-resources-plugin - 3.1.0 + 3.3.1 @@ -356,13 +356,13 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.7.0 org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.11.2 false @@ -372,7 +372,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.1 @@ -391,7 +391,7 @@ org.jacoco jacoco-maven-plugin - 0.8.5 + 0.8.12 @@ -471,7 +471,7 @@ org.codehaus.mojo xml-maven-plugin - 1.0.2 + 1.1.0 validate-ALL-xml-and-xsl @@ -679,7 +679,7 @@ org.codehaus.mojo license-maven-plugin - 2.0.0 + 2.5.0 false From f9fbc237bf30445ec679dff4c36b53a4f9e96de9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:01:37 +0000 Subject: [PATCH 295/632] Bump the apache-commons group with 12 updates Bumps the apache-commons group with 12 updates: | Package | From | To | | --- | --- | --- | | commons-beanutils:commons-beanutils | `1.9.4` | `1.10.0` | | commons-cli:commons-cli | `1.6.0` | `1.9.0` | | [commons-codec:commons-codec](https://github.com/apache/commons-codec) | `1.16.0` | `1.17.2` | | org.apache.commons:commons-configuration2 | `2.10.1` | `2.11.0` | | org.apache.commons:commons-dbcp2 | `2.11.0` | `2.13.0` | | commons-io:commons-io | `2.15.1` | `2.18.0` | | org.apache.commons:commons-lang3 | `3.14.0` | `3.17.0` | | commons-logging:commons-logging | `1.3.0` | `1.3.4` | | org.apache.commons:commons-compress | `1.26.0` | `1.27.1` | | [org.apache.commons:commons-csv](https://github.com/apache/commons-csv) | `1.10.0` | `1.13.0` | | org.apache.commons:commons-text | `1.10.0` | `1.13.0` | | commons-validator:commons-validator | `1.7` | `1.9.0` | Updates `commons-beanutils:commons-beanutils` from 1.9.4 to 1.10.0 Updates `commons-cli:commons-cli` from 1.6.0 to 1.9.0 Updates `commons-codec:commons-codec` from 1.16.0 to 1.17.2 - [Changelog](https://github.com/apache/commons-codec/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-codec/compare/rel/commons-codec-1.16.0...rel/commons-codec-1.17.2) Updates `org.apache.commons:commons-configuration2` from 2.10.1 to 2.11.0 Updates `org.apache.commons:commons-dbcp2` from 2.11.0 to 2.13.0 Updates `commons-io:commons-io` from 2.15.1 to 2.18.0 Updates `org.apache.commons:commons-lang3` from 3.14.0 to 3.17.0 Updates `commons-logging:commons-logging` from 1.3.0 to 1.3.4 Updates `org.apache.commons:commons-compress` from 1.26.0 to 1.27.1 Updates `org.apache.commons:commons-csv` from 1.10.0 to 1.13.0 - [Changelog](https://github.com/apache/commons-csv/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-csv/compare/rel/commons-csv-1.10.0...rel/commons-csv-1.13.0) Updates `org.apache.commons:commons-text` from 1.10.0 to 1.13.0 Updates `commons-validator:commons-validator` from 1.7 to 1.9.0 --- updated-dependencies: - dependency-name: commons-beanutils:commons-beanutils dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-cli:commons-cli dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-codec:commons-codec dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-configuration2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-dbcp2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-lang3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-logging:commons-logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: apache-commons - dependency-name: org.apache.commons:commons-compress dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-csv dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-validator:commons-validator dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index bb093621ff2f..c24ed556bfcb 100644 --- a/pom.xml +++ b/pom.xml @@ -1461,17 +1461,17 @@ commons-beanutils commons-beanutils - 1.9.4 + 1.10.0 commons-cli commons-cli - 1.6.0 + 1.9.0 commons-codec commons-codec - 1.16.0 + 1.17.2 org.apache.commons @@ -1481,12 +1481,12 @@ org.apache.commons commons-configuration2 - 2.10.1 + 2.11.0 org.apache.commons commons-dbcp2 - 2.11.0 + 2.13.0 @@ -1498,29 +1498,29 @@ commons-io commons-io - 2.15.1 + 2.18.0 org.apache.commons commons-lang3 - 3.14.0 + 3.17.0 commons-logging commons-logging - 1.3.0 + 1.3.4 org.apache.commons commons-compress - 1.26.0 + 1.27.1 org.apache.commons commons-csv - 1.10.0 + 1.13.0 org.apache.commons @@ -1530,12 +1530,12 @@ org.apache.commons commons-text - 1.10.0 + 1.13.0 commons-validator commons-validator - 1.7 + 1.9.0 joda-time From b4d209368c6da68897092a8ae74e72c48de17ecf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:01:53 +0000 Subject: [PATCH 296/632] Bump the fasterxml group with 5 updates Bumps the fasterxml group with 5 updates: | Package | From | To | | --- | --- | --- | | [com.fasterxml:classmate](https://github.com/FasterXML/java-classmate) | `1.6.0` | `1.7.0` | | [com.fasterxml.jackson.core:jackson-annotations](https://github.com/FasterXML/jackson) | `2.16.0` | `2.18.2` | | [com.fasterxml.jackson.core:jackson-core](https://github.com/FasterXML/jackson-core) | `2.16.0` | `2.18.2` | | [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) | `2.16.0` | `2.18.2` | | com.fasterxml.jackson.datatype:jackson-datatype-jsr310 | `2.16.0` | `2.18.2` | Updates `com.fasterxml:classmate` from 1.6.0 to 1.7.0 - [Commits](https://github.com/FasterXML/java-classmate/compare/classmate-1.6.0...classmate-1.7.0) Updates `com.fasterxml.jackson.core:jackson-annotations` from 2.16.0 to 2.18.2 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.16.0 to 2.18.2 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.16.0...jackson-core-2.18.2) Updates `com.fasterxml.jackson.core:jackson-core` from 2.16.0 to 2.18.2 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.16.0...jackson-core-2.18.2) Updates `com.fasterxml.jackson.core:jackson-databind` from 2.16.0 to 2.18.2 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.16.0 to 2.18.2 Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.16.0 to 2.18.2 --- updated-dependencies: - dependency-name: com.fasterxml:classmate dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml ... Signed-off-by: dependabot[bot] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index bb093621ff2f..9f34b01d1d6e 100644 --- a/pom.xml +++ b/pom.xml @@ -31,8 +31,8 @@ 3.10.8 2.10.0 - 2.16.0 - 2.16.0 + 2.18.2 + 2.18.2 2.1.1 4.0.2 4.0.5 @@ -1736,7 +1736,7 @@ com.fasterxml classmate - 1.6.0 + 1.7.0 com.fasterxml.jackson.core From d7b0e26179f9b0812afb722fd13efa00eae4fa57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:02:16 +0000 Subject: [PATCH 297/632] Bump the apache-commons group with 11 updates Bumps the apache-commons group with 11 updates: | Package | From | To | | --- | --- | --- | | commons-beanutils:commons-beanutils | `1.9.4` | `1.10.0` | | commons-cli:commons-cli | `1.6.0` | `1.9.0` | | [commons-codec:commons-codec](https://github.com/apache/commons-codec) | `1.16.0` | `1.17.2` | | org.apache.commons:commons-configuration2 | `2.10.1` | `2.11.0` | | org.apache.commons:commons-dbcp2 | `2.11.0` | `2.13.0` | | commons-io:commons-io | `2.15.1` | `2.18.0` | | org.apache.commons:commons-lang3 | `3.14.0` | `3.17.0` | | commons-logging:commons-logging | `1.3.0` | `1.3.4` | | org.apache.commons:commons-compress | `1.26.0` | `1.27.1` | | org.apache.commons:commons-text | `1.10.0` | `1.13.0` | | commons-validator:commons-validator | `1.7` | `1.9.0` | Updates `commons-beanutils:commons-beanutils` from 1.9.4 to 1.10.0 Updates `commons-cli:commons-cli` from 1.6.0 to 1.9.0 Updates `commons-codec:commons-codec` from 1.16.0 to 1.17.2 - [Changelog](https://github.com/apache/commons-codec/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-codec/compare/rel/commons-codec-1.16.0...rel/commons-codec-1.17.2) Updates `org.apache.commons:commons-configuration2` from 2.10.1 to 2.11.0 Updates `org.apache.commons:commons-dbcp2` from 2.11.0 to 2.13.0 Updates `commons-io:commons-io` from 2.15.1 to 2.18.0 Updates `org.apache.commons:commons-lang3` from 3.14.0 to 3.17.0 Updates `commons-logging:commons-logging` from 1.3.0 to 1.3.4 Updates `org.apache.commons:commons-compress` from 1.26.0 to 1.27.1 Updates `org.apache.commons:commons-text` from 1.10.0 to 1.13.0 Updates `commons-validator:commons-validator` from 1.7 to 1.9.0 --- updated-dependencies: - dependency-name: commons-beanutils:commons-beanutils dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-cli:commons-cli dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-codec:commons-codec dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-configuration2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-dbcp2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-lang3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-logging:commons-logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: apache-commons - dependency-name: org.apache.commons:commons-compress dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-validator:commons-validator dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 50faf1f7372e..242c03d1b178 100644 --- a/pom.xml +++ b/pom.xml @@ -1463,17 +1463,17 @@ commons-beanutils commons-beanutils - 1.9.4 + 1.10.0 commons-cli commons-cli - 1.6.0 + 1.9.0 commons-codec commons-codec - 1.16.0 + 1.17.2 org.apache.commons @@ -1483,12 +1483,12 @@ org.apache.commons commons-configuration2 - 2.10.1 + 2.11.0 org.apache.commons commons-dbcp2 - 2.11.0 + 2.13.0 commons-fileupload @@ -1498,24 +1498,24 @@ commons-io commons-io - 2.15.1 + 2.18.0 org.apache.commons commons-lang3 - 3.14.0 + 3.17.0 commons-logging commons-logging - 1.3.0 + 1.3.4 org.apache.commons commons-compress - 1.26.0 + 1.27.1 org.apache.commons @@ -1525,12 +1525,12 @@ org.apache.commons commons-text - 1.10.0 + 1.13.0 commons-validator commons-validator - 1.7 + 1.9.0 joda-time From 4a20a4c37fa43c33eb6ba11ea49422e15e786212 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:02:28 +0000 Subject: [PATCH 298/632] Bump the fasterxml group with 4 updates Bumps the fasterxml group with 4 updates: [com.fasterxml:classmate](https://github.com/FasterXML/java-classmate), [com.fasterxml.jackson.core:jackson-annotations](https://github.com/FasterXML/jackson), [com.fasterxml.jackson.core:jackson-core](https://github.com/FasterXML/jackson-core) and [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson). Updates `com.fasterxml:classmate` from 1.6.0 to 1.7.0 - [Commits](https://github.com/FasterXML/java-classmate/compare/classmate-1.6.0...classmate-1.7.0) Updates `com.fasterxml.jackson.core:jackson-annotations` from 2.16.0 to 2.18.2 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.16.0 to 2.18.2 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.16.0...jackson-core-2.18.2) Updates `com.fasterxml.jackson.core:jackson-core` from 2.16.0 to 2.18.2 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.16.0...jackson-core-2.18.2) Updates `com.fasterxml.jackson.core:jackson-databind` from 2.16.0 to 2.18.2 - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml:classmate dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml ... Signed-off-by: dependabot[bot] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 50faf1f7372e..a7a87a7938ff 100644 --- a/pom.xml +++ b/pom.xml @@ -30,8 +30,8 @@ 3.10.8 2.10.0 - 2.16.0 - 2.16.0 + 2.18.2 + 2.18.2 1.3.2 2.3.1 2.3.9 @@ -1742,7 +1742,7 @@ com.fasterxml classmate - 1.6.0 + 1.7.0 com.fasterxml.jackson.core From f57c927a2e6440aa929dab7767d475864bdcf427 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:02:32 +0000 Subject: [PATCH 299/632] Bump jakarta.servlet:jakarta.servlet-api in the jakarta group Bumps the jakarta group with 1 update: [jakarta.servlet:jakarta.servlet-api](https://github.com/eclipse-ee4j/servlet-api). Updates `jakarta.servlet:jakarta.servlet-api` from 6.0.0 to 6.1.0 - [Commits](https://github.com/eclipse-ee4j/servlet-api/compare/6.0.0-RELEASE...6.1.0-RELEASE) --- updated-dependencies: - dependency-name: jakarta.servlet:jakarta.servlet-api dependency-type: direct:production update-type: version-update:semver-minor dependency-group: jakarta ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bb093621ff2f..1e837f48c04e 100644 --- a/pom.xml +++ b/pom.xml @@ -1569,7 +1569,7 @@ jakarta.servlet jakarta.servlet-api - 6.0.0 + 6.1.0 jakarta.el From bec1ee84e51e6a22766c58348791292fe9d6f36d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:03:40 +0000 Subject: [PATCH 300/632] Bump org.webjars.npm:json-editor__json-editor in the webjars group Bumps the webjars group with 1 update: [org.webjars.npm:json-editor__json-editor](https://github.com/json-editor/json-editor). Updates `org.webjars.npm:json-editor__json-editor` from 2.6.1 to 2.15.1 - [Changelog](https://github.com/json-editor/json-editor/blob/master/CHANGELOG.md) - [Commits](https://github.com/json-editor/json-editor/compare/2.6.1...2.15.1) --- updated-dependencies: - dependency-name: org.webjars.npm:json-editor__json-editor dependency-type: direct:production update-type: version-update:semver-minor dependency-group: webjars ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 35fa473fc170..2715338ed0fa 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -345,7 +345,7 @@ org.webjars.npm json-editor__json-editor - 2.6.1 + 2.15.1 From d9945b27b94f372979ac3268d2c85887edb00fa3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:03:55 +0000 Subject: [PATCH 302/632] Bump jersey.version from 2.39.1 to 2.46 Bumps `jersey.version` from 2.39.1 to 2.46. Updates `org.glassfish.jersey.core:jersey-client` from 2.39.1 to 2.46 Updates `org.glassfish.jersey.inject:jersey-hk2` from 2.39.1 to 2.46 Updates `org.glassfish.jersey.core:jersey-server` from 2.39.1 to 2.46 Updates `org.glassfish.jersey.containers:jersey-container-servlet` from 2.39.1 to 2.46 Updates `org.glassfish.jersey.media:jersey-media-json-jackson` from 2.39.1 to 2.46 Updates `org.glassfish.jersey.media:jersey-media-jaxb` from 2.39.1 to 2.46 Updates `org.glassfish.jersey.ext:jersey-spring5` from 2.39.1 to 2.46 --- updated-dependencies: - dependency-name: org.glassfish.jersey.core:jersey-client dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.glassfish.jersey.inject:jersey-hk2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.glassfish.jersey.core:jersey-server dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.glassfish.jersey.containers:jersey-container-servlet dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.glassfish.jersey.media:jersey-media-json-jackson dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.glassfish.jersey.media:jersey-media-jaxb dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.glassfish.jersey.ext:jersey-spring5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 50faf1f7372e..1e83cbbb9bb9 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ https://jena.apache.org/documentation/migrate_jena2_jena3.html --> 2.13.0 - 2.39.1 + 2.46 UTF-8 From 9d17009cf390ea403e439bc5287bf6c118c88836 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:04:17 +0000 Subject: [PATCH 303/632] Bump jetty.version from 9.4.54.v20240208 to 9.4.57.v20241219 Bumps `jetty.version` from 9.4.54.v20240208 to 9.4.57.v20241219. Updates `org.eclipse.jetty:jetty-server` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-alpn-java-server` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-deploy` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-http` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-io` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-servlet` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-servlets` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-util` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-webapp` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-xml` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty.http2:http2-common` from 9.4.54.v20240208 to 9.4.57.v20241219 Updates `org.eclipse.jetty.http2:http2-server` from 9.4.54.v20240208 to 9.4.57.v20241219 --- updated-dependencies: - dependency-name: org.eclipse.jetty:jetty-server dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-alpn-java-server dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-deploy dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-http dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-io dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-servlet dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-servlets dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-util dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-webapp dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-xml dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty.http2:http2-common dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty.http2:http2-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 50faf1f7372e..6575c7e5277f 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.3.9 1.1.1 - 9.4.54.v20240208 + 9.4.57.v20241219 2.23.1 2.0.31 1.19.0 From bff9792ff1411f9a23780aa4ceaf1e48003eef6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:04:19 +0000 Subject: [PATCH 304/632] Bump the spring group with 24 updates Bumps the spring group with 24 updates: | Package | From | To | | --- | --- | --- | | [org.springframework:spring-orm](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-beans](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-aop](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-context-support](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-tx](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-jdbc](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-expression](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework:spring-test](https://github.com/spring-projects/spring-framework) | `6.1.14` | `6.2.1` | | [org.springframework.boot:spring-boot-starter-test](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter-tomcat](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-maven-plugin](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter-cache](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter-web](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter-data-rest](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter-security](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter-aop](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter-actuator](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.boot:spring-boot-starter-log4j2](https://github.com/spring-projects/spring-boot) | `3.3.4` | `3.4.1` | | [org.springframework.security:spring-security-test](https://github.com/spring-projects/spring-security) | `6.3.3` | `6.4.2` | Updates `org.springframework:spring-orm` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-core` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-beans` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-aop` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-context` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-context-support` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-tx` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-jdbc` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-web` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-webmvc` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-expression` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-test` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-core` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-beans` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-aop` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-context` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-context-support` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-tx` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-jdbc` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-web` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-webmvc` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-expression` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework:spring-test` from 6.1.14 to 6.2.1 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.1) Updates `org.springframework.boot:spring-boot-starter-test` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-web` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-security` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.security:spring-security-test` from 6.3.3 to 6.4.2 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/6.3.3...6.4.2) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-web` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-security` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.3.4 to 3.4.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.4.1) --- updated-dependencies: - dependency-name: org.springframework:spring-orm dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-test dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.security:spring-security-test dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index bb093621ff2f..a8d4dffc8ba8 100644 --- a/pom.xml +++ b/pom.xml @@ -19,9 +19,9 @@ 17 - 6.1.14 - 3.3.4 - 6.3.3 + 6.2.1 + 3.4.1 + 6.4.2 6.4.8.Final 8.0.1.Final 42.7.3 From 3b63097fc2096551fd5188bb61f7a212bd42e207 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:04:29 +0000 Subject: [PATCH 305/632] Bump org.webjars.npm:json-editor__json-editor in the webjars group Bumps the webjars group with 1 update: [org.webjars.npm:json-editor__json-editor](https://github.com/json-editor/json-editor). Updates `org.webjars.npm:json-editor__json-editor` from 2.6.1 to 2.15.1 - [Changelog](https://github.com/json-editor/json-editor/blob/master/CHANGELOG.md) - [Commits](https://github.com/json-editor/json-editor/compare/2.6.1...2.15.1) --- updated-dependencies: - dependency-name: org.webjars.npm:json-editor__json-editor dependency-type: direct:production update-type: version-update:semver-minor dependency-group: webjars ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 290f8afb0dc6..8d6be38d09fb 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -431,7 +431,7 @@ org.webjars.npm json-editor__json-editor - 2.6.1 + 2.15.1 - + From a2daffe81e125df9720bd18894528878b5d9c8f5 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Oct 2024 17:02:46 -0500 Subject: [PATCH 309/632] Minor checkstyle fixes after bump to 8.45.1. All are indentation / spacing fixes which are more strict now. --- .../rest/AuthenticationRestController.java | 2 +- .../app/rest/model/AuthorizationRest.java | 6 +-- .../dspace/app/rest/model/BitstreamRest.java | 15 ++----- .../app/rest/model/BrowseIndexRest.java | 10 +---- .../org/dspace/app/rest/model/BundleRest.java | 15 ++----- .../app/rest/model/ClaimedTaskRest.java | 5 +-- .../dspace/app/rest/model/CollectionRest.java | 40 ++++------------- .../dspace/app/rest/model/CommunityRest.java | 25 +++-------- .../dspace/app/rest/model/EPersonRest.java | 5 +-- .../dspace/app/rest/model/EntityTypeRest.java | 5 +-- .../app/rest/model/ExternalSourceRest.java | 5 +-- .../org/dspace/app/rest/model/GroupRest.java | 15 ++----- .../org/dspace/app/rest/model/ItemRest.java | 45 ++++--------------- .../app/rest/model/OrcidHistoryRest.java | 2 +- .../dspace/app/rest/model/PoolTaskRest.java | 5 +-- .../dspace/app/rest/model/ProcessRest.java | 15 ++----- .../app/rest/model/RelationshipRest.java | 5 +-- .../app/rest/model/ResearcherProfileRest.java | 4 +- .../dspace/app/rest/model/SuggestionRest.java | 4 +- .../app/rest/model/SuggestionTargetRest.java | 2 +- .../app/rest/model/VersionHistoryRest.java | 10 +---- .../dspace/app/rest/model/VersionRest.java | 10 +---- .../model/VocabularyEntryDetailsRest.java | 6 +-- .../dspace/app/rest/model/VocabularyRest.java | 4 +- .../rest/model/WorkflowDefinitionRest.java | 10 +---- .../app/rest/model/WorkflowItemRest.java | 20 ++------- .../app/rest/model/WorkflowStepRest.java | 5 +-- .../app/rest/model/WorkspaceItemRest.java | 20 ++------- .../org/dspace/app/rest/utils/RegexUtils.java | 2 +- .../app/rest/matcher/RegistrationMatcher.java | 2 +- 30 files changed, 74 insertions(+), 245 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java index 070f3d8a1868..63ac50b6ea06 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java @@ -220,7 +220,7 @@ private AuthenticationTokenResource shortLivedTokenResponse(HttpServletRequest r * @return ResponseEntity */ @RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.PUT, RequestMethod.PATCH, - RequestMethod.DELETE }) + RequestMethod.DELETE }) public ResponseEntity login() { return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body("Only POST is allowed for login requests."); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java index fa463a7c3968..cd3e33b9e2fa 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java @@ -18,9 +18,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(method = "getEperson", name = AuthorizationRest.EPERSON), - @LinkRest(method = "getFeature", name = AuthorizationRest.FEATURE), - @LinkRest(method = "getObject", name = AuthorizationRest.OBJECT) + @LinkRest(method = "getEperson", name = AuthorizationRest.EPERSON), + @LinkRest(method = "getFeature", name = AuthorizationRest.FEATURE), + @LinkRest(method = "getObject", name = AuthorizationRest.OBJECT) }) public class AuthorizationRest extends BaseObjectRest { public static final String NAME = "authorization"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java index d2c2268b3f35..d456f7222308 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java @@ -16,18 +16,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = BitstreamRest.BUNDLE, - method = "getBundle" - ), - @LinkRest( - name = BitstreamRest.FORMAT, - method = "getFormat" - ), - @LinkRest( - name = BitstreamRest.THUMBNAIL, - method = "getThumbnail" - ) + @LinkRest(name = BitstreamRest.BUNDLE, method = "getBundle"), + @LinkRest(name = BitstreamRest.FORMAT, method = "getFormat"), + @LinkRest(name = BitstreamRest.THUMBNAIL, method = "getThumbnail") }) public class BitstreamRest extends DSpaceObjectRest { public static final String PLURAL_NAME = "bitstreams"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java index a3c0b37ba576..e5b089479971 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java @@ -20,14 +20,8 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = BrowseIndexRest.LINK_ITEMS, - method = "listBrowseItems" - ), - @LinkRest( - name = BrowseIndexRest.LINK_ENTRIES, - method = "listBrowseEntries" - ) + @LinkRest(name = BrowseIndexRest.LINK_ITEMS, method = "listBrowseItems"), + @LinkRest(name = BrowseIndexRest.LINK_ENTRIES, method = "listBrowseEntries") }) public class BrowseIndexRest extends BaseObjectRest { private static final long serialVersionUID = -4870333170249999559L; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java index 1ec9f448dde4..4a417e6c54c3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java @@ -16,18 +16,9 @@ * @author Jelle Pelgrims (jelle.pelgrims at atmire.com) */ @LinksRest(links = { - @LinkRest( - name = BundleRest.ITEM, - method = "getItem" - ), - @LinkRest( - name = BundleRest.BITSTREAMS, - method = "getBitstreams" - ), - @LinkRest( - name = BundleRest.PRIMARY_BITSTREAM, - method = "getPrimaryBitstream" - ) + @LinkRest(name = BundleRest.ITEM, method = "getItem"), + @LinkRest(name = BundleRest.BITSTREAMS, method = "getBitstreams"), + @LinkRest(name = BundleRest.PRIMARY_BITSTREAM, method = "getPrimaryBitstream") }) public class BundleRest extends DSpaceObjectRest { public static final String NAME = "bundle"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java index 0973fac987d2..d29bf7a7ce6b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java @@ -16,10 +16,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = ClaimedTaskRest.STEP, - method = "getStep" - ) + @LinkRest(name = ClaimedTaskRest.STEP, method = "getStep") }) public class ClaimedTaskRest extends BaseObjectRest { public static final String NAME = "claimedtask"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java index f00bb883959c..34faba4cb4d9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java @@ -15,38 +15,14 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = CollectionRest.LICENSE, - method = "getLicense" - ), - @LinkRest( - name = CollectionRest.LOGO, - method = "getLogo" - ), - @LinkRest( - name = CollectionRest.MAPPED_ITEMS, - method = "getMappedItems" - ), - @LinkRest( - name = CollectionRest.PARENT_COMMUNITY, - method = "getParentCommunity" - ), - @LinkRest( - name = CollectionRest.ADMIN_GROUP, - method = "getAdminGroup" - ), - @LinkRest( - name = CollectionRest.SUBMITTERS_GROUP, - method = "getSubmittersGroup" - ), - @LinkRest( - name = CollectionRest.ITEM_READ_GROUP, - method = "getItemReadGroup" - ), - @LinkRest( - name = CollectionRest.BITSTREAM_READ_GROUP, - method = "getBitstreamReadGroup" - ), + @LinkRest(name = CollectionRest.LICENSE, method = "getLicense"), + @LinkRest(name = CollectionRest.LOGO, method = "getLogo"), + @LinkRest(name = CollectionRest.MAPPED_ITEMS, method = "getMappedItems"), + @LinkRest(name = CollectionRest.PARENT_COMMUNITY, method = "getParentCommunity"), + @LinkRest(name = CollectionRest.ADMIN_GROUP, method = "getAdminGroup"), + @LinkRest(name = CollectionRest.SUBMITTERS_GROUP, method = "getSubmittersGroup"), + @LinkRest(name = CollectionRest.ITEM_READ_GROUP, method = "getItemReadGroup"), + @LinkRest(name = CollectionRest.BITSTREAM_READ_GROUP, method = "getBitstreamReadGroup"), }) public class CollectionRest extends DSpaceObjectRest { public static final String NAME = "collection"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java index 0004e0b91ca4..e70b30803da3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java @@ -15,26 +15,11 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = CommunityRest.COLLECTIONS, - method = "getCollections" - ), - @LinkRest( - name = CommunityRest.LOGO, - method = "getLogo" - ), - @LinkRest( - name = CommunityRest.SUBCOMMUNITIES, - method = "getSubcommunities" - ), - @LinkRest( - name = CommunityRest.PARENT_COMMUNITY, - method = "getParentCommunity" - ), - @LinkRest( - name = CommunityRest.ADMIN_GROUP, - method = "getAdminGroup" - ) + @LinkRest(name = CommunityRest.COLLECTIONS, method = "getCollections"), + @LinkRest(name = CommunityRest.LOGO, method = "getLogo"), + @LinkRest(name = CommunityRest.SUBCOMMUNITIES, method = "getSubcommunities"), + @LinkRest(name = CommunityRest.PARENT_COMMUNITY, method = "getParentCommunity"), + @LinkRest(name = CommunityRest.ADMIN_GROUP, method = "getAdminGroup") }) public class CommunityRest extends DSpaceObjectRest { public static final String NAME = "community"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java index c06ed0e3fe1f..db243400259d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java @@ -20,10 +20,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = EPersonRest.GROUPS, - method = "getGroups" - ) + @LinkRest(name = EPersonRest.GROUPS, method = "getGroups") }) public class EPersonRest extends DSpaceObjectRest { public static final String NAME = "eperson"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java index 9d4a729ded93..e73aa709180d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java @@ -15,10 +15,7 @@ * Refer to {@link org.dspace.content.EntityType} for explanation of the properties */ @LinksRest(links = { - @LinkRest( - name = EntityTypeRest.RELATION_SHIP_TYPES, - method = "getEntityTypeRelationship" - ) + @LinkRest(name = EntityTypeRest.RELATION_SHIP_TYPES, method = "getEntityTypeRelationship") }) public class EntityTypeRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java index 58402954e8db..21f41241b293 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java @@ -13,10 +13,7 @@ * This class serves as a REST representation for an External Source */ @LinksRest(links = { - @LinkRest( - name = ExternalSourceRest.ENTITY_TYPES, - method = "getSupportedEntityTypes" - ) + @LinkRest(name = ExternalSourceRest.ENTITY_TYPES, method = "getSupportedEntityTypes") }) public class ExternalSourceRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java index 7d56af2e7204..0a4963b66fa0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java @@ -18,18 +18,9 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) @LinksRest(links = { - @LinkRest( - name = GroupRest.SUBGROUPS, - method = "getGroups" - ), - @LinkRest( - name = GroupRest.EPERSONS, - method = "getMembers" - ), - @LinkRest( - name = GroupRest.OBJECT, - method = "getParentObject" - ) + @LinkRest(name = GroupRest.SUBGROUPS, method = "getGroups"), + @LinkRest(name = GroupRest.EPERSONS, method = "getMembers"), + @LinkRest(name = GroupRest.OBJECT, method = "getParentObject") }) public class GroupRest extends DSpaceObjectRest { public static final String NAME = "group"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java index b2f540c0ac4a..293f95c4de39 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java @@ -17,42 +17,15 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = ItemRest.ACCESS_STATUS, - method = "getAccessStatus" - ), - @LinkRest( - name = ItemRest.BUNDLES, - method = "getBundles" - ), - @LinkRest( - name = ItemRest.IDENTIFIERS, - method = "getIdentifiers" - ), - @LinkRest( - name = ItemRest.MAPPED_COLLECTIONS, - method = "getMappedCollections" - ), - @LinkRest( - name = ItemRest.OWNING_COLLECTION, - method = "getOwningCollection" - ), - @LinkRest( - name = ItemRest.RELATIONSHIPS, - method = "getRelationships" - ), - @LinkRest( - name = ItemRest.VERSION, - method = "getItemVersion" - ), - @LinkRest( - name = ItemRest.TEMPLATE_ITEM_OF, - method = "getTemplateItemOf" - ), - @LinkRest( - name = ItemRest.THUMBNAIL, - method = "getThumbnail" - ) + @LinkRest(name = ItemRest.ACCESS_STATUS, method = "getAccessStatus"), + @LinkRest(name = ItemRest.BUNDLES, method = "getBundles"), + @LinkRest(name = ItemRest.IDENTIFIERS, method = "getIdentifiers"), + @LinkRest(name = ItemRest.MAPPED_COLLECTIONS, method = "getMappedCollections"), + @LinkRest(name = ItemRest.OWNING_COLLECTION, method = "getOwningCollection"), + @LinkRest(name = ItemRest.RELATIONSHIPS, method = "getRelationships"), + @LinkRest(name = ItemRest.VERSION, method = "getItemVersion"), + @LinkRest(name = ItemRest.TEMPLATE_ITEM_OF, method = "getTemplateItemOf"), + @LinkRest(name = ItemRest.THUMBNAIL, method = "getThumbnail") }) public class ItemRest extends DSpaceObjectRest { public static final String NAME = "item"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java index 2c4c7cbe6043..433d5626ca42 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java @@ -39,7 +39,7 @@ public class OrcidHistoryRest extends BaseObjectRest { private String responseMessage; - public OrcidHistoryRest(){} + public OrcidHistoryRest() {} @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java index 0b66f0604b2e..94c70037330e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java @@ -17,10 +17,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = PoolTaskRest.STEP, - method = "getStep" - ) + @LinkRest(name = PoolTaskRest.STEP, method = "getStep") }) public class PoolTaskRest extends BaseObjectRest { public static final String NAME = "pooltask"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java index d3d88c2776ce..fee104b4e389 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java @@ -21,18 +21,9 @@ * This class serves as a REST representation for the {@link Process} class */ @LinksRest(links = { - @LinkRest( - name = ProcessRest.FILES, - method = "getFilesFromProcess" - ), - @LinkRest( - name = ProcessRest.FILE_TYPES, - method = "getFileTypesFromProcess" - ), - @LinkRest( - name = ProcessRest.OUTPUT, - method = "getOutputFromProcess" - ) + @LinkRest(name = ProcessRest.FILES, method = "getFilesFromProcess"), + @LinkRest(name = ProcessRest.FILE_TYPES, method = "getFileTypesFromProcess"), + @LinkRest(name = ProcessRest.OUTPUT, method = "getOutputFromProcess") }) public class ProcessRest extends BaseObjectRest { public static final String NAME = "process"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java index 76a7a4348682..723f7e148b27 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java @@ -19,10 +19,7 @@ * Refer to {@link org.dspace.content.Relationship} for explanation about the properties */ @LinksRest(links = { - @LinkRest( - name = RelationshipRest.RELATIONSHIP_TYPE, - method = "getRelationshipType" - ) + @LinkRest(name = RelationshipRest.RELATIONSHIP_TYPE, method = "getRelationshipType") }) public class RelationshipRest extends BaseObjectRest { public static final String NAME = "relationship"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java index 13faa2e2bbdf..629dbdf85821 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java @@ -20,8 +20,8 @@ * */ @LinksRest(links = { - @LinkRest(name = ResearcherProfileRest.ITEM, method = "getItem"), - @LinkRest(name = ResearcherProfileRest.EPERSON, method = "getEPerson") + @LinkRest(name = ResearcherProfileRest.ITEM, method = "getItem"), + @LinkRest(name = ResearcherProfileRest.EPERSON, method = "getEPerson") }) public class ResearcherProfileRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionRest.java index c7210e892558..7b1a05127fc7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionRest.java @@ -21,7 +21,9 @@ * * @author Andrea Bollini (andrea.bollini at 4science.it) */ -@LinksRest(links = { @LinkRest(name = SuggestionRest.TARGET, method = "getTarget") }) +@LinksRest(links = { + @LinkRest(name = SuggestionRest.TARGET, method = "getTarget") +}) public class SuggestionRest extends BaseObjectRest { private static final long serialVersionUID = 1L; public static final String NAME = "suggestion"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionTargetRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionTargetRest.java index 65764507e247..b6518eff7488 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionTargetRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionTargetRest.java @@ -19,7 +19,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(name = SuggestionTargetRest.TARGET, method = "getTarget") + @LinkRest(name = SuggestionTargetRest.TARGET, method = "getTarget") }) public class SuggestionTargetRest extends BaseObjectRest { private static final long serialVersionUID = 1L; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java index 5aab7028a8c6..80f704c77936 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java @@ -13,14 +13,8 @@ * The REST object for the {@link org.dspace.versioning.VersionHistory} object */ @LinksRest(links = { - @LinkRest( - name = VersionHistoryRest.VERSIONS, - method = "getVersions" - ), - @LinkRest( - name = VersionHistoryRest.DRAFT_VERSION, - method = "getDraftVersion" - ) + @LinkRest(name = VersionHistoryRest.VERSIONS, method = "getVersions"), + @LinkRest(name = VersionHistoryRest.DRAFT_VERSION, method = "getDraftVersion") }) public class VersionHistoryRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java index 21bf82804dd2..d9ebdd67e408 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java @@ -16,14 +16,8 @@ * The REST object for the {@link org.dspace.versioning.Version} objects */ @LinksRest(links = { - @LinkRest( - name = VersionRest.VERSION_HISTORY, - method = "getVersionHistory" - ), - @LinkRest( - name = VersionRest.ITEM, - method = "getVersionItem" - ) + @LinkRest(name = VersionRest.VERSION_HISTORY, method = "getVersionHistory"), + @LinkRest(name = VersionRest.ITEM, method = "getVersionItem") }) public class VersionRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java index e5869a852521..884e14642cf9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java @@ -18,9 +18,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(name = VocabularyEntryDetailsRest.PARENT, method = "getParent"), - @LinkRest(name = VocabularyEntryDetailsRest.CHILDREN, method = "getChildren") - }) + @LinkRest(name = VocabularyEntryDetailsRest.PARENT, method = "getParent"), + @LinkRest(name = VocabularyEntryDetailsRest.CHILDREN, method = "getChildren") +}) public class VocabularyEntryDetailsRest extends BaseObjectRest { public static final String PLURAL_NAME = "vocabularyEntryDetails"; public static final String NAME = "vocabularyEntryDetail"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java index f119059c2bb7..a54d93c643b4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java @@ -15,9 +15,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(name = VocabularyRest.ENTRIES, - method = "filter" - ), + @LinkRest(name = VocabularyRest.ENTRIES, method = "filter"), }) public class VocabularyRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java index 0ec967d09876..9cef79aaf3be 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java @@ -18,14 +18,8 @@ * @author Maria Verdonck (Atmire) on 11/12/2019 */ @LinksRest(links = { - @LinkRest( - name = WorkflowDefinitionRest.COLLECTIONS_MAPPED_TO, - method = "getCollections" - ), - @LinkRest( - name = WorkflowDefinitionRest.STEPS, - method = "getSteps" - ) + @LinkRest(name = WorkflowDefinitionRest.COLLECTIONS_MAPPED_TO, method = "getCollections"), + @LinkRest(name = WorkflowDefinitionRest.STEPS, method = "getSteps") }) public class WorkflowDefinitionRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java index 65fa531c5e42..d08abb3546a3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java @@ -15,22 +15,10 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = WorkflowItemRest.STEP, - method = "getStep" - ), - @LinkRest( - name = WorkflowItemRest.SUBMITTER, - method = "getWorkflowItemSubmitter" - ), - @LinkRest( - name = WorkflowItemRest.ITEM, - method = "getWorkflowItemItem" - ), - @LinkRest( - name = WorkflowItemRest.COLLECTION, - method = "getWorkflowItemCollection" - ) + @LinkRest(name = WorkflowItemRest.STEP, method = "getStep"), + @LinkRest(name = WorkflowItemRest.SUBMITTER, method = "getWorkflowItemSubmitter"), + @LinkRest(name = WorkflowItemRest.ITEM, method = "getWorkflowItemItem"), + @LinkRest(name = WorkflowItemRest.COLLECTION, method = "getWorkflowItemCollection") }) public class WorkflowItemRest extends AInprogressSubmissionRest { public static final String NAME = "workflowitem"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java index b3397721c117..53ddf38709e4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java @@ -18,10 +18,7 @@ * @author Maria Verdonck (Atmire) on 10/01/2020 */ @LinksRest(links = { - @LinkRest( - name = WorkflowStepRest.ACTIONS, - method = "getActions" - ), + @LinkRest(name = WorkflowStepRest.ACTIONS, method = "getActions"), }) public class WorkflowStepRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java index e311cd259231..8e0d52123f99 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java @@ -15,22 +15,10 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = WorkspaceItemRest.SUPERVISION_ORDERS, - method = "getSupervisionOrders" - ), - @LinkRest( - name = WorkspaceItemRest.SUBMITTER, - method = "getWorkspaceItemSubmitter" - ), - @LinkRest( - name = WorkspaceItemRest.ITEM, - method = "getWorkspaceItemItem" - ), - @LinkRest( - name = WorkspaceItemRest.COLLECTION, - method = "getWorkspaceItemCollection" - ) + @LinkRest(name = WorkspaceItemRest.SUPERVISION_ORDERS, method = "getSupervisionOrders"), + @LinkRest(name = WorkspaceItemRest.SUBMITTER, method = "getWorkspaceItemSubmitter"), + @LinkRest(name = WorkspaceItemRest.ITEM, method = "getWorkspaceItemItem"), + @LinkRest(name = WorkspaceItemRest.COLLECTION, method = "getWorkspaceItemCollection") }) public class WorkspaceItemRest extends AInprogressSubmissionRest { public static final String NAME = "workspaceitem"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java index b358e785c3b3..df525f679323 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java @@ -13,7 +13,7 @@ */ public class RegexUtils { - private RegexUtils(){} + private RegexUtils() {} /** * Regular expression in the request mapping to accept UUID as identifier diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java index a154091a2eff..2a4cee8375be 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java @@ -17,7 +17,7 @@ public class RegistrationMatcher { - private RegistrationMatcher(){} + private RegistrationMatcher() {} public static Matcher matchRegistration(String email, UUID epersonUuid) { return allOf( From abfb86b791ee5dff051492f82e6b1e664f05d8ab Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 3 Dec 2024 09:34:02 -0600 Subject: [PATCH 310/632] Add newly required "should-stop" flag to errorprone config. See https://errorprone.info/docs/installation --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 7a2f9792aa7a..9f76eb74fb23 100644 --- a/pom.xml +++ b/pom.xml @@ -147,6 +147,7 @@ true -XDcompilePolicy=simple + --should-stop=ifError=FLOW -Xplugin:ErrorProne -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED From 52b310077617921aea05e4cec4c69a5b250dd632 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 3 Dec 2024 09:44:56 -0600 Subject: [PATCH 311/632] Fix duplicate code warning from errorprone. This "else if" clause is the same as the "else" and can be removed --- .../src/main/java/org/dspace/discovery/SolrServiceImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 0769310b8175..75f0a0ac4d05 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -1445,8 +1445,6 @@ protected String transformFacetField(DiscoverFacetField facetFieldConfig, String } else { return field + "_acid"; } - } else if (facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_STANDARD)) { - return field; } else { return field; } From a01983c23027642163f7a8f88525e5638784f428 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Oct 2024 17:02:14 -0500 Subject: [PATCH 312/632] Fix checkstyle.xml syntax for bump to 8.45.1 --- checkstyle.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkstyle.xml b/checkstyle.xml index e0fa808d83cb..a33fc4831950 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -92,7 +92,7 @@ For more information on CheckStyle configurations below, see: http://checkstyle. - + From eee743a72d779d7af940a0ecf83393f26c2b4de2 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Oct 2024 17:02:46 -0500 Subject: [PATCH 313/632] Minor checkstyle fixes after bump to 8.45.1. All are indentation / spacing fixes which are more strict now. --- .../rest/AuthenticationRestController.java | 2 +- .../app/rest/model/AuthorizationRest.java | 6 +-- .../dspace/app/rest/model/BitstreamRest.java | 15 ++----- .../app/rest/model/BrowseIndexRest.java | 10 +---- .../org/dspace/app/rest/model/BundleRest.java | 15 ++----- .../app/rest/model/ClaimedTaskRest.java | 5 +-- .../dspace/app/rest/model/CollectionRest.java | 40 ++++------------- .../dspace/app/rest/model/CommunityRest.java | 25 +++-------- .../dspace/app/rest/model/EPersonRest.java | 5 +-- .../dspace/app/rest/model/EntityTypeRest.java | 5 +-- .../app/rest/model/ExternalSourceRest.java | 5 +-- .../org/dspace/app/rest/model/GroupRest.java | 15 ++----- .../org/dspace/app/rest/model/ItemRest.java | 45 ++++--------------- .../app/rest/model/OrcidHistoryRest.java | 2 +- .../dspace/app/rest/model/PoolTaskRest.java | 5 +-- .../dspace/app/rest/model/ProcessRest.java | 15 ++----- .../app/rest/model/RelationshipRest.java | 5 +-- .../app/rest/model/ResearcherProfileRest.java | 4 +- .../app/rest/model/VersionHistoryRest.java | 10 +---- .../dspace/app/rest/model/VersionRest.java | 10 +---- .../model/VocabularyEntryDetailsRest.java | 6 +-- .../dspace/app/rest/model/VocabularyRest.java | 4 +- .../rest/model/WorkflowDefinitionRest.java | 10 +---- .../app/rest/model/WorkflowItemRest.java | 20 ++------- .../app/rest/model/WorkflowStepRest.java | 5 +-- .../app/rest/model/WorkspaceItemRest.java | 20 ++------- .../org/dspace/app/rest/utils/RegexUtils.java | 2 +- .../app/rest/matcher/RegistrationMatcher.java | 2 +- 28 files changed, 70 insertions(+), 243 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java index e8b8eb8e70da..2fbc116843ca 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java @@ -224,7 +224,7 @@ private AuthenticationTokenResource shortLivedTokenResponse(HttpServletRequest r * @return ResponseEntity */ @RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.PUT, RequestMethod.PATCH, - RequestMethod.DELETE }) + RequestMethod.DELETE }) public ResponseEntity login() { return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body("Only POST is allowed for login requests."); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java index 95f288831303..7aec2cb4b76e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java @@ -18,9 +18,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(method = "getEperson", name = AuthorizationRest.EPERSON), - @LinkRest(method = "getFeature", name = AuthorizationRest.FEATURE), - @LinkRest(method = "getObject", name = AuthorizationRest.OBJECT) + @LinkRest(method = "getEperson", name = AuthorizationRest.EPERSON), + @LinkRest(method = "getFeature", name = AuthorizationRest.FEATURE), + @LinkRest(method = "getObject", name = AuthorizationRest.OBJECT) }) public class AuthorizationRest extends BaseObjectRest { public static final String NAME = "authorization"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java index 8e9efc2680b7..77b558c0faab 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java @@ -16,18 +16,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = BitstreamRest.BUNDLE, - method = "getBundle" - ), - @LinkRest( - name = BitstreamRest.FORMAT, - method = "getFormat" - ), - @LinkRest( - name = BitstreamRest.THUMBNAIL, - method = "getThumbnail" - ) + @LinkRest(name = BitstreamRest.BUNDLE, method = "getBundle"), + @LinkRest(name = BitstreamRest.FORMAT, method = "getFormat"), + @LinkRest(name = BitstreamRest.THUMBNAIL, method = "getThumbnail") }) public class BitstreamRest extends DSpaceObjectRest { public static final String PLURAL_NAME = "bitstreams"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java index f7978f00fdf5..176b268e4be1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java @@ -20,14 +20,8 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = BrowseIndexRest.LINK_ITEMS, - method = "listBrowseItems" - ), - @LinkRest( - name = BrowseIndexRest.LINK_ENTRIES, - method = "listBrowseEntries" - ) + @LinkRest(name = BrowseIndexRest.LINK_ITEMS, method = "listBrowseItems"), + @LinkRest(name = BrowseIndexRest.LINK_ENTRIES, method = "listBrowseEntries") }) public class BrowseIndexRest extends BaseObjectRest { private static final long serialVersionUID = -4870333170249999559L; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java index dd4a80d488a8..7ef1ceed92c9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java @@ -16,18 +16,9 @@ * @author Jelle Pelgrims (jelle.pelgrims at atmire.com) */ @LinksRest(links = { - @LinkRest( - name = BundleRest.ITEM, - method = "getItem" - ), - @LinkRest( - name = BundleRest.BITSTREAMS, - method = "getBitstreams" - ), - @LinkRest( - name = BundleRest.PRIMARY_BITSTREAM, - method = "getPrimaryBitstream" - ) + @LinkRest(name = BundleRest.ITEM, method = "getItem"), + @LinkRest(name = BundleRest.BITSTREAMS, method = "getBitstreams"), + @LinkRest(name = BundleRest.PRIMARY_BITSTREAM, method = "getPrimaryBitstream") }) public class BundleRest extends DSpaceObjectRest { public static final String NAME = "bundle"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java index dd97fef44d0b..d9c907697573 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java @@ -16,10 +16,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = ClaimedTaskRest.STEP, - method = "getStep" - ) + @LinkRest(name = ClaimedTaskRest.STEP, method = "getStep") }) public class ClaimedTaskRest extends BaseObjectRest { public static final String NAME = "claimedtask"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java index 3f5ae3bb34c2..28ff9bcceb6b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java @@ -15,38 +15,14 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = CollectionRest.LICENSE, - method = "getLicense" - ), - @LinkRest( - name = CollectionRest.LOGO, - method = "getLogo" - ), - @LinkRest( - name = CollectionRest.MAPPED_ITEMS, - method = "getMappedItems" - ), - @LinkRest( - name = CollectionRest.PARENT_COMMUNITY, - method = "getParentCommunity" - ), - @LinkRest( - name = CollectionRest.ADMIN_GROUP, - method = "getAdminGroup" - ), - @LinkRest( - name = CollectionRest.SUBMITTERS_GROUP, - method = "getSubmittersGroup" - ), - @LinkRest( - name = CollectionRest.ITEM_READ_GROUP, - method = "getItemReadGroup" - ), - @LinkRest( - name = CollectionRest.BITSTREAM_READ_GROUP, - method = "getBitstreamReadGroup" - ), + @LinkRest(name = CollectionRest.LICENSE, method = "getLicense"), + @LinkRest(name = CollectionRest.LOGO, method = "getLogo"), + @LinkRest(name = CollectionRest.MAPPED_ITEMS, method = "getMappedItems"), + @LinkRest(name = CollectionRest.PARENT_COMMUNITY, method = "getParentCommunity"), + @LinkRest(name = CollectionRest.ADMIN_GROUP, method = "getAdminGroup"), + @LinkRest(name = CollectionRest.SUBMITTERS_GROUP, method = "getSubmittersGroup"), + @LinkRest(name = CollectionRest.ITEM_READ_GROUP, method = "getItemReadGroup"), + @LinkRest(name = CollectionRest.BITSTREAM_READ_GROUP, method = "getBitstreamReadGroup"), }) public class CollectionRest extends DSpaceObjectRest { public static final String NAME = "collection"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java index 86dc4b2c3900..08758ef9cc27 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java @@ -15,26 +15,11 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = CommunityRest.COLLECTIONS, - method = "getCollections" - ), - @LinkRest( - name = CommunityRest.LOGO, - method = "getLogo" - ), - @LinkRest( - name = CommunityRest.SUBCOMMUNITIES, - method = "getSubcommunities" - ), - @LinkRest( - name = CommunityRest.PARENT_COMMUNITY, - method = "getParentCommunity" - ), - @LinkRest( - name = CommunityRest.ADMIN_GROUP, - method = "getAdminGroup" - ) + @LinkRest(name = CommunityRest.COLLECTIONS, method = "getCollections"), + @LinkRest(name = CommunityRest.LOGO, method = "getLogo"), + @LinkRest(name = CommunityRest.SUBCOMMUNITIES, method = "getSubcommunities"), + @LinkRest(name = CommunityRest.PARENT_COMMUNITY, method = "getParentCommunity"), + @LinkRest(name = CommunityRest.ADMIN_GROUP, method = "getAdminGroup") }) public class CommunityRest extends DSpaceObjectRest { public static final String NAME = "community"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java index 7b4c683322a9..0c4f4d7b290b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java @@ -20,10 +20,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = EPersonRest.GROUPS, - method = "getGroups" - ) + @LinkRest(name = EPersonRest.GROUPS, method = "getGroups") }) public class EPersonRest extends DSpaceObjectRest { public static final String NAME = "eperson"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java index f777b3a29c18..f62ef2767ea9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java @@ -15,10 +15,7 @@ * Refer to {@link org.dspace.content.EntityType} for explanation of the properties */ @LinksRest(links = { - @LinkRest( - name = EntityTypeRest.RELATION_SHIP_TYPES, - method = "getEntityTypeRelationship" - ) + @LinkRest(name = EntityTypeRest.RELATION_SHIP_TYPES, method = "getEntityTypeRelationship") }) public class EntityTypeRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java index 639c2cf72e2e..2cd3712bdd53 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java @@ -13,10 +13,7 @@ * This class serves as a REST representation for an External Source */ @LinksRest(links = { - @LinkRest( - name = ExternalSourceRest.ENTITY_TYPES, - method = "getSupportedEntityTypes" - ) + @LinkRest(name = ExternalSourceRest.ENTITY_TYPES, method = "getSupportedEntityTypes") }) public class ExternalSourceRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java index 3f60b2d61fd6..332f5a5055fb 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java @@ -18,18 +18,9 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) @LinksRest(links = { - @LinkRest( - name = GroupRest.SUBGROUPS, - method = "getGroups" - ), - @LinkRest( - name = GroupRest.EPERSONS, - method = "getMembers" - ), - @LinkRest( - name = GroupRest.OBJECT, - method = "getParentObject" - ) + @LinkRest(name = GroupRest.SUBGROUPS, method = "getGroups"), + @LinkRest(name = GroupRest.EPERSONS, method = "getMembers"), + @LinkRest(name = GroupRest.OBJECT, method = "getParentObject") }) public class GroupRest extends DSpaceObjectRest { public static final String NAME = "group"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java index 1254ef8f9372..bd0530be5dc4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java @@ -17,42 +17,15 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = ItemRest.ACCESS_STATUS, - method = "getAccessStatus" - ), - @LinkRest( - name = ItemRest.BUNDLES, - method = "getBundles" - ), - @LinkRest( - name = ItemRest.IDENTIFIERS, - method = "getIdentifiers" - ), - @LinkRest( - name = ItemRest.MAPPED_COLLECTIONS, - method = "getMappedCollections" - ), - @LinkRest( - name = ItemRest.OWNING_COLLECTION, - method = "getOwningCollection" - ), - @LinkRest( - name = ItemRest.RELATIONSHIPS, - method = "getRelationships" - ), - @LinkRest( - name = ItemRest.VERSION, - method = "getItemVersion" - ), - @LinkRest( - name = ItemRest.TEMPLATE_ITEM_OF, - method = "getTemplateItemOf" - ), - @LinkRest( - name = ItemRest.THUMBNAIL, - method = "getThumbnail" - ) + @LinkRest(name = ItemRest.ACCESS_STATUS, method = "getAccessStatus"), + @LinkRest(name = ItemRest.BUNDLES, method = "getBundles"), + @LinkRest(name = ItemRest.IDENTIFIERS, method = "getIdentifiers"), + @LinkRest(name = ItemRest.MAPPED_COLLECTIONS, method = "getMappedCollections"), + @LinkRest(name = ItemRest.OWNING_COLLECTION, method = "getOwningCollection"), + @LinkRest(name = ItemRest.RELATIONSHIPS, method = "getRelationships"), + @LinkRest(name = ItemRest.VERSION, method = "getItemVersion"), + @LinkRest(name = ItemRest.TEMPLATE_ITEM_OF, method = "getTemplateItemOf"), + @LinkRest(name = ItemRest.THUMBNAIL, method = "getThumbnail") }) public class ItemRest extends DSpaceObjectRest { public static final String NAME = "item"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java index 02e0f4706208..abfc0a31dc6a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java @@ -38,7 +38,7 @@ public class OrcidHistoryRest extends BaseObjectRest { private String responseMessage; - public OrcidHistoryRest(){} + public OrcidHistoryRest() {} @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java index c32c2c95783a..320558f94671 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java @@ -17,10 +17,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = PoolTaskRest.STEP, - method = "getStep" - ) + @LinkRest(name = PoolTaskRest.STEP, method = "getStep") }) public class PoolTaskRest extends BaseObjectRest { public static final String NAME = "pooltask"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java index 8216e1617195..f7d8088d8a30 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java @@ -21,18 +21,9 @@ * This class serves as a REST representation for the {@link Process} class */ @LinksRest(links = { - @LinkRest( - name = ProcessRest.FILES, - method = "getFilesFromProcess" - ), - @LinkRest( - name = ProcessRest.FILE_TYPES, - method = "getFileTypesFromProcess" - ), - @LinkRest( - name = ProcessRest.OUTPUT, - method = "getOutputFromProcess" - ) + @LinkRest(name = ProcessRest.FILES, method = "getFilesFromProcess"), + @LinkRest(name = ProcessRest.FILE_TYPES, method = "getFileTypesFromProcess"), + @LinkRest(name = ProcessRest.OUTPUT, method = "getOutputFromProcess") }) public class ProcessRest extends BaseObjectRest { public static final String NAME = "process"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java index dd35a0726e9d..d4050cda9a34 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java @@ -19,10 +19,7 @@ * Refer to {@link org.dspace.content.Relationship} for explanation about the properties */ @LinksRest(links = { - @LinkRest( - name = RelationshipRest.RELATIONSHIP_TYPE, - method = "getRelationshipType" - ) + @LinkRest(name = RelationshipRest.RELATIONSHIP_TYPE, method = "getRelationshipType") }) public class RelationshipRest extends BaseObjectRest { public static final String NAME = "relationship"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java index 4224cfeeb924..1ebde12e854f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java @@ -20,8 +20,8 @@ * */ @LinksRest(links = { - @LinkRest(name = ResearcherProfileRest.ITEM, method = "getItem"), - @LinkRest(name = ResearcherProfileRest.EPERSON, method = "getEPerson") + @LinkRest(name = ResearcherProfileRest.ITEM, method = "getItem"), + @LinkRest(name = ResearcherProfileRest.EPERSON, method = "getEPerson") }) public class ResearcherProfileRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java index e93e131aadb7..51d926082e33 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java @@ -13,14 +13,8 @@ * The REST object for the {@link org.dspace.versioning.VersionHistory} object */ @LinksRest(links = { - @LinkRest( - name = VersionHistoryRest.VERSIONS, - method = "getVersions" - ), - @LinkRest( - name = VersionHistoryRest.DRAFT_VERSION, - method = "getDraftVersion" - ) + @LinkRest(name = VersionHistoryRest.VERSIONS, method = "getVersions"), + @LinkRest(name = VersionHistoryRest.DRAFT_VERSION, method = "getDraftVersion") }) public class VersionHistoryRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java index abdc64295fdc..b4a7ce2b016c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java @@ -16,14 +16,8 @@ * The REST object for the {@link org.dspace.versioning.Version} objects */ @LinksRest(links = { - @LinkRest( - name = VersionRest.VERSION_HISTORY, - method = "getVersionHistory" - ), - @LinkRest( - name = VersionRest.ITEM, - method = "getVersionItem" - ) + @LinkRest(name = VersionRest.VERSION_HISTORY, method = "getVersionHistory"), + @LinkRest(name = VersionRest.ITEM, method = "getVersionItem") }) public class VersionRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java index 30e5eb71cbff..964c67dbbe8e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java @@ -18,9 +18,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(name = VocabularyEntryDetailsRest.PARENT, method = "getParent"), - @LinkRest(name = VocabularyEntryDetailsRest.CHILDREN, method = "getChildren") - }) + @LinkRest(name = VocabularyEntryDetailsRest.PARENT, method = "getParent"), + @LinkRest(name = VocabularyEntryDetailsRest.CHILDREN, method = "getChildren") +}) public class VocabularyEntryDetailsRest extends BaseObjectRest { public static final String PLURAL_NAME = "vocabularyEntryDetails"; public static final String NAME = "vocabularyEntryDetail"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java index cc848b945b2f..45d13076acb2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java @@ -15,9 +15,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(name = VocabularyRest.ENTRIES, - method = "filter" - ), + @LinkRest(name = VocabularyRest.ENTRIES, method = "filter"), }) public class VocabularyRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java index 7c2de7071bde..9ea4e2ae8c22 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java @@ -18,14 +18,8 @@ * @author Maria Verdonck (Atmire) on 11/12/2019 */ @LinksRest(links = { - @LinkRest( - name = WorkflowDefinitionRest.COLLECTIONS_MAPPED_TO, - method = "getCollections" - ), - @LinkRest( - name = WorkflowDefinitionRest.STEPS, - method = "getSteps" - ) + @LinkRest(name = WorkflowDefinitionRest.COLLECTIONS_MAPPED_TO, method = "getCollections"), + @LinkRest(name = WorkflowDefinitionRest.STEPS, method = "getSteps") }) public class WorkflowDefinitionRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java index 4a840a0bb77b..e94cfd54644d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java @@ -15,22 +15,10 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = WorkflowItemRest.STEP, - method = "getStep" - ), - @LinkRest( - name = WorkflowItemRest.SUBMITTER, - method = "getWorkflowItemSubmitter" - ), - @LinkRest( - name = WorkflowItemRest.ITEM, - method = "getWorkflowItemItem" - ), - @LinkRest( - name = WorkflowItemRest.COLLECTION, - method = "getWorkflowItemCollection" - ) + @LinkRest(name = WorkflowItemRest.STEP, method = "getStep"), + @LinkRest(name = WorkflowItemRest.SUBMITTER, method = "getWorkflowItemSubmitter"), + @LinkRest(name = WorkflowItemRest.ITEM, method = "getWorkflowItemItem"), + @LinkRest(name = WorkflowItemRest.COLLECTION, method = "getWorkflowItemCollection") }) public class WorkflowItemRest extends AInprogressSubmissionRest { public static final String NAME = "workflowitem"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java index 648cffbca80d..91128fd05a7d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java @@ -18,10 +18,7 @@ * @author Maria Verdonck (Atmire) on 10/01/2020 */ @LinksRest(links = { - @LinkRest( - name = WorkflowStepRest.ACTIONS, - method = "getActions" - ), + @LinkRest(name = WorkflowStepRest.ACTIONS, method = "getActions"), }) public class WorkflowStepRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java index b40d1a4494f4..7693771fb9f2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java @@ -15,22 +15,10 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = WorkspaceItemRest.SUPERVISION_ORDERS, - method = "getSupervisionOrders" - ), - @LinkRest( - name = WorkspaceItemRest.SUBMITTER, - method = "getWorkspaceItemSubmitter" - ), - @LinkRest( - name = WorkspaceItemRest.ITEM, - method = "getWorkspaceItemItem" - ), - @LinkRest( - name = WorkspaceItemRest.COLLECTION, - method = "getWorkspaceItemCollection" - ) + @LinkRest(name = WorkspaceItemRest.SUPERVISION_ORDERS, method = "getSupervisionOrders"), + @LinkRest(name = WorkspaceItemRest.SUBMITTER, method = "getWorkspaceItemSubmitter"), + @LinkRest(name = WorkspaceItemRest.ITEM, method = "getWorkspaceItemItem"), + @LinkRest(name = WorkspaceItemRest.COLLECTION, method = "getWorkspaceItemCollection") }) public class WorkspaceItemRest extends AInprogressSubmissionRest { public static final String NAME = "workspaceitem"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java index 8739f6b8d57f..856e36457057 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java @@ -13,7 +13,7 @@ */ public class RegexUtils { - private RegexUtils(){} + private RegexUtils() {} /** * Regular expression in the request mapping to accept UUID as identifier diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java index a154091a2eff..2a4cee8375be 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java @@ -17,7 +17,7 @@ public class RegistrationMatcher { - private RegistrationMatcher(){} + private RegistrationMatcher() {} public static Matcher matchRegistration(String email, UUID epersonUuid) { return allOf( From 5d7b42603d5d68bbffef0226fca3116e7029e401 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 3 Dec 2024 09:34:02 -0600 Subject: [PATCH 314/632] Add newly required "should-stop" flag to errorprone config. See https://errorprone.info/docs/installation --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index f496ed7e879d..f3b09f3a9dd9 100644 --- a/pom.xml +++ b/pom.xml @@ -147,6 +147,7 @@ true -XDcompilePolicy=simple + --should-stop=ifError=FLOW -Xplugin:ErrorProne -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED From f7ee509423591c33621e9b6abf80135c08f16522 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 3 Dec 2024 09:44:56 -0600 Subject: [PATCH 315/632] Fix duplicate code warning from errorprone. This "else if" clause is the same as the "else" and can be removed --- .../src/main/java/org/dspace/discovery/SolrServiceImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 9339b574b578..34efe96ae7f8 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -1445,8 +1445,6 @@ protected String transformFacetField(DiscoverFacetField facetFieldConfig, String } else { return field + "_acid"; } - } else if (facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_STANDARD)) { - return field; } else { return field; } From b98696f4a7cbf5d1065fa18e22f025334f263b03 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 14 Jan 2025 14:46:27 -0600 Subject: [PATCH 316/632] Dependency convergence fix --- dspace-api/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 58bd8106e9af..dbc21d14ecb0 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -756,6 +756,11 @@ org.javassist javassist + + + org.yaml + snakeyaml + From 8c88e215b4741ce04ff54c1a0581fd50d50a4e15 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 14 Jan 2025 16:23:21 -0600 Subject: [PATCH 317/632] Tell Spring Boot to use the simple HttpURLConnection for RestClient, like in Spring boot 3.3 --- .../src/main/resources/application.properties | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dspace-server-webapp/src/main/resources/application.properties b/dspace-server-webapp/src/main/resources/application.properties index 8233298ef0b0..0d9b9cd836ec 100644 --- a/dspace-server-webapp/src/main/resources/application.properties +++ b/dspace-server-webapp/src/main/resources/application.properties @@ -135,3 +135,15 @@ spring.servlet.multipart.max-file-size = 512MB # Maximum size of a multipart request (i.e. max total size of all files in one request) (default = 10MB) spring.servlet.multipart.max-request-size = 512MB + +################################## +# Spring Boot's HTTP Client configuration (for RestClient and RestTemplate) +# https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes#restclient-and-resttemplate +# +# "simple" tells Spring Boot to use JDK's HttpURLConnection (SimpleClientHttpRequestFactory) +# We have to configure this explicitly for DSpace because Spring Boot's autoconfiguration will attempt to +# use Jetty or similar if found on the classpath (and Jetty is on the classpath for Handle Server, etc) +spring.http.client.factory = simple +# "dont_follow" tells Spring Boot not to follow any redirects itself, but instead return the 3xx code to +# the user's browser. +spring.http.client.redirects = dont_follow \ No newline at end of file From 6bbee7f27b72b783ebdb4e9350de8911dc3fc5cf Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 16 Jan 2025 12:01:13 +0100 Subject: [PATCH 318/632] 124362: Fix issue with the VersionedHandleIdentifierProviderWithCanonicalHandles and creating communities / collections --- ...dentifierProviderWithCanonicalHandles.java | 38 ++++++++++++------- .../config/spring/api/identifier-service.xml | 9 ++--- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java index 51458b4ad6e3..6f44fd332eb5 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java +++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java @@ -15,11 +15,14 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataValue; -import org.dspace.content.service.ItemService; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogHelper; @@ -62,9 +65,6 @@ public class VersionedHandleIdentifierProviderWithCanonicalHandles extends Ident @Autowired(required = true) private HandleService handleService; - @Autowired(required = true) - private ItemService itemService; - /** * After all the properties are set check that the versioning is enabled * @@ -171,6 +171,16 @@ public String register(Context context, DSpaceObject dso) { throw new RuntimeException("The current user is not authorized to change this item.", ex); } } + if (dso instanceof Collection || dso instanceof Community) { + try { + // Update the metadata with the handle for collections and communities. + modifyHandleMetadata(context, dso, getCanonical(id)); + } catch (SQLException ex) { + throw new RuntimeException("A problem with the database connection occured.", ex); + } catch (AuthorizeException ex) { + throw new RuntimeException("The current user is not authorized to change this item.", ex); + } + } return id; } @@ -489,27 +499,29 @@ protected String getCanonical(String identifier) { * Remove all handles from an item's metadata and add the supplied handle instead. * * @param context The relevant DSpace Context. - * @param item which item to modify + * @param dso which dso to modify * @param handle which handle to add * @throws SQLException if database error * @throws AuthorizeException if authorization error */ - protected void modifyHandleMetadata(Context context, Item item, String handle) + protected void modifyHandleMetadata(Context context, DSpaceObject dso, String handle) throws SQLException, AuthorizeException { // we want to exchange the old handle against the new one. To do so, we // load all identifiers, clear the metadata field, re add all // identifiers which are not from type handle and add the new handle. String handleref = handleService.getCanonicalForm(handle); - List identifiers = itemService - .getMetadata(item, MetadataSchemaEnum.DC.getName(), "identifier", "uri", Item.ANY); - itemService.clearMetadata(context, item, MetadataSchemaEnum.DC.getName(), "identifier", "uri", Item.ANY); + DSpaceObjectService dSpaceObjectService = + ContentServiceFactory.getInstance().getDSpaceObjectService(dso); + List identifiers = dSpaceObjectService + .getMetadata(dso, MetadataSchemaEnum.DC.getName(), "identifier", "uri", Item.ANY); + dSpaceObjectService.clearMetadata(context, dso, MetadataSchemaEnum.DC.getName(), "identifier", "uri", Item.ANY); for (MetadataValue identifier : identifiers) { if (this.supports(identifier.getValue())) { // ignore handles continue; } - itemService.addMetadata(context, - item, + dSpaceObjectService.addMetadata(context, + dso, identifier.getMetadataField(), identifier.getLanguage(), identifier.getValue(), @@ -517,9 +529,9 @@ protected void modifyHandleMetadata(Context context, Item item, String handle) identifier.getConfidence()); } if (!StringUtils.isEmpty(handleref)) { - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + dSpaceObjectService.addMetadata(context, dso, MetadataSchemaEnum.DC.getName(), "identifier", "uri", null, handleref); } - itemService.update(context, item); + dSpaceObjectService.update(context, dso); } } diff --git a/dspace/config/spring/api/identifier-service.xml b/dspace/config/spring/api/identifier-service.xml index 63ef5456acd7..96612f8f94c1 100644 --- a/dspace/config/spring/api/identifier-service.xml +++ b/dspace/config/spring/api/identifier-service.xml @@ -24,9 +24,9 @@ The VersionedHandleIdentifierProvider creates a new versioned handle for every new version. --> - - - + + + - - - - - + + + + - + 2.16.0 2.16.0 From c657f7770f30309b1656018771dd44e28b8c1c02 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Jan 2025 14:12:38 -0600 Subject: [PATCH 327/632] Sync a few dependency exclusions from dspace-8_x to dspace-7_x to fix convergence issues --- dspace-server-webapp/pom.xml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 35fa473fc170..9f630cf60df9 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -316,6 +316,13 @@ org.webjars.bowergithub.codeseven toastr 2.1.4 + + + + org.webjars.bowergithub.jquery + jquery-dist + + @@ -337,6 +344,13 @@ org.webjars.bowergithub.jashkenas backbone 1.4.1 + + + + org.webjars.bowergithub.jashkenas + underscore + + + + net.minidev + json-smart + + + + + + + net.minidev + json-smart + 2.5.0 From 4c46bc33be2692684ca87cb572c628dfca544ae2 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Jan 2025 15:07:10 -0600 Subject: [PATCH 328/632] Remove unused dependency --- dspace-sword/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index 12325533c5c5..c48266454604 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -36,11 +36,6 @@ - - org.dspace - dspace-api-lang - - org.springframework.boot From 1fc7587ddd64f02026c13d7f946a34092b23559b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:12:07 +0000 Subject: [PATCH 329/632] Bump de.digitalcollections.iiif:iiif-apis from 0.3.10 to 0.3.11 Bumps [de.digitalcollections.iiif:iiif-apis](https://github.com/dbmdz/iiif-apis) from 0.3.10 to 0.3.11. - [Release notes](https://github.com/dbmdz/iiif-apis/releases) - [Commits](https://github.com/dbmdz/iiif-apis/compare/0.3.10...0.3.11) --- updated-dependencies: - dependency-name: de.digitalcollections.iiif:iiif-apis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-iiif/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index 030ac31b3843..e1d6c4cbfbe4 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -111,7 +111,7 @@ de.digitalcollections.iiif iiif-apis - 0.3.10 + 0.3.11 org.javassist From 311880207a48daad3a7b7c3dbbd821c86d80f1a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:12:10 +0000 Subject: [PATCH 330/632] Bump com.opencsv:opencsv from 5.9 to 5.10 Bumps com.opencsv:opencsv from 5.9 to 5.10. --- updated-dependencies: - dependency-name: com.opencsv:opencsv dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 2f0e20ed228f..ea5eb69d3721 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -777,7 +777,7 @@ com.opencsv opencsv - 5.9 + 5.10 From 2e1bcc6ded0c340517ef2a9253854d9fd04069f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:12:20 +0000 Subject: [PATCH 331/632] Bump com.amazonaws:aws-java-sdk-s3 from 1.12.261 to 1.12.780 Bumps [com.amazonaws:aws-java-sdk-s3](https://github.com/aws/aws-sdk-java) from 1.12.261 to 1.12.780. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.261...1.12.780) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-s3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 2f0e20ed228f..f239c380e6bc 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -741,7 +741,7 @@ com.amazonaws aws-java-sdk-s3 - 1.12.261 + 1.12.780 9.4.55.v20240627 2.23.1 - 2.0.31 + 2.0.33 1.19.0 2.0.11 2.9.2 From 6007753cc7b122ca69b7208244107422f7a1e2fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:12:30 +0000 Subject: [PATCH 333/632] Bump org.apache.ant:ant from 1.10.14 to 1.10.15 Bumps org.apache.ant:ant from 1.10.14 to 1.10.15. --- updated-dependencies: - dependency-name: org.apache.ant:ant dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b45d029bd361..13536fcd80af 100644 --- a/pom.xml +++ b/pom.xml @@ -1380,7 +1380,7 @@ org.apache.ant ant - 1.10.14 + 1.10.15 org.apache.jena From f38fbe666e3f66248d71f981bba4dc6050b60168 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:12:30 +0000 Subject: [PATCH 334/632] Bump slf4j.version from 2.0.11 to 2.0.16 Bumps `slf4j.version` from 2.0.11 to 2.0.16. Updates `org.slf4j:jcl-over-slf4j` from 2.0.11 to 2.0.16 Updates `org.slf4j:slf4j-api` from 2.0.11 to 2.0.16 --- updated-dependencies: - dependency-name: org.slf4j:jcl-over-slf4j dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b45d029bd361..73a162a07abb 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ 2.23.1 2.0.31 1.19.0 - 2.0.11 + 2.0.16 2.9.2 1.78.1 From 2b5db943b228e9fb6efe286743669604a644c29d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:12:56 +0000 Subject: [PATCH 335/632] Bump org.scala-lang:scala-library from 2.13.11 to 2.13.16 Bumps [org.scala-lang:scala-library](https://github.com/scala/scala) from 2.13.11 to 2.13.16. - [Release notes](https://github.com/scala/scala/releases) - [Commits](https://github.com/scala/scala/compare/v2.13.11...v2.13.16) --- updated-dependencies: - dependency-name: org.scala-lang:scala-library dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index c42895ab4c49..943e0d6d005e 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -943,7 +943,7 @@ org.scala-lang scala-library - 2.13.11 + 2.13.16 test From bd16f7a9821e1acfbdf5691ed3a9f2562533159e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:13:00 +0000 Subject: [PATCH 336/632] Bump org.apache.bcel:bcel from 6.7.0 to 6.10.0 Bumps [org.apache.bcel:bcel](https://github.com/apache/commons-bcel) from 6.7.0 to 6.10.0. - [Changelog](https://github.com/apache/commons-bcel/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-bcel/compare/rel/commons-bcel-6.7.0...rel/commons-bcel-6.10.0) --- updated-dependencies: - dependency-name: org.apache.bcel:bcel dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index c42895ab4c49..17031911579f 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -823,7 +823,7 @@ org.apache.bcel bcel - 6.7.0 + 6.10.0 test From 80e39f7669edf1fbe195d2860845ca1b04ab383f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:13:06 +0000 Subject: [PATCH 337/632] Bump log4j.version from 2.23.1 to 2.24.3 Bumps `log4j.version` from 2.23.1 to 2.24.3. Updates `org.apache.logging.log4j:log4j-api` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-core` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-1.2-api` from 2.23.1 to 2.24.3 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-1.2-api dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2a97e8767bf9..fcf03e61655a 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ 1.1.1 9.4.57.v20241219 - 2.23.1 + 2.24.3 2.0.31 1.19.0 1.7.36 From 492f37307b32250ae41a78109ed7260083a08a67 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Jan 2025 16:55:18 -0600 Subject: [PATCH 338/632] Fix startup bug by upgrading gson --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a8d4dffc8ba8..6a911b008857 100644 --- a/pom.xml +++ b/pom.xml @@ -1351,7 +1351,7 @@ com.google.code.gson gson - 2.10.1 + 2.11.0 @@ -882,32 +882,32 @@ io.netty netty-buffer - 4.1.106.Final + 4.1.117.Final io.netty netty-transport - 4.1.106.Final + 4.1.117.Final io.netty netty-transport-native-unix-common - 4.1.106.Final + 4.1.117.Final io.netty netty-common - 4.1.106.Final + 4.1.117.Final io.netty netty-handler - 4.1.106.Final + 4.1.117.Final io.netty netty-codec - 4.1.106.Final + 4.1.117.Final org.apache.velocity diff --git a/pom.xml b/pom.xml index 523f50c38308..a92a91c81223 100644 --- a/pom.xml +++ b/pom.xml @@ -1685,7 +1685,7 @@ com.h2database h2 - 2.2.224 + 2.3.232 test From 9dcc4e6f7ce32e22c8492b3429077f1a991f1d1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 22:43:38 +0000 Subject: [PATCH 343/632] Bump the spring group with 4 updates Bumps the spring group with 4 updates: [org.springframework.security:spring-security-test](https://github.com/spring-projects/spring-security), [org.springframework.security:spring-security-core](https://github.com/spring-projects/spring-security), [org.springframework.security:spring-security-web](https://github.com/spring-projects/spring-security) and [org.springframework.security:spring-security-config](https://github.com/spring-projects/spring-security). Updates `org.springframework.security:spring-security-test` from 5.7.12 to 5.7.14 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/5.7.12...5.7.14) Updates `org.springframework.security:spring-security-core` from 5.7.12 to 5.7.14 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/5.7.12...5.7.14) Updates `org.springframework.security:spring-security-web` from 5.7.12 to 5.7.14 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/5.7.12...5.7.14) Updates `org.springframework.security:spring-security-config` from 5.7.12 to 5.7.14 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/5.7.12...5.7.14) Updates `org.springframework.security:spring-security-core` from 5.7.12 to 5.7.14 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/5.7.12...5.7.14) Updates `org.springframework.security:spring-security-web` from 5.7.12 to 5.7.14 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/5.7.12...5.7.14) Updates `org.springframework.security:spring-security-config` from 5.7.12 to 5.7.14 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/5.7.12...5.7.14) --- updated-dependencies: - dependency-name: org.springframework.security:spring-security-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-config dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-config dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 523f50c38308..40870b0b777f 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 11 5.3.39 2.7.18 - 5.7.12 + 5.7.14 5.6.15.Final 6.2.5.Final 42.7.3 From bf1aa3da7aabff7825b57e74851649f7d12c5c24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 22:43:50 +0000 Subject: [PATCH 344/632] Bump solr.client.version from 8.11.3 to 8.11.4 Bumps `solr.client.version` from 8.11.3 to 8.11.4. Updates `org.apache.solr:solr-solrj` from 8.11.3 to 8.11.4 Updates `org.apache.lucene:lucene-core` from 8.11.3 to 8.11.4 Updates `org.apache.lucene:lucene-analyzers-icu` from 8.11.3 to 8.11.4 Updates `org.apache.lucene:lucene-analyzers-smartcn` from 8.11.3 to 8.11.4 Updates `org.apache.lucene:lucene-analyzers-stempel` from 8.11.3 to 8.11.4 Updates `org.apache.solr:solr-core` from 8.11.3 to 8.11.4 --- updated-dependencies: - dependency-name: org.apache.solr:solr-solrj dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.lucene:lucene-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.lucene:lucene-analyzers-icu dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.lucene:lucene-analyzers-smartcn dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.lucene:lucene-analyzers-stempel dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.solr:solr-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 523f50c38308..57cd8066aa97 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ 5.6.15.Final 6.2.5.Final 42.7.3 - 8.11.3 + 8.11.4 3.10.8 2.31.0 From 8076745a09236ebd6636f1c6c83d906ee6cec0cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 22:43:53 +0000 Subject: [PATCH 345/632] Bump io.swagger:swagger-core from 1.6.2 to 1.6.15 Bumps [io.swagger:swagger-core](https://github.com/swagger-api/swagger-core) from 1.6.2 to 1.6.15. - [Release notes](https://github.com/swagger-api/swagger-core/releases) - [Commits](https://github.com/swagger-api/swagger-core/compare/v1.6.2...v1.6.15) --- updated-dependencies: - dependency-name: io.swagger:swagger-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index cf81408a2659..2ad962d88a3d 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -938,7 +938,7 @@ io.swagger swagger-core - 1.6.2 + 1.6.15 org.scala-lang From 88c094051e4d8223803661598859f217f8e61656 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 23:04:51 +0000 Subject: [PATCH 346/632] Bump com.github.spotbugs:spotbugs in the build-tools group Bumps the build-tools group with 1 update: [com.github.spotbugs:spotbugs](https://github.com/spotbugs/spotbugs). Updates `com.github.spotbugs:spotbugs` from 4.8.6 to 4.9.0 - [Release notes](https://github.com/spotbugs/spotbugs/releases) - [Changelog](https://github.com/spotbugs/spotbugs/blob/master/CHANGELOG.md) - [Commits](https://github.com/spotbugs/spotbugs/compare/4.8.6...4.9.0) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b45d029bd361..311cde285f92 100644 --- a/pom.xml +++ b/pom.xml @@ -313,7 +313,7 @@ com.github.spotbugs spotbugs - 4.8.6 + 4.9.0 From 4e73138c15151a94871cda778aa546f0e8b0413c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 19:07:26 +0000 Subject: [PATCH 347/632] Bump the spring group across 1 directory with 12 updates Bumps the spring group with 12 updates in the / directory: | Package | From | To | | --- | --- | --- | | [org.springframework:spring-orm](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-beans](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-aop](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-context-support](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-tx](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-jdbc](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-expression](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | | [org.springframework:spring-test](https://github.com/spring-projects/spring-framework) | `6.2.1` | `6.2.2` | Updates `org.springframework:spring-orm` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-core` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-beans` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-aop` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-context` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-context-support` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-tx` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-jdbc` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-web` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-webmvc` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-expression` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-test` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-core` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-beans` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-aop` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-context` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-context-support` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-tx` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-jdbc` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-web` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-webmvc` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-expression` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) Updates `org.springframework:spring-test` from 6.2.1 to 6.2.2 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.1...v6.2.2) --- updated-dependencies: - dependency-name: org.springframework:spring-orm dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d127c52a90ea..1362d83f5738 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 17 - 6.2.1 + 6.2.2 3.4.1 6.4.2 6.4.8.Final From b3e113900603d8aacbad84ae84543f4e59ad245b Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 21 Jan 2025 13:41:10 -0600 Subject: [PATCH 348/632] Remove swagger-core as it is unused --- dspace-api/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 2ad962d88a3d..8071b24b0841 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -935,11 +935,6 @@ validation-api 2.0.1.Final - - io.swagger - swagger-core - 1.6.15 - org.scala-lang scala-library From 7d4a5fc311cad860b18591fbd1d6381b340d5e5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:28:06 +0000 Subject: [PATCH 349/632] Bump bouncycastle.version from 1.78.1 to 1.80 Bumps `bouncycastle.version` from 1.78.1 to 1.80. Updates `org.bouncycastle:bcpkix-jdk18on` from 1.78.1 to 1.80 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) Updates `org.bouncycastle:bcprov-jdk18on` from 1.78.1 to 1.80 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) Updates `org.bouncycastle:bcutil-jdk18on` from 1.78.1 to 1.80 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) --- updated-dependencies: - dependency-name: org.bouncycastle:bcpkix-jdk18on dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.bouncycastle:bcprov-jdk18on dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.bouncycastle:bcutil-jdk18on dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3597b20f3311..6bdb1399fd7a 100644 --- a/pom.xml +++ b/pom.xml @@ -44,7 +44,7 @@ 1.7.36 2.9.2 - 1.78.1 + 1.80 From 9705c30f8a811b62b317532f2078e955c81d2548 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:28:11 +0000 Subject: [PATCH 350/632] Bump net.bytebuddy:byte-buddy from 1.11.13 to 1.16.1 Bumps [net.bytebuddy:byte-buddy](https://github.com/raphw/byte-buddy) from 1.11.13 to 1.16.1. - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.11.13...byte-buddy-1.16.1) --- updated-dependencies: - dependency-name: net.bytebuddy:byte-buddy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3597b20f3311..a7d025a57cf6 100644 --- a/pom.xml +++ b/pom.xml @@ -1814,7 +1814,7 @@ net.bytebuddy byte-buddy - 1.11.13 + 1.16.1 From 39e2ef2b304e0ba0b09cba3e67a2c67922c7e5ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:28:19 +0000 Subject: [PATCH 351/632] Bump pdfbox-version from 2.0.31 to 2.0.33 Bumps `pdfbox-version` from 2.0.31 to 2.0.33. Updates `org.apache.pdfbox:pdfbox` from 2.0.31 to 2.0.33 Updates `org.apache.pdfbox:fontbox` from 2.0.31 to 2.0.33 --- updated-dependencies: - dependency-name: org.apache.pdfbox:pdfbox dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.pdfbox:fontbox dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3597b20f3311..04cd35050b45 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 9.4.57.v20241219 2.24.3 - 2.0.31 + 2.0.33 1.19.0 1.7.36 2.9.2 From f547dc7957b1d82e2660de20e34bfde35bdd513e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:28:22 +0000 Subject: [PATCH 352/632] Bump bouncycastle.version from 1.78.1 to 1.80 Bumps `bouncycastle.version` from 1.78.1 to 1.80. Updates `org.bouncycastle:bcpkix-jdk18on` from 1.78.1 to 1.80 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) Updates `org.bouncycastle:bcprov-jdk18on` from 1.78.1 to 1.80 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) Updates `org.bouncycastle:bcutil-jdk18on` from 1.78.1 to 1.80 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) --- updated-dependencies: - dependency-name: org.bouncycastle:bcpkix-jdk18on dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.bouncycastle:bcprov-jdk18on dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.bouncycastle:bcutil-jdk18on dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7c52f6642ad9..1a9592eefc75 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 2.0.16 2.9.2 - 1.78.1 + 1.80 8.0.1 3.1.5 From e3abd1c129ed22daea69764f8d451f3ee7ec941d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:28:34 +0000 Subject: [PATCH 353/632] Bump org.apache.velocity:velocity-engine-core from 2.3 to 2.4.1 Bumps org.apache.velocity:velocity-engine-core from 2.3 to 2.4.1. --- updated-dependencies: - dependency-name: org.apache.velocity:velocity-engine-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 38c490c4dbd9..05a9b1ba8531 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -912,7 +912,7 @@ org.apache.velocity velocity-engine-core - 2.3 + 2.4.1 org.xmlunit From 9bca0c928b5b1f8319bbfdb4786b881636eecdc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:28:37 +0000 Subject: [PATCH 354/632] Bump net.cnri:cnri-servlet-container from 3.0.0 to 3.1.0 Bumps [net.cnri:cnri-servlet-container](https://gitlab.com/cnri/cnri-servlet-container) from 3.0.0 to 3.1.0. - [Commits](https://gitlab.com/cnri/cnri-servlet-container/compare/v3.0.0...v3.1.0) --- updated-dependencies: - dependency-name: net.cnri:cnri-servlet-container dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3597b20f3311..a2de1a0f5fbb 100644 --- a/pom.xml +++ b/pom.xml @@ -1389,7 +1389,7 @@ net.cnri cnri-servlet-container - 3.0.0 + 3.1.0 From 9d46a45191da6126bf2aa06dda8660ac63c604e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:28:48 +0000 Subject: [PATCH 355/632] Bump org.apache.ant:ant from 1.10.14 to 1.10.15 Bumps org.apache.ant:ant from 1.10.14 to 1.10.15. --- updated-dependencies: - dependency-name: org.apache.ant:ant dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3597b20f3311..ecdcf1e39237 100644 --- a/pom.xml +++ b/pom.xml @@ -1354,7 +1354,7 @@ org.apache.ant ant - 1.10.14 + 1.10.15 org.apache.jena From cd2fbbf51bbcb19c7e3eda091c00ebb03e7ecb6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:28:54 +0000 Subject: [PATCH 356/632] Bump dnsjava:dnsjava from 3.6.0 to 3.6.2 Bumps [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) from 3.6.0 to 3.6.2. - [Release notes](https://github.com/dnsjava/dnsjava/releases) - [Changelog](https://github.com/dnsjava/dnsjava/blob/master/Changelog) - [Commits](https://github.com/dnsjava/dnsjava/compare/v3.6.0...v3.6.2) --- updated-dependencies: - dependency-name: dnsjava:dnsjava dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 38c490c4dbd9..7c91f117254b 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -646,7 +646,7 @@ dnsjava dnsjava - 3.6.0 + 3.6.2 From 4900a1a5276b516a4e99da2136fef4f98722b2d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:29:40 +0000 Subject: [PATCH 357/632] Bump org.jboss.logging:jboss-logging from 3.4.3.Final to 3.6.1.Final Bumps [org.jboss.logging:jboss-logging](https://github.com/jboss-logging/jboss-logging) from 3.4.3.Final to 3.6.1.Final. - [Release notes](https://github.com/jboss-logging/jboss-logging/releases) - [Commits](https://github.com/jboss-logging/jboss-logging/compare/3.4.3.Final...3.6.1.Final) --- updated-dependencies: - dependency-name: org.jboss.logging:jboss-logging dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7c52f6642ad9..06e4c4a7bb09 100644 --- a/pom.xml +++ b/pom.xml @@ -1131,7 +1131,7 @@ org.jboss.logging jboss-logging - 3.4.3.Final + 3.6.1.Final From a10808556578cc551fd8bb35bf08d205101b3a15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:29:44 +0000 Subject: [PATCH 358/632] Bump net.minidev:json-smart from 2.5.0 to 2.5.1 Bumps [net.minidev:json-smart](https://github.com/netplex/json-smart-v2) from 2.5.0 to 2.5.1. - [Release notes](https://github.com/netplex/json-smart-v2/releases) - [Commits](https://github.com/netplex/json-smart-v2/compare/2.5.0...2.5.1) --- updated-dependencies: - dependency-name: net.minidev:json-smart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index cf0279ec9797..f4b00dcd3a6b 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -299,7 +299,7 @@ @@ -560,7 +560,7 @@ net.minidev json-smart - 2.5.0 + 2.5.1 From e4e11cd82a01eacb775da0922e0dc47ada0ba0ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:29:53 +0000 Subject: [PATCH 359/632] Bump flyway.version from 10.10.0 to 10.22.0 Bumps `flyway.version` from 10.10.0 to 10.22.0. Updates `org.flywaydb:flyway-core` from 10.10.0 to 10.22.0 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-10.10.0...flyway-10.22.0) Updates `org.flywaydb:flyway-database-postgresql` from 10.10.0 to 10.22.0 --- updated-dependencies: - dependency-name: org.flywaydb:flyway-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.flywaydb:flyway-database-postgresql dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7c52f6642ad9..de4ac0dfe6b3 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ 6.4.8.Final 8.0.1.Final 42.7.3 - 10.10.0 + 10.22.0 8.11.4 3.10.8 From b4a22b4e51523706fc6d7cc4ef614553f276823a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:30:00 +0000 Subject: [PATCH 360/632] Bump org.apache.httpcomponents.client5:httpclient5 from 5.3.1 to 5.4.1 Bumps [org.apache.httpcomponents.client5:httpclient5](https://github.com/apache/httpcomponents-client) from 5.3.1 to 5.4.1. - [Changelog](https://github.com/apache/httpcomponents-client/blob/rel/v5.4.1/RELEASE_NOTES.txt) - [Commits](https://github.com/apache/httpcomponents-client/compare/rel/v5.3.1...rel/v5.4.1) --- updated-dependencies: - dependency-name: org.apache.httpcomponents.client5:httpclient5 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index cf0279ec9797..802589db2523 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -598,7 +598,7 @@ org.apache.httpcomponents.client5 httpclient5 - 5.3.1 + 5.4.1 test From 995af98886840ce9b9e979235d5cd8e82f2c4037 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:30:10 +0000 Subject: [PATCH 361/632] Bump log4j.version from 2.23.1 to 2.24.3 Bumps `log4j.version` from 2.23.1 to 2.24.3. Updates `org.apache.logging.log4j:log4j-api` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-core` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.23.1 to 2.24.3 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7c52f6642ad9..316ac10b6900 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 1.1.1 9.4.55.v20240627 - 2.23.1 + 2.24.3 2.0.33 1.19.0 2.0.16 From 0b1d4c09306e3c4fc56cc1ec6e3f10c761767d8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:30:13 +0000 Subject: [PATCH 362/632] Bump org.apache.jena:apache-jena-libs from 4.9.0 to 4.10.0 Bumps org.apache.jena:apache-jena-libs from 4.9.0 to 4.10.0. --- updated-dependencies: - dependency-name: org.apache.jena:apache-jena-libs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7c52f6642ad9..4f5bf159af1c 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ - 4.9.0 + 4.10.0 UTF-8 From da3584759b3478d4c37e85e05359015ec03d6eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike=20Martin=20L=C3=B6hden?= Date: Wed, 15 Jan 2025 08:05:07 +0100 Subject: [PATCH 363/632] Add check to avoid adding empty array of values to an item. (cherry picked from commit 6e0124fcbb5e95bf7400deeedf8df1ccfca478f1) --- .../dspace/identifier/VersionedDOIIdentifierProvider.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java index e5a90907c7b6..b42c915163dc 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java @@ -354,7 +354,10 @@ void removePreviousVersionDOIsOutOfObject(Context c, Item item, String oldDoi) if (changed) { try { itemService.clearMetadata(c, item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, Item.ANY); - itemService.addMetadata(c, item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, newIdentifiers); + // Checks if Array newIdentifiers is empty to avoid adding null values to the metadata field. + if (!newIdentifiers.isEmpty()) { + itemService.addMetadata(c, item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, newIdentifiers); + } itemService.update(c, item); } catch (SQLException ex) { throw new RuntimeException("A problem with the database connection occured.", ex); From 33efc550e44fffb727c70d29d02608b2a3e89c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike=20Martin=20L=C3=B6hden?= Date: Wed, 15 Jan 2025 08:05:07 +0100 Subject: [PATCH 364/632] Add check to avoid adding empty array of values to an item. (cherry picked from commit 6e0124fcbb5e95bf7400deeedf8df1ccfca478f1) --- .../dspace/identifier/VersionedDOIIdentifierProvider.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java index e5a90907c7b6..b42c915163dc 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java @@ -354,7 +354,10 @@ void removePreviousVersionDOIsOutOfObject(Context c, Item item, String oldDoi) if (changed) { try { itemService.clearMetadata(c, item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, Item.ANY); - itemService.addMetadata(c, item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, newIdentifiers); + // Checks if Array newIdentifiers is empty to avoid adding null values to the metadata field. + if (!newIdentifiers.isEmpty()) { + itemService.addMetadata(c, item, MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, newIdentifiers); + } itemService.update(c, item); } catch (SQLException ex) { throw new RuntimeException("A problem with the database connection occured.", ex); From 8525273f17a4b0f228007dd0a76c862fb37e6f5d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 21:26:34 +0000 Subject: [PATCH 365/632] Bump jetty.version from 9.4.55.v20240627 to 9.4.57.v20241219 Bumps `jetty.version` from 9.4.55.v20240627 to 9.4.57.v20241219. Updates `org.eclipse.jetty:jetty-server` from 9.4.55.v20240627 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-deploy` from 9.4.55.v20240627 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-http` from 9.4.55.v20240627 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-io` from 9.4.55.v20240627 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-servlet` from 9.4.55.v20240627 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-util` from 9.4.55.v20240627 to 9.4.57.v20241219 Updates `org.eclipse.jetty:jetty-webapp` from 9.4.55.v20240627 to 9.4.57.v20241219 Updates `org.eclipse.jetty.http2:http2-common` from 9.4.55.v20240627 to 9.4.57.v20241219 --- updated-dependencies: - dependency-name: org.eclipse.jetty:jetty-server dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-deploy dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-http dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-io dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-servlet dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-util dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty:jetty-webapp dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.eclipse.jetty.http2:http2-common dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5cd47d01e6af..5c6d8c1b8dac 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ 4.0.5 1.1.1 - 9.4.55.v20240627 + 9.4.57.v20241219 2.24.3 2.0.33 1.19.0 From 1d44a6ebde25c3791465fe0d117d1b910187752c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 21:32:01 +0000 Subject: [PATCH 366/632] Bump org.postgresql:postgresql from 42.7.3 to 42.7.5 Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.3 to 42.7.5. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.3...REL42.7.5) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5cd47d01e6af..baf52604b76b 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 6.4.2 6.4.8.Final 8.0.1.Final - 42.7.3 + 42.7.5 10.22.0 8.11.4 From 569e0af6590d6ae1e091290d2a0281d80bdeac03 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 13:41:37 -0600 Subject: [PATCH 367/632] Resolve dependency convergence issue --- dspace-server-webapp/pom.xml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index f4b00dcd3a6b..ceb7d5cbb7dd 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -293,14 +293,6 @@ spring-expression ${spring.version} - - - @@ -610,6 +602,13 @@ com.jayway.jsonpath json-path + + + + net.minidev + json-smart + + com.jayway.jsonpath From 403cebb15cc46c2e32620adccb94e249256d4c8e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 21 Jan 2025 15:02:42 -0600 Subject: [PATCH 368/632] Fix dependency convergence issue with Jena --- dspace-swordv2/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index d218406a16cc..2e6b1a27d838 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -59,6 +59,11 @@ org.apache.geronimo.specs geronimo-stax-api_1.0_spec + + + org.apache.jena + jena-core + From 0a55995b7c49b4e276c7d2f55d022d2d3e793273 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:08:10 +0000 Subject: [PATCH 369/632] Remove unused joad-time dependency Bumps [joda-time:joda-time](https://github.com/JodaOrg/joda-time) from 2.12.5 to 2.13.0. - [Release notes](https://github.com/JodaOrg/joda-time/releases) - [Changelog](https://github.com/JodaOrg/joda-time/blob/main/RELEASE-NOTES.txt) - [Commits](https://github.com/JodaOrg/joda-time/compare/v2.12.5...v2.13.0) --- updated-dependencies: - dependency-name: joda-time:joda-time dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 59564fafff40..730cfe2cc938 100644 --- a/pom.xml +++ b/pom.xml @@ -1536,7 +1536,7 @@ joda-time joda-time - 2.12.5 + 2.13.0 com.sun.mail From f451307e6f5c69301b491837f3f33cd689958b69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:01 +0000 Subject: [PATCH 370/632] Bump com.amazonaws:aws-java-sdk-s3 from 1.12.261 to 1.12.780 Bumps [com.amazonaws:aws-java-sdk-s3](https://github.com/aws/aws-sdk-java) from 1.12.261 to 1.12.780. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.261...1.12.780) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-s3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index ce6cd41a8f0f..ff2a26cb61dd 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -756,7 +756,7 @@ com.amazonaws aws-java-sdk-s3 - 1.12.261 + 1.12.780 From 3767093c158b0fdddf66f33283128a41b234558c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:11 +0000 Subject: [PATCH 371/632] Bump org.atteo:evo-inflector from 1.2.1 to 1.3 Bumps [org.atteo:evo-inflector](https://github.com/atteo/evo-inflector) from 1.2.1 to 1.3. - [Commits](https://github.com/atteo/evo-inflector/compare/1.2.1...1.3) --- updated-dependencies: - dependency-name: org.atteo:evo-inflector dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-rest/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-rest/pom.xml b/dspace-rest/pom.xml index 3f4bdaf1d0d8..fa4e15e8b626 100644 --- a/dspace-rest/pom.xml +++ b/dspace-rest/pom.xml @@ -175,7 +175,7 @@ org.atteo evo-inflector - 1.2.1 + 1.3 org.apache.logging.log4j From 23321e84a5884d3a45d54b8c96f80a84fa3b122b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:12 +0000 Subject: [PATCH 372/632] Bump the spring group with 11 updates Bumps the spring group with 11 updates: | Package | From | To | | --- | --- | --- | | [org.springframework.boot:spring-boot-starter-test](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter-tomcat](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-maven-plugin](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter-cache](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter-web](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter-data-rest](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter-security](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter-aop](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter-actuator](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | | [org.springframework.boot:spring-boot-starter-log4j2](https://github.com/spring-projects/spring-boot) | `3.4.1` | `3.4.2` | Updates `org.springframework.boot:spring-boot-starter-test` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.1 to 3.4.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 49a0ebaad801..a7b547490fae 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 17 6.2.2 - 3.4.1 + 3.4.2 6.4.2 6.4.8.Final 8.0.1.Final From 35f664166b699e9291cd46ca4053cf1f95a034d9 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 23 Jan 2025 11:27:45 -0600 Subject: [PATCH 373/632] Remove outdated, unused Google Analytics APIs. Remove dependabot rules (as they only work for main branch) --- .github/dependabot.yml | 118 ----------------------------------------- dspace-api/pom.xml | 6 --- pom.xml | 6 --- 3 files changed, 130 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index b6412b25b660..000000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,118 +0,0 @@ -#------------------- -# DSpace's dependabot rules. Enables maven updates for all dependencies on a weekly basis -# for main and any maintenance branches. Security updates only apply to main. -#------------------- -version: 2 -updates: - - package-ecosystem: "maven" - directory: "/" - schedule: - interval: "weekly" - # Allow up to 10 open PRs for dependencies - open-pull-requests-limit: 10 - # Group together some upgrades in a single PR - groups: - # Group together all Build Tools in a single PR - build-tools: - applies-to: version-updates - patterns: - - "org.apache.maven.plugins:*" - - "*:*-maven-plugin" - - "*:maven-*-plugin" - - "com.github.spotbugs:spotbugs" - - "com.google.code.findbugs:*" - - "com.google.errorprone:*" - - "com.puppycrawl.tools:checkstyle" - - "org.sonatype.plugins:*" - exclude-patterns: - # Exclude anything from Spring, as that is in a separate group - - "org.springframework.*:*" - update-types: - - "minor" - - "patch" - test-tools: - applies-to: version-updates - patterns: - - "junit:*" - - "com.github.stefanbirker:system-rules" - - "com.h2database:*" - - "io.findify:s3mock*" - - "io.netty:*" - - "org.hamcrest:*" - - "org.mock-server:*" - - "org.mockito:*" - update-types: - - "minor" - - "patch" - # Group together all Apache Commons deps in a single PR - apache-commons: - applies-to: version-updates - patterns: - - "org.apache.commons:*" - - "commons-*:commons-*" - update-types: - - "minor" - - "patch" - # Group together all fasterxml deps in a single PR - fasterxml: - applies-to: version-updates - patterns: - - "com.fasterxml:*" - - "com.fasterxml.*:*" - update-types: - - "minor" - - "patch" - # Group together all Hibernate deps in a single PR - hibernate: - applies-to: version-updates - patterns: - - "org.hibernate.*:*" - update-types: - - "minor" - - "patch" - # Group together all Jakarta deps in a single PR - jakarta: - applies-to: version-updates - patterns: - - "jakarta.*:*" - - "org.eclipse.angus:jakarta.mail" - - "org.glassfish.jaxb:jaxb-runtime" - update-types: - - "minor" - - "patch" - # Group together all Google deps in a single PR - google-apis: - applies-to: version-updates - patterns: - - "com.google.apis:*" - - "com.google.api-client:*" - - "com.google.http-client:*" - - "com.google.oauth-client:*" - update-types: - - "minor" - - "patch" - # Group together all Spring deps in a single PR - spring: - applies-to: version-updates - patterns: - - "org.springframework:*" - - "org.springframework.*:*" - update-types: - - "minor" - - "patch" - # Group together all WebJARs deps in a single PR - webjars: - applies-to: version-updates - patterns: - - "org.webjars:*" - - "org.webjars.*:*" - update-types: - - "minor" - - "patch" - ignore: - # Don't try to auto-update any DSpace dependencies - - dependency-name: "org.dspace:*" - - dependency-name: "org.dspace.*:*" - # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. - - dependency-name: "*" - update-types: ["version-update:semver-major"] diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index f59d976c3358..bf16e9a34e78 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -692,12 +692,6 @@ ${flyway.version} - - - com.google.apis - google-api-services-analytics - - com.google.code.findbugs diff --git a/pom.xml b/pom.xml index 49a0ebaad801..afa6ed25c69c 100644 --- a/pom.xml +++ b/pom.xml @@ -1712,12 +1712,6 @@ 2.3.232 test - - - com.google.apis - google-api-services-analytics - v3-rev145-1.23.0 - From 1b850aaf0b042ade92c1d7ef2ff56a9b78704d6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:27 +0000 Subject: [PATCH 374/632] Bump net.minidev:json-smart from 2.5.0 to 2.5.1 Bumps [net.minidev:json-smart](https://github.com/netplex/json-smart-v2) from 2.5.0 to 2.5.1. - [Release notes](https://github.com/netplex/json-smart-v2/releases) - [Commits](https://github.com/netplex/json-smart-v2/compare/2.5.0...2.5.1) --- updated-dependencies: - dependency-name: net.minidev:json-smart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index e078bfea6253..7c4739dc79e9 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -509,7 +509,7 @@ net.minidev json-smart - 2.5.0 + 2.5.1 From 5fc18dc98bec8f6a4d421973c0618f54cea8f27b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:28 +0000 Subject: [PATCH 375/632] Bump org.antlr:antlr4-runtime from 4.13.1 to 4.13.2 Bumps [org.antlr:antlr4-runtime](https://github.com/antlr/antlr4) from 4.13.1 to 4.13.2. - [Release notes](https://github.com/antlr/antlr4/releases) - [Changelog](https://github.com/antlr/antlr4/blob/dev/CHANGES.txt) - [Commits](https://github.com/antlr/antlr4/compare/4.13.1...4.13.2) --- updated-dependencies: - dependency-name: org.antlr:antlr4-runtime dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 49a0ebaad801..6f4fb5985584 100644 --- a/pom.xml +++ b/pom.xml @@ -1138,7 +1138,7 @@ org.antlr antlr4-runtime - 4.13.1 + 4.13.2 From 9282a281ff4d3484f72bfa348df55164642c7401 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:32 +0000 Subject: [PATCH 376/632] Bump org.apache.james:apache-mime4j-core from 0.8.10 to 0.8.12 Bumps org.apache.james:apache-mime4j-core from 0.8.10 to 0.8.12. --- updated-dependencies: - dependency-name: org.apache.james:apache-mime4j-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 49a0ebaad801..f00daa6384c1 100644 --- a/pom.xml +++ b/pom.xml @@ -1316,7 +1316,7 @@ org.apache.james apache-mime4j-core - 0.8.10 + 0.8.12 From 0f3fc0eccb86a9e0d2a4df2f9d044b2ae55d43b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:37 +0000 Subject: [PATCH 377/632] Bump org.postgresql:postgresql from 42.7.3 to 42.7.5 Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.3 to 42.7.5. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.3...REL42.7.5) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 59564fafff40..e41992328c66 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 5.7.14 5.6.15.Final 6.2.5.Final - 42.7.3 + 42.7.5 8.11.4 3.10.8 From b94be265273e32a8f55e03ac8b905e677ffc5458 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:37 +0000 Subject: [PATCH 378/632] Bump joda-time:joda-time from 2.12.5 to 2.13.0 Bumps [joda-time:joda-time](https://github.com/JodaOrg/joda-time) from 2.12.5 to 2.13.0. - [Release notes](https://github.com/JodaOrg/joda-time/releases) - [Changelog](https://github.com/JodaOrg/joda-time/blob/main/RELEASE-NOTES.txt) - [Commits](https://github.com/JodaOrg/joda-time/compare/v2.12.5...v2.13.0) --- updated-dependencies: - dependency-name: joda-time:joda-time dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 49a0ebaad801..d5aec94b4c40 100644 --- a/pom.xml +++ b/pom.xml @@ -1541,7 +1541,7 @@ joda-time joda-time - 2.12.5 + 2.13.0 jakarta.activation From daa29e582a9c5d2c52e66c319cf981614073e503 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:43 +0000 Subject: [PATCH 379/632] Bump org.jboss.logging:jboss-logging from 3.4.3.Final to 3.6.1.Final Bumps [org.jboss.logging:jboss-logging](https://github.com/jboss-logging/jboss-logging) from 3.4.3.Final to 3.6.1.Final. - [Release notes](https://github.com/jboss-logging/jboss-logging/releases) - [Commits](https://github.com/jboss-logging/jboss-logging/compare/3.4.3.Final...3.6.1.Final) --- updated-dependencies: - dependency-name: org.jboss.logging:jboss-logging dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 59564fafff40..1c386f0f1163 100644 --- a/pom.xml +++ b/pom.xml @@ -1148,7 +1148,7 @@ org.jboss.logging jboss-logging - 3.4.3.Final + 3.6.1.Final From c1ee2e5c95b6f6addb6a93a9fb22709e29ea24e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:43 +0000 Subject: [PATCH 380/632] Bump com.ibm.icu:icu4j from 62.1 to 62.2 Bumps [com.ibm.icu:icu4j](https://github.com/unicode-org/icu) from 62.1 to 62.2. - [Release notes](https://github.com/unicode-org/icu/releases) - [Commits](https://github.com/unicode-org/icu/commits) --- updated-dependencies: - dependency-name: com.ibm.icu:icu4j dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 49a0ebaad801..573155020588 100644 --- a/pom.xml +++ b/pom.xml @@ -1634,7 +1634,7 @@ com.ibm.icu icu4j - 62.1 + 62.2 From d2d6740efd224717f03eedaf0971614b1cbe2ce6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:45 +0000 Subject: [PATCH 381/632] Bump org.apache.velocity:velocity-engine-core from 2.3 to 2.4.1 Bumps org.apache.velocity:velocity-engine-core from 2.3 to 2.4.1. --- updated-dependencies: - dependency-name: org.apache.velocity:velocity-engine-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index f59d976c3358..3af940c3d8be 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -789,7 +789,7 @@ org.apache.velocity velocity-engine-core - 2.3 + 2.4.1 From 75d747e40ad3c63a50a57d17d4270d8930c07104 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:23:46 +0000 Subject: [PATCH 382/632] Bump org.apache.james:apache-mime4j-core from 0.8.10 to 0.8.12 Bumps org.apache.james:apache-mime4j-core from 0.8.10 to 0.8.12. --- updated-dependencies: - dependency-name: org.apache.james:apache-mime4j-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 59564fafff40..f7b20122e02f 100644 --- a/pom.xml +++ b/pom.xml @@ -1320,7 +1320,7 @@ org.apache.james apache-mime4j-core - 0.8.10 + 0.8.12 From 20178bfcac780935fe59142005932466f611f778 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:24:00 +0000 Subject: [PATCH 383/632] Bump jersey.version from 3.1.5 to 3.1.10 Bumps `jersey.version` from 3.1.5 to 3.1.10. Updates `org.glassfish.jersey.core:jersey-client` from 3.1.5 to 3.1.10 Updates `org.glassfish.jersey.inject:jersey-hk2` from 3.1.5 to 3.1.10 --- updated-dependencies: - dependency-name: org.glassfish.jersey.core:jersey-client dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.glassfish.jersey.inject:jersey-hk2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 49a0ebaad801..13b734d66b1d 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 1.80 8.0.1 - 3.1.5 + 3.1.10 2.9.0 From 0d069354f7dbba1afcdfe44a6642c4763e7eb478 Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Mon, 23 Dec 2024 15:17:32 +0100 Subject: [PATCH 384/632] 122350: Move failRunningProcesses during tomcat startup to RestRepository --- .../dspace/scripts/ProcessServiceImpl.java | 47 +++++++------------ .../scripts/service/ProcessService.java | 10 ++++ .../repository/ProcessRestRepository.java | 7 +++ 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java index ab5147221cfc..b3893f744380 100644 --- a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java @@ -47,13 +47,12 @@ import org.dspace.eperson.Group; import org.dspace.scripts.service.ProcessService; import org.dspace.services.ConfigurationService; -import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; /** * The implementation for the {@link ProcessService} class */ -public class ProcessServiceImpl implements ProcessService, InitializingBean { +public class ProcessServiceImpl implements ProcessService { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ProcessService.class); @@ -75,33 +74,6 @@ public class ProcessServiceImpl implements ProcessService, InitializingBean { @Autowired private ConfigurationService configurationService; - @Override - public void afterPropertiesSet() throws Exception { - try { - Context context = new Context(); - - // Processes that were running or scheduled when tomcat crashed, should be cleaned up during startup. - List processesToBeFailed = findByStatusAndCreationTimeOlderThan( - context, List.of(ProcessStatus.RUNNING, ProcessStatus.SCHEDULED), new Date()); - for (Process process : processesToBeFailed) { - context.setCurrentUser(process.getEPerson()); - // Fail the process. - log.info("Process with ID {} did not complete before tomcat shutdown, failing it now.", - process.getID()); - fail(context, process); - // But still attach its log to the process. - appendLog(process.getID(), process.getName(), - "Process did not complete before tomcat shutdown.", - ProcessLogLevel.ERROR); - createLogBitstream(context, process); - } - - context.complete(); - } catch (Exception e) { - log.error("Unable to clean up Processes: ", e); - } - } - @Override public Process create(Context context, EPerson ePerson, String scriptName, List parameters, @@ -359,6 +331,23 @@ public int countByUser(Context context, EPerson user) throws SQLException { return processDAO.countByUser(context, user); } + @Override + public void failRunningProcesses(Context context) throws SQLException, IOException, AuthorizeException { + List processesToBeFailed = findByStatusAndCreationTimeOlderThan( + context, List.of(ProcessStatus.RUNNING, ProcessStatus.SCHEDULED), new Date()); + for (Process process : processesToBeFailed) { + context.setCurrentUser(process.getEPerson()); + // Fail the process. + log.info("Process with ID {} did not complete before tomcat shutdown, failing it now.", process.getID()); + fail(context, process); + // But still attach its log to the process. + appendLog(process.getID(), process.getName(), + "Process did not complete before tomcat shutdown.", + ProcessLogLevel.ERROR); + createLogBitstream(context, process); + } + } + private String formatLogLine(int processId, String scriptName, String output, ProcessLogLevel processLogLevel) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); StringBuilder sb = new StringBuilder(); diff --git a/dspace-api/src/main/java/org/dspace/scripts/service/ProcessService.java b/dspace-api/src/main/java/org/dspace/scripts/service/ProcessService.java index c6fc24888155..5df2ca15aad8 100644 --- a/dspace-api/src/main/java/org/dspace/scripts/service/ProcessService.java +++ b/dspace-api/src/main/java/org/dspace/scripts/service/ProcessService.java @@ -277,4 +277,14 @@ List findByStatusAndCreationTimeOlderThan(Context context, List Date: Mon, 23 Dec 2024 15:17:32 +0100 Subject: [PATCH 385/632] 122350: Move failRunningProcesses during tomcat startup to RestRepository --- .../dspace/scripts/ProcessServiceImpl.java | 47 +++++++------------ .../scripts/service/ProcessService.java | 10 ++++ .../repository/ProcessRestRepository.java | 7 +++ 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java index ab5147221cfc..b3893f744380 100644 --- a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java @@ -47,13 +47,12 @@ import org.dspace.eperson.Group; import org.dspace.scripts.service.ProcessService; import org.dspace.services.ConfigurationService; -import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; /** * The implementation for the {@link ProcessService} class */ -public class ProcessServiceImpl implements ProcessService, InitializingBean { +public class ProcessServiceImpl implements ProcessService { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ProcessService.class); @@ -75,33 +74,6 @@ public class ProcessServiceImpl implements ProcessService, InitializingBean { @Autowired private ConfigurationService configurationService; - @Override - public void afterPropertiesSet() throws Exception { - try { - Context context = new Context(); - - // Processes that were running or scheduled when tomcat crashed, should be cleaned up during startup. - List processesToBeFailed = findByStatusAndCreationTimeOlderThan( - context, List.of(ProcessStatus.RUNNING, ProcessStatus.SCHEDULED), new Date()); - for (Process process : processesToBeFailed) { - context.setCurrentUser(process.getEPerson()); - // Fail the process. - log.info("Process with ID {} did not complete before tomcat shutdown, failing it now.", - process.getID()); - fail(context, process); - // But still attach its log to the process. - appendLog(process.getID(), process.getName(), - "Process did not complete before tomcat shutdown.", - ProcessLogLevel.ERROR); - createLogBitstream(context, process); - } - - context.complete(); - } catch (Exception e) { - log.error("Unable to clean up Processes: ", e); - } - } - @Override public Process create(Context context, EPerson ePerson, String scriptName, List parameters, @@ -359,6 +331,23 @@ public int countByUser(Context context, EPerson user) throws SQLException { return processDAO.countByUser(context, user); } + @Override + public void failRunningProcesses(Context context) throws SQLException, IOException, AuthorizeException { + List processesToBeFailed = findByStatusAndCreationTimeOlderThan( + context, List.of(ProcessStatus.RUNNING, ProcessStatus.SCHEDULED), new Date()); + for (Process process : processesToBeFailed) { + context.setCurrentUser(process.getEPerson()); + // Fail the process. + log.info("Process with ID {} did not complete before tomcat shutdown, failing it now.", process.getID()); + fail(context, process); + // But still attach its log to the process. + appendLog(process.getID(), process.getName(), + "Process did not complete before tomcat shutdown.", + ProcessLogLevel.ERROR); + createLogBitstream(context, process); + } + } + private String formatLogLine(int processId, String scriptName, String output, ProcessLogLevel processLogLevel) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); StringBuilder sb = new StringBuilder(); diff --git a/dspace-api/src/main/java/org/dspace/scripts/service/ProcessService.java b/dspace-api/src/main/java/org/dspace/scripts/service/ProcessService.java index c6fc24888155..5df2ca15aad8 100644 --- a/dspace-api/src/main/java/org/dspace/scripts/service/ProcessService.java +++ b/dspace-api/src/main/java/org/dspace/scripts/service/ProcessService.java @@ -277,4 +277,14 @@ List findByStatusAndCreationTimeOlderThan(Context context, List Date: Fri, 24 Jan 2025 00:20:45 +0000 Subject: [PATCH 386/632] Bump net.bytebuddy:byte-buddy from 1.11.13 to 1.16.1 Bumps [net.bytebuddy:byte-buddy](https://github.com/raphw/byte-buddy) from 1.11.13 to 1.16.1. - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.11.13...byte-buddy-1.16.1) --- updated-dependencies: - dependency-name: net.bytebuddy:byte-buddy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3bd2c52ebd00..0d2175ccdcab 100644 --- a/pom.xml +++ b/pom.xml @@ -1813,7 +1813,7 @@ net.bytebuddy byte-buddy - 1.11.13 + 1.16.1 From 406e932f070a0d3a029391d524279ca99d658174 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 00:21:01 +0000 Subject: [PATCH 387/632] Bump org.apache.bcel:bcel from 6.7.0 to 6.10.0 Bumps [org.apache.bcel:bcel](https://github.com/apache/commons-bcel) from 6.7.0 to 6.10.0. - [Changelog](https://github.com/apache/commons-bcel/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-bcel/compare/rel/commons-bcel-6.7.0...rel/commons-bcel-6.10.0) --- updated-dependencies: - dependency-name: org.apache.bcel:bcel dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index fd00cc919a07..acb59fb2d492 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -796,7 +796,7 @@ org.apache.bcel bcel - 6.7.0 + 6.10.0 test From b59ad5ba556b5d52660aa9572b1072993ec12d5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 00:21:06 +0000 Subject: [PATCH 388/632] Bump com.nimbusds:nimbus-jose-jwt from 9.37.3 to 9.48 Bumps [com.nimbusds:nimbus-jose-jwt](https://bitbucket.org/connect2id/nimbus-jose-jwt) from 9.37.3 to 9.48. - [Changelog](https://bitbucket.org/connect2id/nimbus-jose-jwt/src/master/CHANGELOG.txt) - [Commits](https://bitbucket.org/connect2id/nimbus-jose-jwt/branches/compare/9.48..9.37.3) --- updated-dependencies: - dependency-name: com.nimbusds:nimbus-jose-jwt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3bd2c52ebd00..73b0dbd4c506 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ 2.9.0 - 9.37.3 + 9.48 From 9d2da83a7edfacda3046671a545f66c15547b6f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 00:21:29 +0000 Subject: [PATCH 389/632] Bump org.checkerframework:checker-qual from 3.31.0 to 3.48.4 Bumps [org.checkerframework:checker-qual](https://github.com/typetools/checker-framework) from 3.31.0 to 3.48.4. - [Release notes](https://github.com/typetools/checker-framework/releases) - [Changelog](https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/typetools/checker-framework/compare/checker-framework-3.31.0...checker-framework-3.48.4) --- updated-dependencies: - dependency-name: org.checkerframework:checker-qual dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3bd2c52ebd00..ef60604796d6 100644 --- a/pom.xml +++ b/pom.xml @@ -1344,7 +1344,7 @@ org.checkerframework checker-qual - 3.31.0 + 3.48.4 From 77efa5ce8872b4e14fb765534165355ad280cc9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 00:21:41 +0000 Subject: [PATCH 391/632] Bump com.ibm.icu:icu4j from 62.1 to 62.2 Bumps [com.ibm.icu:icu4j](https://github.com/unicode-org/icu) from 62.1 to 62.2. - [Release notes](https://github.com/unicode-org/icu/releases) - [Commits](https://github.com/unicode-org/icu/commits) --- updated-dependencies: - dependency-name: com.ibm.icu:icu4j dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1e396be2cd1d..a08f27485891 100644 --- a/pom.xml +++ b/pom.xml @@ -1606,7 +1606,7 @@ com.ibm.icu icu4j - 62.1 + 62.2 From 9b7f142decccb470538d437ccf8e6bb09bfaffeb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 00:21:45 +0000 Subject: [PATCH 392/632] Bump com.google.guava:guava from 32.0.0-jre to 32.1.3-jre Bumps [com.google.guava:guava](https://github.com/google/guava) from 32.0.0-jre to 32.1.3-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3bd2c52ebd00..82b4b615a509 100644 --- a/pom.xml +++ b/pom.xml @@ -1756,7 +1756,7 @@ com.google.guava guava - 32.0.0-jre + 32.1.3-jre From 63081494d87d36acdb3f9026ac14b431881ce41c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 00:22:13 +0000 Subject: [PATCH 393/632] Bump com.opencsv:opencsv from 5.9 to 5.10 Bumps com.opencsv:opencsv from 5.9 to 5.10. --- updated-dependencies: - dependency-name: com.opencsv:opencsv dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index ff2a26cb61dd..07d7f1d21c00 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -805,7 +805,7 @@ com.opencsv opencsv - 5.9 + 5.10 From 25be075b3c9679458cebc131cc692984da751121 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 00:22:28 +0000 Subject: [PATCH 394/632] Bump de.digitalcollections.iiif:iiif-apis from 0.3.10 to 0.3.11 Bumps [de.digitalcollections.iiif:iiif-apis](https://github.com/dbmdz/iiif-apis) from 0.3.10 to 0.3.11. - [Release notes](https://github.com/dbmdz/iiif-apis/releases) - [Commits](https://github.com/dbmdz/iiif-apis/compare/0.3.10...0.3.11) --- updated-dependencies: - dependency-name: de.digitalcollections.iiif:iiif-apis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-iiif/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index 49ee02b56500..86702fe01b96 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -98,7 +98,7 @@ de.digitalcollections.iiif iiif-apis - 0.3.10 + 0.3.11 org.javassist From 70ed55bb552cf4bfbce964291867b3950bfe0730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Chac=C3=B3n?= <167455436+oscar-escire@users.noreply.github.com> Date: Fri, 24 Jan 2025 10:08:22 -0600 Subject: [PATCH 395/632] added expunge request param and enabled workflowitem delete based on it (#9950) * added expunge request param and enabled workflowitem delete based on it * enabled expunge param only in workflowitem delete endpoint and IT * Remove invalid param from JavaDocs --------- Co-authored-by: Tim Donohue --- .../WorkflowItemRestRepository.java | 15 ++++- .../rest/WorkflowItemRestRepositoryIT.java | 65 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemRestRepository.java index f6c879b3efdf..3d852e9aabf0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemRestRepository.java @@ -71,6 +71,7 @@ public class WorkflowItemRestRepository extends DSpaceRestRepository { public static final String OPERATION_PATH_SECTIONS = "sections"; + public static final String REQUESTPARAMETER_EXPUNGE = "expunge"; private static final Logger log = LogManager.getLogger(); @@ -239,13 +240,25 @@ public void patch(Context context, HttpServletRequest request, String apiCategor * move the workflowitem back to the submitter workspace regardless to how the workflow is designed */ protected void delete(Context context, Integer id) { + String expungeParam = getRequestService() + .getCurrentRequest() + .getServletRequest() + .getParameter(REQUESTPARAMETER_EXPUNGE); + boolean expunge = false; + if (expungeParam != null) { + expunge = Boolean.parseBoolean(expungeParam); + } XmlWorkflowItem witem = null; try { witem = wis.find(context, id); if (witem == null) { throw new ResourceNotFoundException("WorkflowItem ID " + id + " not found"); } - wfs.abort(context, witem, context.getCurrentUser()); + if (expunge) { + wis.delete(context, witem); + } else { + wfs.abort(context, witem, context.getCurrentUser()); + } } catch (AuthorizeException e) { throw new RESTAuthorizationException(e); } catch (SQLException e) { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java index 6275360b3c5b..a9bbc752f875 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java @@ -686,6 +686,71 @@ public void deleteOneTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(1))); } + @Test + /** + * A delete request over a workflowitem with expunge param should result in delete item over detabase + * workspace + * + * @throws Exception + */ + public void deleteOneWithExpungeTest() throws Exception { + context.turnOffAuthorisationSystem(); + + //** GIVEN ** + //1. A community with one collection. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") + .withWorkflowGroup(1, admin).build(); + + //2. create a normal user to use as submitter + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("submitter@example.com") + .withPassword("dspace") + .build(); + + context.setCurrentUser(submitter); + + //3. a workflow item + XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1) + .withTitle("Workflow Item 1") + .withIssueDate("2017-10-17") + .build(); + + Item item = witem.getItem(); + + //Add a bitstream to the item + String bitstreamContent = "ThisIsSomeDummyText"; + Bitstream bitstream = null; + try (InputStream is = IOUtils.toInputStream(bitstreamContent, Charset.defaultCharset())) { + bitstream = BitstreamBuilder + .createBitstream(context, item, is) + .withName("Bitstream1") + .withMimeType("text/plain").build(); + } + + context.restoreAuthSystemState(); + + String token = getAuthToken(admin.getEmail(), password); + + // Delete the workflowitem + getClient(token).perform(delete("/api/workflow/workflowitems/" + witem.getID() + "?expunge=true")) + .andExpect(status().is(204)); + + // Trying to get deleted workflowitem should fail with 404 + getClient(token).perform(get("/api/workflow/workflowitems/" + witem.getID())) + .andExpect(status().is(404)); + + // the workflowitem's item should fail with 404 + getClient(token).perform(get("/api/core/items/" + item.getID())) + .andExpect(status().is(404)); + + // the workflowitem's bitstream should fail with 404 + getClient(token).perform(get("/api/core/bitstreams/" + bitstream.getID())) + .andExpect(status().is(404)); + } + @Test /** * Test the deposit of a workspaceitem POSTing to the resource workflowitems collection endpoint a workspaceitem (as From 10b3f06480ca43de24ce1ed81874a671a27e2963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Chac=C3=B3n?= <167455436+oscar-escire@users.noreply.github.com> Date: Fri, 24 Jan 2025 10:08:22 -0600 Subject: [PATCH 396/632] added expunge request param and enabled workflowitem delete based on it (#9950) * added expunge request param and enabled workflowitem delete based on it * enabled expunge param only in workflowitem delete endpoint and IT * Remove invalid param from JavaDocs --------- Co-authored-by: Tim Donohue --- .../WorkflowItemRestRepository.java | 15 ++++- .../rest/WorkflowItemRestRepositoryIT.java | 65 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemRestRepository.java index de39ff69fb9c..f34961727e25 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemRestRepository.java @@ -71,6 +71,7 @@ public class WorkflowItemRestRepository extends DSpaceRestRepository { public static final String OPERATION_PATH_SECTIONS = "sections"; + public static final String REQUESTPARAMETER_EXPUNGE = "expunge"; private static final Logger log = LogManager.getLogger(); @@ -239,13 +240,25 @@ public void patch(Context context, HttpServletRequest request, String apiCategor * move the workflowitem back to the submitter workspace regardless to how the workflow is designed */ protected void delete(Context context, Integer id) { + String expungeParam = getRequestService() + .getCurrentRequest() + .getServletRequest() + .getParameter(REQUESTPARAMETER_EXPUNGE); + boolean expunge = false; + if (expungeParam != null) { + expunge = Boolean.parseBoolean(expungeParam); + } XmlWorkflowItem witem = null; try { witem = wis.find(context, id); if (witem == null) { throw new ResourceNotFoundException("WorkflowItem ID " + id + " not found"); } - wfs.abort(context, witem, context.getCurrentUser()); + if (expunge) { + wis.delete(context, witem); + } else { + wfs.abort(context, witem, context.getCurrentUser()); + } } catch (AuthorizeException e) { throw new RESTAuthorizationException(e); } catch (SQLException e) { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java index 72612fc5eb53..fe8e67bbf564 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java @@ -686,6 +686,71 @@ public void deleteOneTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(1))); } + @Test + /** + * A delete request over a workflowitem with expunge param should result in delete item over detabase + * workspace + * + * @throws Exception + */ + public void deleteOneWithExpungeTest() throws Exception { + context.turnOffAuthorisationSystem(); + + //** GIVEN ** + //1. A community with one collection. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") + .withWorkflowGroup(1, admin).build(); + + //2. create a normal user to use as submitter + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("submitter@example.com") + .withPassword("dspace") + .build(); + + context.setCurrentUser(submitter); + + //3. a workflow item + XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1) + .withTitle("Workflow Item 1") + .withIssueDate("2017-10-17") + .build(); + + Item item = witem.getItem(); + + //Add a bitstream to the item + String bitstreamContent = "ThisIsSomeDummyText"; + Bitstream bitstream = null; + try (InputStream is = IOUtils.toInputStream(bitstreamContent, Charset.defaultCharset())) { + bitstream = BitstreamBuilder + .createBitstream(context, item, is) + .withName("Bitstream1") + .withMimeType("text/plain").build(); + } + + context.restoreAuthSystemState(); + + String token = getAuthToken(admin.getEmail(), password); + + // Delete the workflowitem + getClient(token).perform(delete("/api/workflow/workflowitems/" + witem.getID() + "?expunge=true")) + .andExpect(status().is(204)); + + // Trying to get deleted workflowitem should fail with 404 + getClient(token).perform(get("/api/workflow/workflowitems/" + witem.getID())) + .andExpect(status().is(404)); + + // the workflowitem's item should fail with 404 + getClient(token).perform(get("/api/core/items/" + item.getID())) + .andExpect(status().is(404)); + + // the workflowitem's bitstream should fail with 404 + getClient(token).perform(get("/api/core/bitstreams/" + bitstream.getID())) + .andExpect(status().is(404)); + } + @Test /** * Test the deposit of a workspaceitem POSTing to the resource workflowitems collection endpoint a workspaceitem (as From 96451f7391ec30548c2c61cc0288440a59dde527 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 24 Jan 2025 15:06:43 -0600 Subject: [PATCH 397/632] Dependency convergence fixes --- pom.xml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pom.xml b/pom.xml index 7be509838d00..dfe2347fd64c 100644 --- a/pom.xml +++ b/pom.xml @@ -1703,6 +1703,23 @@ com.google.http-client google-http-client 1.45.3 + + + com.google.errorprone + error_prone_annotations + + + com.google.j2objc + j2objc-annotations + + + + + + io.grpc + grpc-context + 1.69.0 com.google.http-client @@ -1724,6 +1741,13 @@ google-oauth-client 1.37.0 + + + com.google.http-client + google-http-client-gson + 1.43.3 + From 5169a55437f39756bf914336640619a2a6090e48 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 15 Nov 2024 13:41:37 -0600 Subject: [PATCH 398/632] Resolve dependency convergence issue --- dspace-server-webapp/pom.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 7c4739dc79e9..63de9fe721cd 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -270,6 +270,11 @@ com.fasterxml.jackson.datatype jackson-datatype-jdk8 + + + net.minidev + json-smart + @@ -553,6 +558,13 @@ com.jayway.jsonpath json-path test + + + + net.minidev + json-smart + + com.jayway.jsonpath From 1cc98e6c2d6a5f2ec6d713dfad326593362d8437 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 24 Jan 2025 16:31:05 -0600 Subject: [PATCH 399/632] Fix missing dependency errors for javax.el --- dspace-api/pom.xml | 5 +++++ pom.xml | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 38c490c4dbd9..a3184d9adff8 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -505,6 +505,11 @@ javax.servlet-api provided + + + javax.el + javax.el-api + javax.annotation javax.annotation-api diff --git a/pom.xml b/pom.xml index a2de1a0f5fbb..1399e1c05491 100644 --- a/pom.xml +++ b/pom.xml @@ -1548,6 +1548,12 @@ javax.servlet-api 3.1.0 + + + javax.el + javax.el-api + 3.0.0 + From f7902bce00f7e480f034a151b6b180294963e573 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 17 Sep 2024 14:36:06 -0400 Subject: [PATCH 400/632] On error in bulk operations, continue instead of panic-stopping. (cherry picked from commit bfeba1aa7a8119d083fd6a9e15b58bf55988d006) --- .../dspace/identifier/doi/DOIOrganiser.java | 61 +++++++++++++------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index 12f6d7c4fca4..88738226755d 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -13,7 +13,6 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.UUID; @@ -227,8 +226,16 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args } for (DOI doi : dois) { - organiser.reserve(doi); - context.uncacheEntity(doi); + doi = context.reloadEntity(doi); + try { + organiser.reserve(doi); + context.commit(); + } catch (RuntimeException e) { + System.err.format("DOI %s for object %s reservation failed, skipping: %s%n", + doi.getDSpaceObject().getID().toString(), + doi.getDoi(), e.getMessage()); + context.rollback(); + } } } catch (SQLException ex) { System.err.println("Error in database connection:" + ex.getMessage()); @@ -245,8 +252,16 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args + "that could be registered."); } for (DOI doi : dois) { - organiser.register(doi); - context.uncacheEntity(doi); + doi = context.reloadEntity(doi); + try { + organiser.register(doi); + context.commit(); + } catch (SQLException e) { + System.err.format("DOI %s for object %s registration failed, skipping: %s%n", + doi.getDSpaceObject().getID().toString(), + doi.getDoi(), e.getMessage()); + context.rollback(); + } } } catch (SQLException ex) { System.err.println("Error in database connection:" + ex.getMessage()); @@ -268,8 +283,9 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args } for (DOI doi : dois) { + doi = context.reloadEntity(doi); organiser.update(doi); - context.uncacheEntity(doi); + context.commit(); } } catch (SQLException ex) { System.err.println("Error in database connection:" + ex.getMessage()); @@ -286,12 +302,17 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args + "that could be deleted."); } - Iterator iterator = dois.iterator(); - while (iterator.hasNext()) { - DOI doi = iterator.next(); - iterator.remove(); - organiser.delete(doi.getDoi()); - context.uncacheEntity(doi); + for (DOI doi : dois) { + doi = context.reloadEntity(doi); + try { + organiser.delete(doi.getDoi()); + context.commit(); + } catch (SQLException e) { + System.err.format("DOI %s for object %s deletion failed, skipping: %s%n", + doi.getDSpaceObject().getID().toString(), + doi.getDoi(), e.getMessage()); + context.rollback(); + } } } catch (SQLException ex) { System.err.println("Error in database connection:" + ex.getMessage()); @@ -473,10 +494,10 @@ public void register(DOI doiRow, Filter filter) throws SQLException, DOIIdentifi } /** - * Register DOI with the provider + * Register DOI with the provider. * @param doiRow - doi to register - * @throws SQLException - * @throws DOIIdentifierException + * @throws SQLException passed through + * @throws DOIIdentifierException passed through */ public void register(DOI doiRow) throws SQLException, DOIIdentifierException { register(doiRow, this.filter); @@ -485,18 +506,18 @@ public void register(DOI doiRow) throws SQLException, DOIIdentifierException { /** * Reserve DOI with the provider, * @param doiRow - doi to reserve - * @throws SQLException - * @throws DOIIdentifierException */ public void reserve(DOI doiRow) { reserve(doiRow, this.filter); } /** - * Reserve DOI with the provider + * Reserve DOI with the provider. * @param doiRow - doi to reserve - * @throws SQLException - * @throws DOIIdentifierException + * @param filter - Logical item filter to determine whether this + * identifier should be reserved online. + * @throws IllegalStateException on invalid DOI. + * @throws RuntimeException on database error. */ public void reserve(DOI doiRow, Filter filter) { DSpaceObject dso = doiRow.getDSpaceObject(); From cc3841d2122e1df9595d2dade28f7614f00a0a6b Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 17 Sep 2024 16:22:01 -0400 Subject: [PATCH 401/632] Reorganize some documentation. (cherry picked from commit 77425163f2d14567013fad1b8e4f73eee631bd63) --- .../dspace/identifier/doi/package-info.java | 19 +++++++---------- .../dspace/identifier/ezid/package-info.java | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/identifier/ezid/package-info.java diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java b/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java index e92170daf0cf..30ee5c45dd33 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java @@ -6,17 +6,14 @@ * http://www.dspace.org/license/ */ /** - * Make requests to the DOI registration angencies, f.e.to - * EZID DOI service, and analyze the responses. - * + * Make requests to the DOI registration agencies and analyze the responses. + * + *

    + * {@link DOIOrganiser} is a tool for managing DOI registrations. + * *

    - * Use {@link org.dspace.identifier.ezid.EZIDRequestFactory#getInstance} to - * configure an {@link org.dspace.identifier.ezid.EZIDRequest} - * with your authority number and credentials. {@code EZIDRequest} encapsulates - * EZID's operations (lookup, create/mint, modify, delete...). - * An operation returns an {@link org.dspace.identifier.ezid.EZIDResponse} which - * gives easy access to EZID's status code and value, status of the underlying - * HTTP request, and key/value pairs found in the response body (if any). - *

    + * Classes specific to the DataCite + * registrar are here. See {@link org.dspace.identifier.ezid} for the + * EZID registrar. */ package org.dspace.identifier.doi; diff --git a/dspace-api/src/main/java/org/dspace/identifier/ezid/package-info.java b/dspace-api/src/main/java/org/dspace/identifier/ezid/package-info.java new file mode 100644 index 000000000000..bff0bdea26e0 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/ezid/package-info.java @@ -0,0 +1,21 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +/** + * DOI classes specific to the EZID registrar. + * + *

    + * Use {@link org.dspace.identifier.ezid.EZIDRequestFactory#getInstance} to + * configure an {@link org.dspace.identifier.ezid.EZIDRequest} + * with your authority number and credentials. {@code EZIDRequest} encapsulates + * EZID's operations (lookup, create/mint, modify, delete...). + * An operation returns an {@link org.dspace.identifier.ezid.EZIDResponse} which + * gives easy access to EZID's status code and value, status of the underlying + * HTTP request, and key/value pairs found in the response body (if any). + *

    + */ +package org.dspace.identifier.ezid; From 6d187a08fda16b5c24a281cc8e0e4d41dc335e66 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 21 Jan 2025 14:03:06 -0500 Subject: [PATCH 402/632] Document and handle the actual exceptions returned by register. (cherry picked from commit 2edea69ca3cbb1448557517bce25b96fbfc3bd8e) --- .../dspace/identifier/doi/DOIOrganiser.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index 88738226755d..507503ffaa15 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -264,10 +264,10 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args } } } catch (SQLException ex) { - System.err.println("Error in database connection:" + ex.getMessage()); + System.err.format("Error in database connection: %s%n", ex.getMessage()); ex.printStackTrace(System.err); - } catch (DOIIdentifierException ex) { - System.err.println("Error registering DOI identifier:" + ex.getMessage()); + } catch (RuntimeException ex) { + System.err.format("Error registering DOI identifier: %s%n", ex.getMessage()); } } @@ -422,12 +422,18 @@ public void list(String processName, PrintStream out, PrintStream err, Integer . /** * Register DOI with the provider - * @param doiRow - doi to register - * @param filter - logical item filter to override - * @throws SQLException - * @throws DOIIdentifierException + * @param doiRow DOI to register + * @param filter logical item filter to override + * @throws IllegalArgumentException + * if {@link doiRow} does not name an Item. + * @throws IllegalStateException + * on invalid DOI. + * @throws RuntimeException + * on database error. */ - public void register(DOI doiRow, Filter filter) throws SQLException, DOIIdentifierException { + public void register(DOI doiRow, Filter filter) + throws IllegalArgumentException, IllegalStateException, + RuntimeException { DSpaceObject dso = doiRow.getDSpaceObject(); if (Constants.ITEM != dso.getType()) { throw new IllegalArgumentException("Currenty DSpace supports DOIs for Items only."); @@ -495,11 +501,14 @@ public void register(DOI doiRow, Filter filter) throws SQLException, DOIIdentifi /** * Register DOI with the provider. - * @param doiRow - doi to register - * @throws SQLException passed through - * @throws DOIIdentifierException passed through + * @param doiRow DOI to register + * @throws IllegalArgumentException passed through. + * @throws IllegalStateException passed through. + * @throws RuntimeException passed through. */ - public void register(DOI doiRow) throws SQLException, DOIIdentifierException { + public void register(DOI doiRow) + throws IllegalStateException, IllegalArgumentException, + RuntimeException { register(doiRow, this.filter); } From e11c0bce4a23fda2ab5586f274e8a4ac17d4b432 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 17 Sep 2024 14:36:06 -0400 Subject: [PATCH 403/632] On error in bulk operations, continue instead of panic-stopping. (cherry picked from commit bfeba1aa7a8119d083fd6a9e15b58bf55988d006) --- .../dspace/identifier/doi/DOIOrganiser.java | 61 +++++++++++++------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index 05769e94bce5..9b12d37ce286 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -13,7 +13,6 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.UUID; @@ -227,8 +226,16 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args } for (DOI doi : dois) { - organiser.reserve(doi); - context.uncacheEntity(doi); + doi = context.reloadEntity(doi); + try { + organiser.reserve(doi); + context.commit(); + } catch (RuntimeException e) { + System.err.format("DOI %s for object %s reservation failed, skipping: %s%n", + doi.getDSpaceObject().getID().toString(), + doi.getDoi(), e.getMessage()); + context.rollback(); + } } } catch (SQLException ex) { System.err.println("Error in database connection:" + ex.getMessage()); @@ -245,8 +252,16 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args + "that could be registered."); } for (DOI doi : dois) { - organiser.register(doi); - context.uncacheEntity(doi); + doi = context.reloadEntity(doi); + try { + organiser.register(doi); + context.commit(); + } catch (SQLException e) { + System.err.format("DOI %s for object %s registration failed, skipping: %s%n", + doi.getDSpaceObject().getID().toString(), + doi.getDoi(), e.getMessage()); + context.rollback(); + } } } catch (SQLException ex) { System.err.println("Error in database connection:" + ex.getMessage()); @@ -268,8 +283,9 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args } for (DOI doi : dois) { + doi = context.reloadEntity(doi); organiser.update(doi); - context.uncacheEntity(doi); + context.commit(); } } catch (SQLException ex) { System.err.println("Error in database connection:" + ex.getMessage()); @@ -286,12 +302,17 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args + "that could be deleted."); } - Iterator iterator = dois.iterator(); - while (iterator.hasNext()) { - DOI doi = iterator.next(); - iterator.remove(); - organiser.delete(doi.getDoi()); - context.uncacheEntity(doi); + for (DOI doi : dois) { + doi = context.reloadEntity(doi); + try { + organiser.delete(doi.getDoi()); + context.commit(); + } catch (SQLException e) { + System.err.format("DOI %s for object %s deletion failed, skipping: %s%n", + doi.getDSpaceObject().getID().toString(), + doi.getDoi(), e.getMessage()); + context.rollback(); + } } } catch (SQLException ex) { System.err.println("Error in database connection:" + ex.getMessage()); @@ -473,10 +494,10 @@ public void register(DOI doiRow, Filter filter) throws SQLException, DOIIdentifi } /** - * Register DOI with the provider + * Register DOI with the provider. * @param doiRow - doi to register - * @throws SQLException - * @throws DOIIdentifierException + * @throws SQLException passed through + * @throws DOIIdentifierException passed through */ public void register(DOI doiRow) throws SQLException, DOIIdentifierException { register(doiRow, this.filter); @@ -485,18 +506,18 @@ public void register(DOI doiRow) throws SQLException, DOIIdentifierException { /** * Reserve DOI with the provider, * @param doiRow - doi to reserve - * @throws SQLException - * @throws DOIIdentifierException */ public void reserve(DOI doiRow) { reserve(doiRow, this.filter); } /** - * Reserve DOI with the provider + * Reserve DOI with the provider. * @param doiRow - doi to reserve - * @throws SQLException - * @throws DOIIdentifierException + * @param filter - Logical item filter to determine whether this + * identifier should be reserved online. + * @throws IllegalStateException on invalid DOI. + * @throws RuntimeException on database error. */ public void reserve(DOI doiRow, Filter filter) { DSpaceObject dso = doiRow.getDSpaceObject(); From 6f1cfa20bdc68ecb26a0825fac146a5b2cd395e3 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 17 Sep 2024 16:22:01 -0400 Subject: [PATCH 404/632] Reorganize some documentation. (cherry picked from commit 77425163f2d14567013fad1b8e4f73eee631bd63) --- .../dspace/identifier/doi/package-info.java | 19 +++++++---------- .../dspace/identifier/ezid/package-info.java | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/identifier/ezid/package-info.java diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java b/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java index e92170daf0cf..30ee5c45dd33 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java @@ -6,17 +6,14 @@ * http://www.dspace.org/license/ */ /** - * Make requests to the DOI registration angencies, f.e.to - * EZID DOI service, and analyze the responses. - * + * Make requests to the DOI registration agencies and analyze the responses. + * + *

    + * {@link DOIOrganiser} is a tool for managing DOI registrations. + * *

    - * Use {@link org.dspace.identifier.ezid.EZIDRequestFactory#getInstance} to - * configure an {@link org.dspace.identifier.ezid.EZIDRequest} - * with your authority number and credentials. {@code EZIDRequest} encapsulates - * EZID's operations (lookup, create/mint, modify, delete...). - * An operation returns an {@link org.dspace.identifier.ezid.EZIDResponse} which - * gives easy access to EZID's status code and value, status of the underlying - * HTTP request, and key/value pairs found in the response body (if any). - *

    + * Classes specific to the DataCite + * registrar are here. See {@link org.dspace.identifier.ezid} for the + * EZID registrar. */ package org.dspace.identifier.doi; diff --git a/dspace-api/src/main/java/org/dspace/identifier/ezid/package-info.java b/dspace-api/src/main/java/org/dspace/identifier/ezid/package-info.java new file mode 100644 index 000000000000..bff0bdea26e0 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/ezid/package-info.java @@ -0,0 +1,21 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +/** + * DOI classes specific to the EZID registrar. + * + *

    + * Use {@link org.dspace.identifier.ezid.EZIDRequestFactory#getInstance} to + * configure an {@link org.dspace.identifier.ezid.EZIDRequest} + * with your authority number and credentials. {@code EZIDRequest} encapsulates + * EZID's operations (lookup, create/mint, modify, delete...). + * An operation returns an {@link org.dspace.identifier.ezid.EZIDResponse} which + * gives easy access to EZID's status code and value, status of the underlying + * HTTP request, and key/value pairs found in the response body (if any). + *

    + */ +package org.dspace.identifier.ezid; From 4d71205c684a44ae4ffa15e09ed5d0f12ca27e2d Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 21 Jan 2025 14:03:06 -0500 Subject: [PATCH 405/632] Document and handle the actual exceptions returned by register. (cherry picked from commit 2edea69ca3cbb1448557517bce25b96fbfc3bd8e) --- .../dspace/identifier/doi/DOIOrganiser.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index 9b12d37ce286..fc978d3813fb 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -264,10 +264,10 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args } } } catch (SQLException ex) { - System.err.println("Error in database connection:" + ex.getMessage()); + System.err.format("Error in database connection: %s%n", ex.getMessage()); ex.printStackTrace(System.err); - } catch (DOIIdentifierException ex) { - System.err.println("Error registering DOI identifier:" + ex.getMessage()); + } catch (RuntimeException ex) { + System.err.format("Error registering DOI identifier: %s%n", ex.getMessage()); } } @@ -422,12 +422,18 @@ public void list(String processName, PrintStream out, PrintStream err, Integer . /** * Register DOI with the provider - * @param doiRow - doi to register - * @param filter - logical item filter to override - * @throws SQLException - * @throws DOIIdentifierException + * @param doiRow DOI to register + * @param filter logical item filter to override + * @throws IllegalArgumentException + * if {@link doiRow} does not name an Item. + * @throws IllegalStateException + * on invalid DOI. + * @throws RuntimeException + * on database error. */ - public void register(DOI doiRow, Filter filter) throws SQLException, DOIIdentifierException { + public void register(DOI doiRow, Filter filter) + throws IllegalArgumentException, IllegalStateException, + RuntimeException { DSpaceObject dso = doiRow.getDSpaceObject(); if (Constants.ITEM != dso.getType()) { throw new IllegalArgumentException("Currenty DSpace supports DOIs for Items only."); @@ -495,11 +501,14 @@ public void register(DOI doiRow, Filter filter) throws SQLException, DOIIdentifi /** * Register DOI with the provider. - * @param doiRow - doi to register - * @throws SQLException passed through - * @throws DOIIdentifierException passed through + * @param doiRow DOI to register + * @throws IllegalArgumentException passed through. + * @throws IllegalStateException passed through. + * @throws RuntimeException passed through. */ - public void register(DOI doiRow) throws SQLException, DOIIdentifierException { + public void register(DOI doiRow) + throws IllegalStateException, IllegalArgumentException, + RuntimeException { register(doiRow, this.filter); } From 338e17d1973c4a910b2a3ef4e03068127070378b Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 24 Jan 2025 16:45:20 -0600 Subject: [PATCH 406/632] Remove unused configuration (cherry picked from commit 845c706cacdc13706acd120a63083764d3141194) --- dspace-api/src/test/data/dspaceFolder/config/local.cfg | 2 -- dspace/config/dspace.cfg | 2 -- 2 files changed, 4 deletions(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index 35ed8a235b75..0b4fe8288cfa 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -156,8 +156,6 @@ useProxies = true proxies.trusted.ipranges = 7.7.7.7 proxies.trusted.include_ui_ip = true -csvexport.dir = dspace-server-webapp/src/test/data/dspaceFolder/exports - # For the tests we have to disable this health indicator because there isn't a mock server and the calculated status was DOWN management.health.solrOai.enabled = false diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index c21fb54655b8..14d962f56839 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -19,8 +19,6 @@ # Windows note: Please remember to use forward slashes for all paths (e.g. C:/dspace) dspace.dir = /dspace -csvexport.dir = ${dspace.dir}/exports - # Public URL of DSpace backend ('server' webapp). May require a port number if not using standard ports (80 or 443) # DO NOT end it with '/'. # This is where REST API and all enabled server modules (OAI-PMH, SWORD, SWORDv2, RDF, etc) will respond. From 3978c806b1f3eda7c8f5b60b41924a6ef212066c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 24 Jan 2025 16:45:20 -0600 Subject: [PATCH 407/632] Remove unused configuration (cherry picked from commit 845c706cacdc13706acd120a63083764d3141194) --- dspace-api/src/test/data/dspaceFolder/config/local.cfg | 2 -- dspace/config/dspace.cfg | 2 -- 2 files changed, 4 deletions(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index b44f319a35f6..43b6d05e5e42 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -156,8 +156,6 @@ useProxies = true proxies.trusted.ipranges = 7.7.7.7 proxies.trusted.include_ui_ip = true -csvexport.dir = dspace-server-webapp/src/test/data/dspaceFolder/exports - # For the tests we have to disable this health indicator because there isn't a mock server and the calculated status was DOWN management.health.solrOai.enabled = false diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 7896560c12c8..8ea7e113bb79 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -19,8 +19,6 @@ # Windows note: Please remember to use forward slashes for all paths (e.g. C:/dspace) dspace.dir = /dspace -csvexport.dir = ${dspace.dir}/exports - # Public URL of DSpace backend ('server' webapp). May require a port number if not using standard ports (80 or 443) # DO NOT end it with '/'. # This is where REST API and all enabled server modules (OAI-PMH, SWORD, SWORDv2, RDF, etc) will respond. From 576561d6183e4a97d0e4100ba6875fc675cac06d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 22:22:57 +0000 Subject: [PATCH 408/632] Bump dnsjava:dnsjava from 3.6.2 to 3.6.3 Bumps [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) from 3.6.2 to 3.6.3. - [Release notes](https://github.com/dnsjava/dnsjava/releases) - [Changelog](https://github.com/dnsjava/dnsjava/blob/master/Changelog) - [Commits](https://github.com/dnsjava/dnsjava/compare/v3.6.2...v3.6.3) --- updated-dependencies: - dependency-name: dnsjava:dnsjava dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index acb59fb2d492..6ed22b9177b0 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -648,7 +648,7 @@ dnsjava dnsjava - 3.6.2 + 3.6.3 From e8a54e698c9f92eb0f7e049d76049c9fbe77203e Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Wed, 29 Jan 2025 12:42:25 +0100 Subject: [PATCH 409/632] cli speed improvement: periodically uncache entities when processing many --- .../src/main/java/org/dspace/core/Context.java | 12 ++++++++++++ .../src/main/java/org/dspace/core/DBConnection.java | 12 ++++++++++++ .../java/org/dspace/core/HibernateDBConnection.java | 6 ++++++ .../java/org/dspace/discovery/SolrServiceImpl.java | 6 ++++++ 4 files changed, 36 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/core/Context.java b/dspace-api/src/main/java/org/dspace/core/Context.java index 82b39dd2dfc7..391405c0ae66 100644 --- a/dspace-api/src/main/java/org/dspace/core/Context.java +++ b/dspace-api/src/main/java/org/dspace/core/Context.java @@ -951,4 +951,16 @@ public void setAuthenticationMethod(final String authenticationMethod) { public boolean isContextUserSwitched() { return currentUserPreviousState != null; } + + /** + * Remove all entities from the cache and reload the current user entity. This is useful when batch processing + * a large number of entities when the calling code requires the cache to be completely cleared before continuing. + * + * @throws SQLException if a database error occurs. + */ + public void uncacheEntities() throws SQLException { + dbConnection.uncacheEntities(); + reloadContextBoundEntities(); + } + } diff --git a/dspace-api/src/main/java/org/dspace/core/DBConnection.java b/dspace-api/src/main/java/org/dspace/core/DBConnection.java index cb5825eec1d9..210998902c52 100644 --- a/dspace-api/src/main/java/org/dspace/core/DBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/DBConnection.java @@ -148,4 +148,16 @@ public interface DBConnection { * @throws java.sql.SQLException passed through. */ public void uncacheEntity(E entity) throws SQLException; + + /** + * Remove all entities from the session cache. + * + *

    Entities removed from cache are not saved in any way. Therefore, if you + * have modified any entities, you should be sure to {@link #commit()} changes + * before calling this method. + * + * @throws SQLException passed through. + */ + public void uncacheEntities() throws SQLException; + } diff --git a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java index 3321e4d837e5..11661ee64cc8 100644 --- a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java @@ -337,4 +337,10 @@ public void uncacheEntity(E entity) throws SQLExcep } } } + + @Override + public void uncacheEntities() throws SQLException { + getSession().clear(); + } + } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 0cf2aa50af67..8cb3c34db57f 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -72,6 +72,7 @@ import org.dspace.discovery.indexobject.IndexableItem; import org.dspace.discovery.indexobject.factory.IndexFactory; import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory; +import org.dspace.discovery.indexobject.factory.ItemIndexFactory; import org.dspace.eperson.Group; import org.dspace.eperson.factory.EPersonServiceFactory; import org.dspace.eperson.service.GroupService; @@ -341,6 +342,7 @@ public void updateIndex(Context context, boolean force, String type) { try { final List indexableObjectServices = indexObjectServiceFactory. getIndexFactories(); + int indexObject = 0; for (IndexFactory indexableObjectService : indexableObjectServices) { if (type == null || StringUtils.equals(indexableObjectService.getType(), type)) { final Iterator indexableObjects = indexableObjectService.findAll(context); @@ -348,6 +350,10 @@ public void updateIndex(Context context, boolean force, String type) { final IndexableObject indexableObject = indexableObjects.next(); indexContent(context, indexableObject, force); context.uncacheEntity(indexableObject.getIndexedObject()); + indexObject++; + if ((indexObject % 100) == 0 && indexableObjectService instanceof ItemIndexFactory) { + context.uncacheEntities(); + } } } } From 932e1ce9de8774b4f838c90cf3e21ccb93f232bd Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 19 Nov 2024 15:08:51 +0100 Subject: [PATCH 410/632] allow remote debugging (replace CATALINA_OPTS) (cherry picked from commit 2a4beeeb8bb03af739d5092d9a3210cce3129660) --- Dockerfile.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.test b/Dockerfile.test index 1c36b31b66bb..c9627e439fd7 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -68,7 +68,7 @@ RUN apt-get update \ EXPOSE 8080 8000 # Give java extra memory (2GB) ENV JAVA_OPTS=-Xmx2000m -# Set up debugging -ENV CATALINA_OPTS=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:8000 +# enable JVM debugging via JDWP +ENV JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000 # On startup, run DSpace Runnable JAR ENTRYPOINT ["java", "-jar", "webapps/server-boot.jar", "--dspace.dir=$DSPACE_INSTALL"] From 401e164f9ed5477646c25a387d8523e5d8b5f6ee Mon Sep 17 00:00:00 2001 From: Alphonse Bendt Date: Mon, 24 Jun 2024 16:05:54 +0300 Subject: [PATCH 411/632] Bugfix: BitstreamRestController etag/content-length calculation does not consider cover page Copied Alphonse Bendt's PR #9666 to DSpace 8 branch (squashed 5 commits). This PR fixes a bug where the etag/content-length calculation did not respect the potential existence of a coverpage. The controller now will use the post processed pdf if coverpages are enabled. --- .../app/rest/BitstreamRestController.java | 14 +- .../app/rest/utils/BitstreamResource.java | 121 ++++++++++------ .../app/rest/BitstreamRestControllerIT.java | 130 +++++++++++++++++- 3 files changed, 208 insertions(+), 57 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamRestController.java index db9d26a5f6ca..11b048e23ef1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamRestController.java @@ -135,11 +135,16 @@ public ResponseEntity retrieve(@PathVariable UUID uuid, HttpServletResponse resp long filesize = bit.getSizeBytes(); Boolean citationEnabledForBitstream = citationDocumentService.isCitationEnabledForBitstream(bit, context); + var bitstreamResource = + new org.dspace.app.rest.utils.BitstreamResource(name, uuid, + currentUser != null ? currentUser.getID() : null, + context.getSpecialGroupUuids(), citationEnabledForBitstream); + HttpHeadersInitializer httpHeadersInitializer = new HttpHeadersInitializer() .withBufferSize(BUFFER_SIZE) .withFileName(name) - .withChecksum(bit.getChecksum()) - .withLength(bit.getSizeBytes()) + .withChecksum(bitstreamResource.getChecksum()) + .withLength(bitstreamResource.contentLength()) .withMimetype(mimetype) .with(request) .with(response); @@ -157,11 +162,6 @@ public ResponseEntity retrieve(@PathVariable UUID uuid, HttpServletResponse resp httpHeadersInitializer.withDisposition(HttpHeadersInitializer.CONTENT_DISPOSITION_ATTACHMENT); } - org.dspace.app.rest.utils.BitstreamResource bitstreamResource = - new org.dspace.app.rest.utils.BitstreamResource(name, uuid, - currentUser != null ? currentUser.getID() : null, - context.getSpecialGroupUuids(), citationEnabledForBitstream); - //We have all the data we need, close the connection to the database so that it doesn't stay open during //download/streaming context.complete(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/BitstreamResource.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/BitstreamResource.java index 4e5545fabc7f..1ac6a320d9c2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/BitstreamResource.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/BitstreamResource.java @@ -15,7 +15,8 @@ import java.util.UUID; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.tuple.Pair; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.factory.ContentServiceFactory; @@ -27,6 +28,7 @@ import org.dspace.eperson.service.EPersonService; import org.dspace.utils.DSpace; import org.springframework.core.io.AbstractResource; +import org.springframework.util.DigestUtils; /** * This class acts as a {@link AbstractResource} used by Spring's framework to send the data in a proper and @@ -36,21 +38,24 @@ */ public class BitstreamResource extends AbstractResource { - private String name; - private UUID uuid; - private UUID currentUserUUID; - private boolean shouldGenerateCoverPage; - private byte[] file; - private Set currentSpecialGroups; - - private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); - private EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - private CitationDocumentService citationDocumentService = - new DSpace().getServiceManager() + private static final Logger LOG = LogManager.getLogger(BitstreamResource.class); + + private final String name; + private final UUID uuid; + private final UUID currentUserUUID; + private final boolean shouldGenerateCoverPage; + private final Set currentSpecialGroups; + + private final BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); + private final EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); + private final CitationDocumentService citationDocumentService = + new DSpace().getServiceManager() .getServicesByType(CitationDocumentService.class).get(0); + private BitstreamDocument document; + public BitstreamResource(String name, UUID uuid, UUID currentUserUUID, Set currentSpecialGroups, - boolean shouldGenerateCoverPage) { + boolean shouldGenerateCoverPage) { this.name = name; this.uuid = uuid; this.currentUserUUID = currentUserUUID; @@ -67,17 +72,15 @@ public BitstreamResource(String name, UUID uuid, UUID currentUserUUID, Set * @return a byte array containing the cover page */ private byte[] getCoverpageByteArray(Context context, Bitstream bitstream) - throws IOException, SQLException, AuthorizeException { - if (file == null) { - try { - Pair citedDocument = citationDocumentService.makeCitedDocument(context, bitstream); - this.file = citedDocument.getLeft(); - } catch (Exception e) { - // Return the original bitstream without the cover page - this.file = IOUtils.toByteArray(bitstreamService.retrieve(context, bitstream)); - } + throws IOException, SQLException, AuthorizeException { + try { + var citedDocument = citationDocumentService.makeCitedDocument(context, bitstream); + return citedDocument.getLeft(); + } catch (Exception e) { + LOG.warn("Could not generate cover page. Will fallback to original document", e); + // Return the original bitstream without the cover page + return IOUtils.toByteArray(bitstreamService.retrieve(context, bitstream)); } - return file; } @Override @@ -87,22 +90,9 @@ public String getDescription() { @Override public InputStream getInputStream() throws IOException { - try (Context context = initializeContext()) { - - Bitstream bitstream = bitstreamService.find(context, uuid); - InputStream out; + fetchDocument(); - if (shouldGenerateCoverPage) { - out = new ByteArrayInputStream(getCoverpageByteArray(context, bitstream)); - } else { - out = bitstreamService.retrieve(context, bitstream); - } - - this.file = null; - return out; - } catch (SQLException | AuthorizeException e) { - throw new IOException(e); - } + return document.inputStream(); } @Override @@ -111,17 +101,60 @@ public String getFilename() { } @Override - public long contentLength() throws IOException { + public long contentLength() { + fetchDocument(); + + return document.length(); + } + + public String getChecksum() { + fetchDocument(); + + return document.etag(); + } + + private void fetchDocument() { + if (document != null) { + return; + } + try (Context context = initializeContext()) { Bitstream bitstream = bitstreamService.find(context, uuid); if (shouldGenerateCoverPage) { - return getCoverpageByteArray(context, bitstream).length; + var coverPage = getCoverpageByteArray(context, bitstream); + + this.document = new BitstreamDocument(etag(bitstream), + coverPage.length, + new ByteArrayInputStream(coverPage)); } else { - return bitstream.getSizeBytes(); + this.document = new BitstreamDocument(bitstream.getChecksum(), + bitstream.getSizeBytes(), + bitstreamService.retrieve(context, bitstream)); } - } catch (SQLException | AuthorizeException e) { - throw new IOException(e); + } catch (SQLException | AuthorizeException | IOException e) { + throw new RuntimeException(e); } + + LOG.debug("fetched document {} {}", shouldGenerateCoverPage, document); + } + + private String etag(Bitstream bitstream) { + + /* Ideally we would calculate the md5 checksum based on the document with coverpage. + However it looks like the coverpage generation is not stable (e.g. if invoked twice it will return + different results). This means we cannot use it for etag calculation/comparison! + + Instead we will create the MD5 based off the original checksum plus fixed prefix. This ensures + that checksums will differ when coverpage is on/off. + However the checksum will _not_ change if the coverpage content changes. + */ + + var content = "coverpage:" + bitstream.getChecksum(); + + StringBuilder builder = new StringBuilder(37); + DigestUtils.appendMd5DigestAsHex(content.getBytes(), builder); + + return builder.toString(); } private Context initializeContext() throws SQLException { @@ -131,4 +164,6 @@ private Context initializeContext() throws SQLException { currentSpecialGroups.forEach(context::setSpecialGroup); return context; } + + private record BitstreamDocument(String etag, long length, InputStream inputStream) {} } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestControllerIT.java index 4dca18d65d6e..691927c6e457 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestControllerIT.java @@ -23,6 +23,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; @@ -49,9 +50,11 @@ import java.io.InputStream; import java.io.StringWriter; import java.io.Writer; +import java.nio.file.Files; import java.time.Period; import java.util.UUID; +import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; @@ -91,6 +94,7 @@ import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; /** * Integration test to test the /api/core/bitstreams/[id]/* endpoints @@ -925,7 +929,6 @@ public void retrieveCitationCoverpageOfBitstream() throws Exception { //2. A public item with a bitstream File originalPdf = new File(testProps.getProperty("test.bitstream")); - try (InputStream is = new FileInputStream(originalPdf)) { Item publicItem1 = ItemBuilder.createItem(context, col1) @@ -949,12 +952,11 @@ public void retrieveCitationCoverpageOfBitstream() throws Exception { //** THEN ** .andExpect(status().isOk()) - //The Content Length must match the full length + // exact content-length and etag values are verified in s separate test .andExpect(header().string("Content-Length", not(nullValue()))) + .andExpect(header().string("ETag", not(nullValue()))) //The server should indicate we support Range requests .andExpect(header().string("Accept-Ranges", "bytes")) - //The ETag has to be based on the checksum - .andExpect(header().string("ETag", "\"" + bitstream.getChecksum() + "\"")) //We expect the content type to match the bitstream mime type .andExpect(content().contentType("application/pdf;charset=UTF-8")) //THe bytes of the content must match the original content @@ -963,20 +965,22 @@ public void retrieveCitationCoverpageOfBitstream() throws Exception { // The citation cover page contains the item title. // We will now verify that the pdf text contains this title. String pdfText = extractPDFText(content); - System.out.println(pdfText); assertTrue(StringUtils.contains(pdfText,"Public item citation cover page test 1")); // The dspace-api/src/test/data/dspaceFolder/assetstore/ConstitutionofIreland.pdf file contains 64 pages, // manually counted + 1 citation cover page assertEquals(65,getNumberOfPdfPages(content)); + var etagHeader = getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content")) + .andReturn().getResponse().getHeader("ETag"); + //A If-None-Match HEAD request on the ETag must tell is the bitstream is not modified getClient().perform(head("/api/core/bitstreams/" + bitstream.getID() + "/content") - .header("If-None-Match", bitstream.getChecksum())) + .header("If-None-Match", etagHeader)) .andExpect(status().isNotModified()); //The download and head request should also be logged as a statistics record - checkNumberOfStatsRecords(bitstream, 2); + checkNumberOfStatsRecords(bitstream, 3); } private String extractPDFText(byte[] content) throws IOException { @@ -1384,4 +1388,116 @@ private void verifyBitstreamDownload(Bitstream file, String contentType, boolean header.contains("attachment")); } } + + @Test + public void contentLengthAndEtagUsesOriginalBitstream() throws Exception { + givenPdf(false, originalPdf -> { + var originalMd5 = md5Checksum(originalPdf); + long originalLength = Files.size(originalPdf.toPath()); + + assertThat(originalLength, greaterThan(0L)); + + getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(header().longValue("Content-Length", originalLength)) + .andExpect(header().string("ETag", "\"" + originalMd5 + "\"")); + }); + } + + private static String md5Checksum(File file) throws IOException { + final String md5; + try (InputStream is = new FileInputStream(file)) { + md5 = DigestUtils.md5Hex(is); + } + return md5; + } + + @Test + public void withCoverPageContentLengthAndEtagChanges() throws Exception { + givenPdf(true, originalPdf -> { + var originalMd5 = md5Checksum(originalPdf); + long originalLength = Files.size(originalPdf.toPath()); + + getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(header().string("Content-Length", not(Long.toString(originalLength)))) + .andExpect(header().string("ETag", not("\"" + originalMd5 + "\""))); + }); + } + + @Test + public void etagAndContentLengthIsStable() { + givenPdf(false, ignored -> { + var etag1 = getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content")) + .andReturn().getResponse().getHeader("Etag"); + + var etag2 = getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content")) + .andReturn().getResponse().getHeader("Etag"); + + assertThat(etag1, equalTo(etag2)); + }); + } + + @Test + public void withCoverPageEtagAndContentLengthIsStable() { + givenPdf(true, ignored -> { + var etag1 = getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content")) + .andReturn().getResponse().getHeader("Etag"); + + var etag2 = getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content")) + .andReturn().getResponse().getHeader("Etag"); + + assertThat(etag1, equalTo(etag2)); + }); + } + + @FunctionalInterface + interface ThrowingConsumer { + void accept(T t) throws Exception; + } + + private void givenPdf(boolean coverPageEnabled, ThrowingConsumer block) { + configurationService.setProperty("citation-page.enable_globally", coverPageEnabled); + + try { + citationDocumentService.afterPropertiesSet(); + context.turnOffAuthorisationSystem(); + + //** GIVEN ** + //1. A community-collection structure with one parent community and one collections. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + Collection col1 = + CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); + + //2. A public item with a bitstream + File originalPdf = new File(testProps.getProperty("test.bitstream")); + + try (InputStream is = new FileInputStream(originalPdf)) { + Item publicItem1 = ItemBuilder.createItem(context, col1) + .withTitle("Public item citation cover page test 1") + .withIssueDate("2017-10-17") + .withAuthor("Smith, Donald").withAuthor("Doe, John") + .build(); + + bitstream = BitstreamBuilder + .createBitstream(context, publicItem1, is) + .withName("Test bitstream") + .withDescription("This is a bitstream to test the citation cover page.") + .withMimeType("application/pdf") + .build(); + } + context.restoreAuthSystemState(); + + block.accept(originalPdf); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } From 6b4c7a773d4e16d4eebfa73539b85e6b7f44575a Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 22 Jan 2025 13:33:58 +0100 Subject: [PATCH 412/632] 124579: If no ORIGINAL bundle exists, end the process gracefully instead of throwing NPE (cherry picked from commit 046c1b5d0561b6bca558c71265c2bbc7cb331230) --- .../src/main/java/org/dspace/ctask/general/ClamScan.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java b/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java index d1fa70565dfd..c939b67af56d 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import org.apache.commons.collections4.ListUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; @@ -99,7 +100,12 @@ public int perform(DSpaceObject dso) throws IOException { } try { - Bundle bundle = itemService.getBundles(item, "ORIGINAL").get(0); + List bundles = itemService.getBundles(item, "ORIGINAL"); + if (ListUtils.emptyIfNull(bundles).isEmpty()) { + setResult("No ORIGINAL bundle found for item: " + getItemHandle(item)); + return Curator.CURATE_SKIP; + } + Bundle bundle = bundles.get(0); results = new ArrayList(); for (Bitstream bitstream : bundle.getBitstreams()) { InputStream inputstream = bitstreamService.retrieve(Curator.curationContext(), bitstream); From 094af861b305ff5d4dd3f0ffcdc0c3a62ea3fc91 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Thu, 23 Jan 2025 12:02:15 +0100 Subject: [PATCH 413/632] 124579: catch any exceptions during process and end task gracefully (cherry picked from commit 11a1c9ab06703b90c87e14843def82571fc6c51f) --- .../main/java/org/dspace/ctask/general/ClamScan.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java b/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java index c939b67af56d..6b84efe31963 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java @@ -15,12 +15,10 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.apache.commons.collections4.ListUtils; -import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.DSpaceObject; @@ -127,10 +125,11 @@ public int perform(DSpaceObject dso) throws IOException { } } - } catch (AuthorizeException authE) { - throw new IOException(authE.getMessage(), authE); - } catch (SQLException sqlE) { - throw new IOException(sqlE.getMessage(), sqlE); + } catch (Exception e) { + // Any exception which may occur during the performance of the task should be caught here + // And end the process gracefully + log.error("Error scanning item: " + getItemHandle(item), e); + status = Curator.CURATE_ERROR; } finally { closeSession(); } From fe59557e6cf663da973cdcf82edd5617dffa336a Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 22 Jan 2025 13:33:58 +0100 Subject: [PATCH 414/632] 124579: If no ORIGINAL bundle exists, end the process gracefully instead of throwing NPE (cherry picked from commit 046c1b5d0561b6bca558c71265c2bbc7cb331230) --- .../main/java/org/dspace/ctask/general/ClamScan.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java b/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java index 47fa6ee6452d..bfcbde189b9b 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import org.apache.commons.collections4.ListUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; @@ -99,8 +100,13 @@ public int perform(DSpaceObject dso) throws IOException { } try { - Bundle bundle = itemService.getBundles(item, "ORIGINAL").get(0); - results = new ArrayList<>(); + List bundles = itemService.getBundles(item, "ORIGINAL"); + if (ListUtils.emptyIfNull(bundles).isEmpty()) { + setResult("No ORIGINAL bundle found for item: " + getItemHandle(item)); + return Curator.CURATE_SKIP; + } + Bundle bundle = bundles.get(0); + results = new ArrayList(); for (Bitstream bitstream : bundle.getBitstreams()) { InputStream inputstream = bitstreamService.retrieve(Curator.curationContext(), bitstream); logDebugMessage("Scanning " + bitstream.getName() + " . . . "); From ca6c23d2e6bf4cdd8b5199332acb646e9ae0df7a Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Thu, 23 Jan 2025 12:02:15 +0100 Subject: [PATCH 415/632] 124579: catch any exceptions during process and end task gracefully (cherry picked from commit 11a1c9ab06703b90c87e14843def82571fc6c51f) --- .../main/java/org/dspace/ctask/general/ClamScan.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java b/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java index bfcbde189b9b..5a717fe1e479 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/ClamScan.java @@ -15,14 +15,12 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.apache.commons.collections4.ListUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.DSpaceObject; @@ -127,10 +125,11 @@ public int perform(DSpaceObject dso) throws IOException { } } - } catch (AuthorizeException authE) { - throw new IOException(authE.getMessage(), authE); - } catch (SQLException sqlE) { - throw new IOException(sqlE.getMessage(), sqlE); + } catch (Exception e) { + // Any exception which may occur during the performance of the task should be caught here + // And end the process gracefully + log.error("Error scanning item: " + getItemHandle(item), e); + status = Curator.CURATE_ERROR; } finally { closeSession(); } From d198864ee04675ac54079ee065b162e4d21c98ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 22:50:06 +0000 Subject: [PATCH 416/632] Bump the apache-commons group with 2 updates Bumps the apache-commons group with 2 updates: [commons-codec:commons-codec](https://github.com/apache/commons-codec) and org.apache.commons:commons-pool2. Updates `commons-codec:commons-codec` from 1.17.2 to 1.18.0 - [Changelog](https://github.com/apache/commons-codec/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-codec/compare/rel/commons-codec-1.17.2...rel/commons-codec-1.18.0) Updates `org.apache.commons:commons-pool2` from 2.12.0 to 2.12.1 --- updated-dependencies: - dependency-name: commons-codec:commons-codec dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-pool2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ba9af988ab41..c5011cfe4714 100644 --- a/pom.xml +++ b/pom.xml @@ -1472,7 +1472,7 @@ commons-codec commons-codec - 1.17.2 + 1.18.0 org.apache.commons @@ -1526,7 +1526,7 @@ org.apache.commons commons-pool2 - 2.12.0 + 2.12.1 org.apache.commons From 75efc026742a878aa0d29873eb36c20af47eb890 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 22:51:28 +0000 Subject: [PATCH 417/632] Bump org.apache.httpcomponents.client5:httpclient5 from 5.4.1 to 5.4.2 Bumps [org.apache.httpcomponents.client5:httpclient5](https://github.com/apache/httpcomponents-client) from 5.4.1 to 5.4.2. - [Changelog](https://github.com/apache/httpcomponents-client/blob/rel/v5.4.2/RELEASE_NOTES.txt) - [Commits](https://github.com/apache/httpcomponents-client/compare/rel/v5.4.1...rel/v5.4.2) --- updated-dependencies: - dependency-name: org.apache.httpcomponents.client5:httpclient5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index c8bb82f0ea2e..8a2b50ad76fd 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -590,7 +590,7 @@ org.apache.httpcomponents.client5 httpclient5 - 5.4.1 + 5.4.2 test From 18edaf9cd760bf028d1fb89a8a4e52e6b4c9c437 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 22:51:35 +0000 Subject: [PATCH 418/632] Bump com.google.code.gson:gson from 2.11.0 to 2.12.1 Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.11.0 to 2.12.1. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.11.0...gson-parent-2.12.1) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ba9af988ab41..3fca3cf7969f 100644 --- a/pom.xml +++ b/pom.xml @@ -1352,7 +1352,7 @@ com.google.code.gson gson - 2.11.0 + 2.12.1 Apache Software License, Version 2.0|Similar to Apache License but with the acknowledgment clause removed - BSD License|The BSD License|BSD licence|BSD license|BSD|BSD-style license|New BSD License|New BSD license|Revised BSD License|BSD 2-Clause license|3-Clause BSD License|BSD 2-Clause|BSD 3-clause New License|BSD Licence 3|BSD-2-Clause|BSD-3-Clause|Modified BSD|The New BSD License|The BSD 3-Clause License (BSD3)|BSD License 3|BSD License 2.0 + BSD License|The BSD License|BSD licence|BSD license|BSD|BSD-style license|New BSD License|New BSD license|Revised BSD License|BSD 2-Clause license|3-Clause BSD License|BSD 2-Clause|BSD 3-clause New License|BSD Licence 3|BSD-2-Clause|BSD-3-Clause|Modified BSD|The New BSD License|The BSD 3-Clause License (BSD3)|BSD License 3|BSD License 2.0|The (New) BSD License BSD License|DSpace BSD License|DSpace Sourcecode License @@ -735,7 +735,7 @@ GNU Lesser General Public License (LGPL)|The GNU Lesser General Public License, Version 2.1|GNU Lesser General Public License (LGPL), Version 2.1|GNU LESSER GENERAL PUBLIC LICENSE, Version 2.1|GNU Lesser General Public License, version 2.1|GNU LESSER GENERAL PUBLIC LICENSE|GNU Lesser General Public License|GNU Lesser Public License|GNU Lesser General Public License, Version 2.1|Lesser General Public License (LGPL) v 2.1|LGPL 2.1|LGPL 2.1 license|LGPL 3.0 license|LGPL, v2.1 or later|LGPL|LGPL, version 2.1|lgpl|Lesser General Public License, version 3 or greater GNU Lesser General Public License (LGPL)|GNU Library General Public License v2.1 or later - MIT License|The MIT License|MIT LICENSE|MIT|MIT license|MIT License (MIT) + MIT License|The MIT License|MIT LICENSE|MIT|MIT license|MIT License (MIT)|The MIT License (MIT) MIT License|Bouncy Castle Licence From c1ca307b5319a089876778c4ca0265bba1280f56 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 7 Feb 2025 10:37:51 -0600 Subject: [PATCH 438/632] UPdate LICENSES_THIRD_PARTY for 8.1 --- LICENSES_THIRD_PARTY | 551 ++++++++++++++++++++++--------------------- pom.xml | 2 +- 2 files changed, 281 insertions(+), 272 deletions(-) diff --git a/LICENSES_THIRD_PARTY b/LICENSES_THIRD_PARTY index d7e928147c89..1d39b851ad61 100644 --- a/LICENSES_THIRD_PARTY +++ b/LICENSES_THIRD_PARTY @@ -21,56 +21,52 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines Apache Software License, Version 2.0: * Ant-Contrib Tasks (ant-contrib:ant-contrib:1.0b3 - http://ant-contrib.sourceforge.net) - * AWS SDK for Java - Core (com.amazonaws:aws-java-sdk-core:1.12.261 - https://aws.amazon.com/sdkforjava) - * AWS Java SDK for AWS KMS (com.amazonaws:aws-java-sdk-kms:1.12.261 - https://aws.amazon.com/sdkforjava) - * AWS Java SDK for Amazon S3 (com.amazonaws:aws-java-sdk-s3:1.12.261 - https://aws.amazon.com/sdkforjava) - * JMES Path Query library (com.amazonaws:jmespath-java:1.12.261 - https://aws.amazon.com/sdkforjava) + * AWS SDK for Java - Core (com.amazonaws:aws-java-sdk-core:1.12.780 - https://aws.amazon.com/sdkforjava) + * AWS Java SDK for AWS KMS (com.amazonaws:aws-java-sdk-kms:1.12.780 - https://aws.amazon.com/sdkforjava) + * AWS Java SDK for Amazon S3 (com.amazonaws:aws-java-sdk-s3:1.12.780 - https://aws.amazon.com/sdkforjava) + * JMES Path Query library (com.amazonaws:jmespath-java:1.12.780 - https://aws.amazon.com/sdkforjava) * Titanium JSON-LD 1.1 (JRE11) (com.apicatalog:titanium-json-ld:1.3.2 - https://github.com/filip26/titanium-json-ld) * HPPC Collections (com.carrotsearch:hppc:0.8.1 - http://labs.carrotsearch.com/hppc.html/hppc) * com.drewnoakes:metadata-extractor (com.drewnoakes:metadata-extractor:2.19.0 - https://drewnoakes.com/code/exif/) * parso (com.epam:parso:2.0.14 - https://github.com/epam/parso) - * ClassMate (com.fasterxml:classmate:1.6.0 - https://github.com/FasterXML/java-classmate) - * Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.16.0 - https://github.com/FasterXML/jackson) - * Jackson-core (com.fasterxml.jackson.core:jackson-core:2.16.0 - https://github.com/FasterXML/jackson-core) - * jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.16.0 - https://github.com/FasterXML/jackson) - * Jackson dataformat: CBOR (com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.12.6 - http://github.com/FasterXML/jackson-dataformats-binary) + * Internet Time Utility (com.ethlo.time:itu:1.7.0 - https://github.com/ethlo/itu) + * ClassMate (com.fasterxml:classmate:1.7.0 - https://github.com/FasterXML/java-classmate) + * Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.18.2 - https://github.com/FasterXML/jackson) + * Jackson-core (com.fasterxml.jackson.core:jackson-core:2.18.2 - https://github.com/FasterXML/jackson-core) + * jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.18.2 - https://github.com/FasterXML/jackson) + * Jackson dataformat: CBOR (com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.17.2 - https://github.com/FasterXML/jackson-dataformats-binary) * Jackson dataformat: Smile (com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.15.2 - https://github.com/FasterXML/jackson-dataformats-binary) * Jackson-dataformat-TOML (com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2 - https://github.com/FasterXML/jackson-dataformats-text) * Jackson-dataformat-YAML (com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.2 - https://github.com/FasterXML/jackson-dataformats-text) - * Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.4 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8) - * Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.0 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310) + * Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8) + * Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310) * Jackson Jakarta-RS: base (com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-base:2.16.2 - https://github.com/FasterXML/jackson-jakarta-rs-providers/jackson-jakarta-rs-base) * Jackson Jakarta-RS: JSON (com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-json-provider:2.16.2 - https://github.com/FasterXML/jackson-jakarta-rs-providers/jackson-jakarta-rs-json-provider) * Jackson module: Jakarta XML Bind Annotations (jakarta.xml.bind) (com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.16.2 - https://github.com/FasterXML/jackson-modules-base) - * Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.4 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names) - * Java UUID Generator (com.fasterxml.uuid:java-uuid-generator:4.0.1 - https://github.com/cowtowncoder/java-uuid-generator) + * Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.18.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names) + * Java UUID Generator (com.fasterxml.uuid:java-uuid-generator:4.1.0 - https://github.com/cowtowncoder/java-uuid-generator) * Woodstox (com.fasterxml.woodstox:woodstox-core:6.5.1 - https://github.com/FasterXML/woodstox) * zjsonpatch (com.flipkart.zjsonpatch:zjsonpatch:0.4.16 - https://github.com/flipkart-incubator/zjsonpatch/) * Caffeine cache (com.github.ben-manes.caffeine:caffeine:2.9.3 - https://github.com/ben-manes/caffeine) - * Caffeine cache (com.github.ben-manes.caffeine:caffeine:3.1.6 - https://github.com/ben-manes/caffeine) + * Caffeine cache (com.github.ben-manes.caffeine:caffeine:3.1.8 - https://github.com/ben-manes/caffeine) + * JSON.simple (com.github.cliftonlabs:json-simple:3.0.2 - https://cliftonlabs.github.io/json-simple/) * btf (com.github.java-json-tools:btf:1.3 - https://github.com/java-json-tools/btf) * jackson-coreutils (com.github.java-json-tools:jackson-coreutils:2.0 - https://github.com/java-json-tools/jackson-coreutils) * jackson-coreutils-equivalence (com.github.java-json-tools:jackson-coreutils-equivalence:1.0 - https://github.com/java-json-tools/jackson-coreutils) + * json-patch (com.github.java-json-tools:json-patch:1.13 - https://github.com/java-json-tools/json-patch) * json-schema-core (com.github.java-json-tools:json-schema-core:1.2.14 - https://github.com/java-json-tools/json-schema-core) * json-schema-validator (com.github.java-json-tools:json-schema-validator:2.2.14 - https://github.com/java-json-tools/json-schema-validator) * msg-simple (com.github.java-json-tools:msg-simple:1.2 - https://github.com/java-json-tools/msg-simple) * uri-template (com.github.java-json-tools:uri-template:0.10 - https://github.com/java-json-tools/uri-template) * JCIP Annotations under Apache License (com.github.stephenc.jcip:jcip-annotations:1.0-1 - http://stephenc.github.com/jcip-annotations) - * Google APIs Client Library for Java (com.google.api-client:google-api-client:1.23.0 - https://github.com/google/google-api-java-client/google-api-client) - * Google Analytics API v3-rev145-1.23.0 (com.google.apis:google-api-services-analytics:v3-rev145-1.23.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-analytics) * FindBugs-jsr305 (com.google.code.findbugs:jsr305:3.0.2 - http://findbugs.sourceforge.net/) - * Gson (com.google.code.gson:gson:2.10.1 - https://github.com/google/gson/gson) - * error-prone annotations (com.google.errorprone:error_prone_annotations:2.10.0 - https://errorprone.info/error_prone_annotations) + * Gson (com.google.code.gson:gson:2.11.0 - https://github.com/google/gson) + * error-prone annotations (com.google.errorprone:error_prone_annotations:2.36.0 - https://errorprone.info/error_prone_annotations) * Guava InternalFutureFailureAccess and InternalFutures (com.google.guava:failureaccess:1.0.1 - https://github.com/google/guava/failureaccess) - * Guava: Google Core Libraries for Java (com.google.guava:guava:32.0.0-jre - https://github.com/google/guava) - * Guava: Google Core Libraries for Java (JDK5 Backport) (com.google.guava:guava-jdk5:17.0 - http://code.google.com/p/guava-libraries/guava-jdk5) + * Guava: Google Core Libraries for Java (com.google.guava:guava:32.1.3-jre - https://github.com/google/guava) * Guava ListenableFuture only (com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava - https://github.com/google/guava/listenablefuture) - * Google HTTP Client Library for Java (com.google.http-client:google-http-client:1.23.0 - https://github.com/google/google-http-java-client/google-http-client) - * GSON extensions to the Google HTTP Client Library for Java. (com.google.http-client:google-http-client-gson:1.41.7 - https://github.com/googleapis/google-http-java-client/google-http-client-gson) - * Jackson 2 extensions to the Google HTTP Client Library for Java. (com.google.http-client:google-http-client-jackson2:1.23.0 - https://github.com/google/google-http-java-client/google-http-client-jackson2) * J2ObjC Annotations (com.google.j2objc:j2objc-annotations:1.3 - https://github.com/google/j2objc/) * J2ObjC Annotations (com.google.j2objc:j2objc-annotations:2.8 - https://github.com/google/j2objc/) - * Google OAuth Client Library for Java (com.google.oauth-client:google-oauth-client:1.33.3 - https://github.com/googleapis/google-oauth-java-client/google-oauth-client) * ConcurrentLinkedHashMap (com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2 - http://code.google.com/p/concurrentlinkedhashmap) * libphonenumber (com.googlecode.libphonenumber:libphonenumber:8.11.1 - https://github.com/google/libphonenumber/) * Jackcess (com.healthmarketscience.jackcess:jackcess:4.0.5 - https://jackcess.sourceforge.io) @@ -80,8 +76,10 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Disruptor Framework (com.lmax:disruptor:3.4.2 - http://lmax-exchange.github.com/disruptor) * MaxMind DB Reader (com.maxmind.db:maxmind-db:2.1.0 - http://dev.maxmind.com/) * MaxMind GeoIP2 API (com.maxmind.geoip2:geoip2:2.17.0 - https://dev.maxmind.com/geoip?lang=en) - * Nimbus JOSE+JWT (com.nimbusds:nimbus-jose-jwt:9.37.3 - https://bitbucket.org/connect2id/nimbus-jose-jwt) - * opencsv (com.opencsv:opencsv:5.9 - http://opencsv.sf.net) + * JsonSchemaValidator (com.networknt:json-schema-validator:1.0.76 - https://github.com/networknt/json-schema-validator) + * Nimbus JOSE+JWT (com.nimbusds:nimbus-jose-jwt:9.28 - https://bitbucket.org/connect2id/nimbus-jose-jwt) + * Nimbus JOSE+JWT (com.nimbusds:nimbus-jose-jwt:9.48 - https://bitbucket.org/connect2id/nimbus-jose-jwt) + * opencsv (com.opencsv:opencsv:5.10 - http://opencsv.sf.net) * java-libpst (com.pff:java-libpst:0.9.3 - https://github.com/rjohnsondev/java-libpst) * rome (com.rometools:rome:1.19.0 - http://rometools.com/rome) * rome-modules (com.rometools:rome-modules:1.19.0 - http://rometools.com/rome-modules) @@ -98,15 +96,15 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * scala-logging (com.typesafe.scala-logging:scala-logging_2.13:3.9.2 - https://github.com/lightbend/scala-logging) * JSON library from Android SDK (com.vaadin.external.google:android-json:0.0.20131108.vaadin1 - http://developer.android.com/sdk) * SparseBitSet (com.zaxxer:SparseBitSet:1.3 - https://github.com/brettwooldridge/SparseBitSet) - * Apache Commons BeanUtils (commons-beanutils:commons-beanutils:1.9.4 - https://commons.apache.org/proper/commons-beanutils/) - * Apache Commons CLI (commons-cli:commons-cli:1.6.0 - https://commons.apache.org/proper/commons-cli/) - * Apache Commons Codec (commons-codec:commons-codec:1.16.0 - https://commons.apache.org/proper/commons-codec/) + * Apache Commons BeanUtils (commons-beanutils:commons-beanutils:1.10.0 - https://commons.apache.org/proper/commons-beanutils) + * Apache Commons CLI (commons-cli:commons-cli:1.9.0 - https://commons.apache.org/proper/commons-cli/) + * Apache Commons Codec (commons-codec:commons-codec:1.17.2 - https://commons.apache.org/proper/commons-codec/) * Apache Commons Collections (commons-collections:commons-collections:3.2.2 - http://commons.apache.org/collections/) * Commons Digester (commons-digester:commons-digester:2.1 - http://commons.apache.org/digester/) - * Apache Commons IO (commons-io:commons-io:2.15.1 - https://commons.apache.org/proper/commons-io/) + * Apache Commons IO (commons-io:commons-io:2.18.0 - https://commons.apache.org/proper/commons-io/) * Commons Lang (commons-lang:commons-lang:2.6 - http://commons.apache.org/lang/) - * Apache Commons Logging (commons-logging:commons-logging:1.3.0 - https://commons.apache.org/proper/commons-logging/) - * Apache Commons Validator (commons-validator:commons-validator:1.7 - http://commons.apache.org/proper/commons-validator/) + * Apache Commons Logging (commons-logging:commons-logging:1.3.4 - https://commons.apache.org/proper/commons-logging/) + * Apache Commons Validator (commons-validator:commons-validator:1.9.0 - http://commons.apache.org/proper/commons-validator/) * GeoJson POJOs for Jackson (de.grundid.opendatalab:geojson-jackson:1.14 - https://github.com/opendatalab-de/geojson-jackson) * broker-client (eu.openaire:broker-client:1.1.2 - http://api.openaire.eu/broker/broker-client) * OpenAIRE Funders Model (eu.openaire:funders-model:2.0.0 - https://api.openaire.eu) @@ -116,84 +114,91 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Metrics Integration with JMX (io.dropwizard.metrics:metrics-jmx:4.1.5 - https://metrics.dropwizard.io/metrics-jmx) * JVM Integration for Metrics (io.dropwizard.metrics:metrics-jvm:4.1.5 - https://metrics.dropwizard.io/metrics-jvm) * SWORD v2 Common Server Library (forked) (io.gdcc:sword2-server:2.0.0 - https://github.com/gdcc/sword2-server) - * micrometer-commons (io.micrometer:micrometer-commons:1.12.6 - https://github.com/micrometer-metrics/micrometer) - * micrometer-core (io.micrometer:micrometer-core:1.12.6 - https://github.com/micrometer-metrics/micrometer) - * micrometer-jakarta9 (io.micrometer:micrometer-jakarta9:1.12.6 - https://github.com/micrometer-metrics/micrometer) - * micrometer-observation (io.micrometer:micrometer-observation:1.12.6 - https://github.com/micrometer-metrics/micrometer) - * Netty/Buffer (io.netty:netty-buffer:4.1.106.Final - https://netty.io/netty-buffer/) + * micrometer-commons (io.micrometer:micrometer-commons:1.14.2 - https://github.com/micrometer-metrics/micrometer) + * micrometer-commons (io.micrometer:micrometer-commons:1.14.3 - https://github.com/micrometer-metrics/micrometer) + * micrometer-core (io.micrometer:micrometer-core:1.14.3 - https://github.com/micrometer-metrics/micrometer) + * micrometer-jakarta9 (io.micrometer:micrometer-jakarta9:1.14.3 - https://github.com/micrometer-metrics/micrometer) + * micrometer-observation (io.micrometer:micrometer-observation:1.14.2 - https://github.com/micrometer-metrics/micrometer) + * micrometer-observation (io.micrometer:micrometer-observation:1.14.3 - https://github.com/micrometer-metrics/micrometer) * Netty/Buffer (io.netty:netty-buffer:4.1.99.Final - https://netty.io/netty-buffer/) - * Netty/Codec (io.netty:netty-codec:4.1.106.Final - https://netty.io/netty-codec/) * Netty/Codec (io.netty:netty-codec:4.1.99.Final - https://netty.io/netty-codec/) - * Netty/Codec/HTTP (io.netty:netty-codec-http:4.1.53.Final - https://netty.io/netty-codec-http/) - * Netty/Codec/Socks (io.netty:netty-codec-socks:4.1.53.Final - https://netty.io/netty-codec-socks/) - * Netty/Common (io.netty:netty-common:4.1.106.Final - https://netty.io/netty-common/) + * Netty/Codec/HTTP (io.netty:netty-codec-http:4.1.86.Final - https://netty.io/netty-codec-http/) + * Netty/Codec/HTTP2 (io.netty:netty-codec-http2:4.1.86.Final - https://netty.io/netty-codec-http2/) + * Netty/Codec/Socks (io.netty:netty-codec-socks:4.1.86.Final - https://netty.io/netty-codec-socks/) * Netty/Common (io.netty:netty-common:4.1.99.Final - https://netty.io/netty-common/) - * Netty/Handler (io.netty:netty-handler:4.1.106.Final - https://netty.io/netty-handler/) * Netty/Handler (io.netty:netty-handler:4.1.99.Final - https://netty.io/netty-handler/) - * Netty/Handler/Proxy (io.netty:netty-handler-proxy:4.1.53.Final - https://netty.io/netty-handler-proxy/) + * Netty/Handler/Proxy (io.netty:netty-handler-proxy:4.1.86.Final - https://netty.io/netty-handler-proxy/) * Netty/Resolver (io.netty:netty-resolver:4.1.99.Final - https://netty.io/netty-resolver/) - * Netty/Transport (io.netty:netty-transport:4.1.106.Final - https://netty.io/netty-transport/) + * Netty/TomcatNative [BoringSSL - Static] (io.netty:netty-tcnative-boringssl-static:2.0.56.Final - https://github.com/netty/netty-tcnative/netty-tcnative-boringssl-static/) + * Netty/TomcatNative [OpenSSL - Classes] (io.netty:netty-tcnative-classes:2.0.56.Final - https://github.com/netty/netty-tcnative/netty-tcnative-classes/) * Netty/Transport (io.netty:netty-transport:4.1.99.Final - https://netty.io/netty-transport/) + * Netty/Transport/Classes/Epoll (io.netty:netty-transport-classes-epoll:4.1.99.Final - https://netty.io/netty-transport-classes-epoll/) * Netty/Transport/Native/Epoll (io.netty:netty-transport-native-epoll:4.1.99.Final - https://netty.io/netty-transport-native-epoll/) - * Netty/Transport/Native/Unix/Common (io.netty:netty-transport-native-unix-common:4.1.106.Final - https://netty.io/netty-transport-native-unix-common/) * Netty/Transport/Native/Unix/Common (io.netty:netty-transport-native-unix-common:4.1.99.Final - https://netty.io/netty-transport-native-unix-common/) * OpenTracing API (io.opentracing:opentracing-api:0.33.0 - https://github.com/opentracing/opentracing-java/opentracing-api) * OpenTracing-noop (io.opentracing:opentracing-noop:0.33.0 - https://github.com/opentracing/opentracing-java/opentracing-noop) * OpenTracing-util (io.opentracing:opentracing-util:0.33.0 - https://github.com/opentracing/opentracing-java/opentracing-util) + * Prometheus Java Simpleclient (io.prometheus:simpleclient:0.16.0 - http://github.com/prometheus/client_java/simpleclient) + * Prometheus Java Simpleclient Common (io.prometheus:simpleclient_common:0.16.0 - http://github.com/prometheus/client_java/simpleclient_common) + * Prometheus Java Simpleclient Httpserver (io.prometheus:simpleclient_httpserver:0.16.0 - http://github.com/prometheus/client_java/simpleclient_httpserver) + * Prometheus Java Span Context Supplier - Common (io.prometheus:simpleclient_tracer_common:0.16.0 - http://github.com/prometheus/client_java/simpleclient_tracer/simpleclient_tracer_common) + * Prometheus Java Span Context Supplier - OpenTelemetry (io.prometheus:simpleclient_tracer_otel:0.16.0 - http://github.com/prometheus/client_java/simpleclient_tracer/simpleclient_tracer_otel) + * Prometheus Java Span Context Supplier - OpenTelemetry Agent (io.prometheus:simpleclient_tracer_otel_agent:0.16.0 - http://github.com/prometheus/client_java/simpleclient_tracer/simpleclient_tracer_otel_agent) * Google S2 geometry library (io.sgr:s2-geometry-library-java:1.0.0 - https://github.com/sgr-io/s2-geometry-library-java) * Jandex: Core (io.smallrye:jandex:3.1.2 - https://smallrye.io) - * swagger-annotations (io.swagger:swagger-annotations:1.6.2 - https://github.com/swagger-api/swagger-core/modules/swagger-annotations) - * swagger-compat-spec-parser (io.swagger:swagger-compat-spec-parser:1.0.52 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-compat-spec-parser) - * swagger-core (io.swagger:swagger-core:1.6.2 - https://github.com/swagger-api/swagger-core/modules/swagger-core) - * swagger-models (io.swagger:swagger-models:1.6.2 - https://github.com/swagger-api/swagger-core/modules/swagger-models) - * swagger-parser (io.swagger:swagger-parser:1.0.52 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser) - * swagger-annotations (io.swagger.core.v3:swagger-annotations:2.1.5 - https://github.com/swagger-api/swagger-core/modules/swagger-annotations) + * swagger-annotations (io.swagger:swagger-annotations:1.6.9 - https://github.com/swagger-api/swagger-core/modules/swagger-annotations) + * swagger-compat-spec-parser (io.swagger:swagger-compat-spec-parser:1.0.64 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-compat-spec-parser) + * swagger-core (io.swagger:swagger-core:1.6.9 - https://github.com/swagger-api/swagger-core/modules/swagger-core) + * swagger-models (io.swagger:swagger-models:1.6.9 - https://github.com/swagger-api/swagger-core/modules/swagger-models) + * swagger-parser (io.swagger:swagger-parser:1.0.64 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser) + * swagger-annotations (io.swagger.core.v3:swagger-annotations:2.2.8 - https://github.com/swagger-api/swagger-core/modules/swagger-annotations) * swagger-annotations-jakarta (io.swagger.core.v3:swagger-annotations-jakarta:2.2.21 - https://github.com/swagger-api/swagger-core/modules/swagger-annotations-jakarta) - * swagger-core (io.swagger.core.v3:swagger-core:2.1.5 - https://github.com/swagger-api/swagger-core/modules/swagger-core) + * swagger-core (io.swagger.core.v3:swagger-core:2.2.8 - https://github.com/swagger-api/swagger-core/modules/swagger-core) * swagger-core-jakarta (io.swagger.core.v3:swagger-core-jakarta:2.2.21 - https://github.com/swagger-api/swagger-core/modules/swagger-core-jakarta) * swagger-integration-jakarta (io.swagger.core.v3:swagger-integration-jakarta:2.2.21 - https://github.com/swagger-api/swagger-core/modules/swagger-integration-jakarta) * swagger-jaxrs2-jakarta (io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.21 - https://github.com/swagger-api/swagger-core/modules/swagger-jaxrs2-jakarta) - * swagger-models (io.swagger.core.v3:swagger-models:2.1.5 - https://github.com/swagger-api/swagger-core/modules/swagger-models) + * swagger-models (io.swagger.core.v3:swagger-models:2.2.8 - https://github.com/swagger-api/swagger-core/modules/swagger-models) * swagger-models-jakarta (io.swagger.core.v3:swagger-models-jakarta:2.2.21 - https://github.com/swagger-api/swagger-core/modules/swagger-models-jakarta) - * swagger-parser (io.swagger.parser.v3:swagger-parser:2.0.23 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser) - * swagger-parser (io.swagger.parser.v3:swagger-parser-core:2.0.23 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser-core) - * swagger-parser-v2-converter (io.swagger.parser.v3:swagger-parser-v2-converter:2.0.23 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser-v2-converter) - * swagger-parser-v3 (io.swagger.parser.v3:swagger-parser-v3:2.0.23 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser-v3) + * swagger-parser (io.swagger.parser.v3:swagger-parser:2.1.10 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser) + * swagger-parser (io.swagger.parser.v3:swagger-parser-core:2.1.10 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser-core) + * swagger-parser-v2-converter (io.swagger.parser.v3:swagger-parser-v2-converter:2.1.10 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser-v2-converter) + * swagger-parser-v3 (io.swagger.parser.v3:swagger-parser-v3:2.1.10 - http://nexus.sonatype.org/oss-repository-hosting.html/swagger-parser-project/modules/swagger-parser-v3) * Jakarta Dependency Injection (jakarta.inject:jakarta.inject-api:2.0.1 - https://github.com/eclipse-ee4j/injection-api) * Jakarta Bean Validation API (jakarta.validation:jakarta.validation-api:3.0.2 - https://beanvalidation.org) * JSR107 API and SPI (javax.cache:cache-api:1.1.1 - https://github.com/jsr107/jsr107spec) - * javax.inject (javax.inject:javax.inject:1 - http://code.google.com/p/atinject/) - * Bean Validation API (javax.validation:validation-api:1.1.0.Final - http://beanvalidation.org) * jdbm (jdbm:jdbm:1.0 - no url defined) - * Joda-Time (joda-time:joda-time:2.12.5 - https://www.joda.org/joda-time/) - * Byte Buddy (without dependencies) (net.bytebuddy:byte-buddy:1.11.13 - https://bytebuddy.net/byte-buddy) + * Joda-Time (joda-time:joda-time:2.13.0 - https://www.joda.org/joda-time/) + * Byte Buddy (without dependencies) (net.bytebuddy:byte-buddy:1.16.1 - https://bytebuddy.net/byte-buddy) * Byte Buddy agent (net.bytebuddy:byte-buddy-agent:1.11.13 - https://bytebuddy.net/byte-buddy-agent) * eigenbase-properties (net.hydromatic:eigenbase-properties:1.1.5 - http://github.com/julianhyde/eigenbase-properties) - * json-unit-core (net.javacrumbs.json-unit:json-unit-core:2.19.0 - https://github.com/lukas-krecan/JsonUnit/json-unit-core) + * json-unit-core (net.javacrumbs.json-unit:json-unit-core:2.36.0 - https://github.com/lukas-krecan/JsonUnit/json-unit-core) * "Java Concurrency in Practice" book annotations (net.jcip:jcip-annotations:1.0 - http://jcip.net/) * ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.5.0 - https://urielch.github.io/) + * ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.5.1 - https://urielch.github.io/) * JSON Small and Fast Parser (net.minidev:json-smart:2.5.0 - https://urielch.github.io/) + * JSON Small and Fast Parser (net.minidev:json-smart:2.5.1 - https://urielch.github.io/) * Abdera Core (org.apache.abdera:abdera-core:1.1.3 - http://abdera.apache.org/abdera-core) * I18N Libraries (org.apache.abdera:abdera-i18n:1.1.3 - http://abdera.apache.org) * Abdera Parser (org.apache.abdera:abdera-parser:1.1.3 - http://abdera.apache.org/abdera-parser) - * Apache Ant Core (org.apache.ant:ant:1.10.14 - https://ant.apache.org/) - * Apache Ant Launcher (org.apache.ant:ant-launcher:1.10.14 - https://ant.apache.org/) - * Apache Commons BCEL (org.apache.bcel:bcel:6.7.0 - https://commons.apache.org/proper/commons-bcel) + * Apache Ant Core (org.apache.ant:ant:1.10.15 - https://ant.apache.org/) + * Apache Ant Launcher (org.apache.ant:ant-launcher:1.10.15 - https://ant.apache.org/) + * Apache Commons BCEL (org.apache.bcel:bcel:6.10.0 - https://commons.apache.org/proper/commons-bcel) * Calcite Core (org.apache.calcite:calcite-core:1.35.0 - https://calcite.apache.org) * Calcite Linq4j (org.apache.calcite:calcite-linq4j:1.35.0 - https://calcite.apache.org) * Apache Calcite Avatica (org.apache.calcite.avatica:avatica-core:1.23.0 - https://calcite.apache.org/avatica) * Apache Calcite Avatica Metrics (org.apache.calcite.avatica:avatica-metrics:1.23.0 - https://calcite.apache.org/avatica) * Apache Commons Collections (org.apache.commons:commons-collections4:4.4 - https://commons.apache.org/proper/commons-collections/) - * Apache Commons Compress (org.apache.commons:commons-compress:1.26.0 - https://commons.apache.org/proper/commons-compress/) - * Apache Commons Configuration (org.apache.commons:commons-configuration2:2.10.1 - https://commons.apache.org/proper/commons-configuration/) - * Apache Commons CSV (org.apache.commons:commons-csv:1.10.0 - https://commons.apache.org/proper/commons-csv/) - * Apache Commons DBCP (org.apache.commons:commons-dbcp2:2.11.0 - https://commons.apache.org/dbcp/) + * Apache Commons Compress (org.apache.commons:commons-compress:1.27.1 - https://commons.apache.org/proper/commons-compress/) + * Apache Commons Configuration (org.apache.commons:commons-configuration2:2.11.0 - https://commons.apache.org/proper/commons-configuration/) + * Apache Commons CSV (org.apache.commons:commons-csv:1.13.0 - https://commons.apache.org/proper/commons-csv/) + * Apache Commons DBCP (org.apache.commons:commons-dbcp2:2.13.0 - https://commons.apache.org/proper/commons-dbcp/) + * Apache Commons Digester (org.apache.commons:commons-digester3:3.2 - http://commons.apache.org/digester/) * Apache Commons Exec (org.apache.commons:commons-exec:1.3 - http://commons.apache.org/proper/commons-exec/) * Apache Commons Exec (org.apache.commons:commons-exec:1.4.0 - https://commons.apache.org/proper/commons-exec/) - * Apache Commons Lang (org.apache.commons:commons-lang3:3.14.0 - https://commons.apache.org/proper/commons-lang/) + * Apache Commons Lang (org.apache.commons:commons-lang3:3.17.0 - https://commons.apache.org/proper/commons-lang/) * Apache Commons Math (org.apache.commons:commons-math3:3.6.1 - http://commons.apache.org/proper/commons-math/) * Apache Commons Pool (org.apache.commons:commons-pool2:2.12.0 - https://commons.apache.org/proper/commons-pool/) - * Apache Commons Text (org.apache.commons:commons-text:1.10.0 - https://commons.apache.org/proper/commons-text) + * Apache Commons Text (org.apache.commons:commons-text:1.13.0 - https://commons.apache.org/proper/commons-text) * Curator Client (org.apache.curator:curator-client:2.13.0 - http://curator.apache.org/curator-client) * Curator Framework (org.apache.curator:curator-framework:2.13.0 - http://curator.apache.org/curator-framework) * Curator Recipes (org.apache.curator:curator-recipes:2.13.0 - http://curator.apache.org/curator-recipes) @@ -207,79 +212,79 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.16 - http://hc.apache.org/httpcomponents-core-ga) * Apache HttpClient Mime (org.apache.httpcomponents:httpmime:4.5.14 - http://hc.apache.org/httpcomponents-client-ga) * Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.1.3 - https://hc.apache.org/httpcomponents-client-5.0.x/5.1.3/httpclient5/) - * Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.3.1 - https://hc.apache.org/httpcomponents-client-5.0.x/5.3.1/httpclient5/) + * Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.4.1 - https://hc.apache.org/httpcomponents-client-5.4.x/5.4.1/httpclient5/) * Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.1.3 - https://hc.apache.org/httpcomponents-core-5.1.x/5.1.3/httpcore5/) - * Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.2.4 - https://hc.apache.org/httpcomponents-core-5.2.x/5.2.4/httpcore5/) + * Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.3.1 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.1/httpcore5/) * Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.1.3 - https://hc.apache.org/httpcomponents-core-5.1.x/5.1.3/httpcore5-h2/) - * Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.2.4 - https://hc.apache.org/httpcomponents-core-5.2.x/5.2.4/httpcore5-h2/) - * Apache James :: Mime4j :: Core (org.apache.james:apache-mime4j-core:0.8.10 - http://james.apache.org/mime4j/apache-mime4j-core) + * Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.3.1 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.1/httpcore5-h2/) + * Apache James :: Mime4j :: Core (org.apache.james:apache-mime4j-core:0.8.12 - http://james.apache.org/mime4j/apache-mime4j-core) * Apache James :: Mime4j :: DOM (org.apache.james:apache-mime4j-dom:0.8.11 - http://james.apache.org/mime4j/apache-mime4j-dom) - * Apache Jena - Libraries POM (org.apache.jena:apache-jena-libs:4.9.0 - https://jena.apache.org/apache-jena-libs/) - * Apache Jena - ARQ (org.apache.jena:jena-arq:4.9.0 - https://jena.apache.org/jena-arq/) - * Apache Jena - Base (org.apache.jena:jena-base:4.9.0 - https://jena.apache.org/jena-base/) - * Apache Jena - Core (org.apache.jena:jena-core:4.9.0 - https://jena.apache.org/jena-core/) - * Apache Jena - DBOE Base (org.apache.jena:jena-dboe-base:4.9.0 - https://jena.apache.org/jena-dboe-base/) - * Apache Jena - DBOE Indexes (org.apache.jena:jena-dboe-index:4.9.0 - https://jena.apache.org/jena-dboe-index/) - * Apache Jena - DBOE Storage (org.apache.jena:jena-dboe-storage:4.9.0 - https://jena.apache.org/jena-dboe-storage/) - * Apache Jena - DBOE Transactional Datastructures (org.apache.jena:jena-dboe-trans-data:4.9.0 - https://jena.apache.org/jena-dboe-trans-data/) - * Apache Jena - DBOE Transactions (org.apache.jena:jena-dboe-transaction:4.9.0 - https://jena.apache.org/jena-dboe-transaction/) - * Apache Jena - IRI (org.apache.jena:jena-iri:4.9.0 - https://jena.apache.org/jena-iri/) - * Apache Jena - RDF Connection (org.apache.jena:jena-rdfconnection:4.9.0 - https://jena.apache.org/jena-rdfconnection/) - * Apache Jena - RDF Patch (org.apache.jena:jena-rdfpatch:4.9.0 - https://jena.apache.org/jena-rdfpatch/) - * Apache Jena - SHACL (org.apache.jena:jena-shacl:4.9.0 - https://jena.apache.org/jena-shacl/) - * Apache Jena - ShEx (org.apache.jena:jena-shex:4.9.0 - https://jena.apache.org/jena-shex/) - * Apache Jena - TDB1 (Native Triple Store) (org.apache.jena:jena-tdb:4.9.0 - https://jena.apache.org/jena-tdb/) - * Apache Jena - TDB2 (Native Triple Store) (org.apache.jena:jena-tdb2:4.9.0 - https://jena.apache.org/jena-tdb2/) + * Apache Jena - Libraries POM (org.apache.jena:apache-jena-libs:4.10.0 - https://jena.apache.org/apache-jena-libs/) + * Apache Jena - ARQ (org.apache.jena:jena-arq:4.10.0 - https://jena.apache.org/jena-arq/) + * Apache Jena - Base (org.apache.jena:jena-base:4.10.0 - https://jena.apache.org/jena-base/) + * Apache Jena - Core (org.apache.jena:jena-core:4.10.0 - https://jena.apache.org/jena-core/) + * Apache Jena - DBOE Base (org.apache.jena:jena-dboe-base:4.10.0 - https://jena.apache.org/jena-dboe-base/) + * Apache Jena - DBOE Indexes (org.apache.jena:jena-dboe-index:4.10.0 - https://jena.apache.org/jena-dboe-index/) + * Apache Jena - DBOE Storage (org.apache.jena:jena-dboe-storage:4.10.0 - https://jena.apache.org/jena-dboe-storage/) + * Apache Jena - DBOE Transactional Datastructures (org.apache.jena:jena-dboe-trans-data:4.10.0 - https://jena.apache.org/jena-dboe-trans-data/) + * Apache Jena - DBOE Transactions (org.apache.jena:jena-dboe-transaction:4.10.0 - https://jena.apache.org/jena-dboe-transaction/) + * Apache Jena - IRI (org.apache.jena:jena-iri:4.10.0 - https://jena.apache.org/jena-iri/) + * Apache Jena - RDF Connection (org.apache.jena:jena-rdfconnection:4.10.0 - https://jena.apache.org/jena-rdfconnection/) + * Apache Jena - RDF Patch (org.apache.jena:jena-rdfpatch:4.10.0 - https://jena.apache.org/jena-rdfpatch/) + * Apache Jena - SHACL (org.apache.jena:jena-shacl:4.10.0 - https://jena.apache.org/jena-shacl/) + * Apache Jena - ShEx (org.apache.jena:jena-shex:4.10.0 - https://jena.apache.org/jena-shex/) + * Apache Jena - TDB1 (Native Triple Store) (org.apache.jena:jena-tdb:4.10.0 - https://jena.apache.org/jena-tdb/) + * Apache Jena - TDB2 (Native Triple Store) (org.apache.jena:jena-tdb2:4.10.0 - https://jena.apache.org/jena-tdb2/) * Kerby-kerb core (org.apache.kerby:kerb-core:1.0.1 - http://directory.apache.org/kerby/kerby-kerb/kerb-core) * Kerby-kerb Util (org.apache.kerby:kerb-util:1.0.1 - http://directory.apache.org/kerby/kerby-kerb/kerb-util) * Kerby ASN1 Project (org.apache.kerby:kerby-asn1:1.0.1 - http://directory.apache.org/kerby/kerby-common/kerby-asn1) * Kerby PKIX Project (org.apache.kerby:kerby-pkix:1.0.1 - http://directory.apache.org/kerby/kerby-pkix) - * Apache Log4j 1.x Compatibility API (org.apache.logging.log4j:log4j-1.2-api:2.23.1 - https://logging.apache.org/log4j/2.x/log4j/log4j-1.2-api/) - * Apache Log4j API (org.apache.logging.log4j:log4j-api:2.23.1 - https://logging.apache.org/log4j/2.x/log4j/log4j-api/) - * Apache Log4j Core (org.apache.logging.log4j:log4j-core:2.23.1 - https://logging.apache.org/log4j/2.x/log4j/log4j-core/) - * Apache Log4j JUL Adapter (org.apache.logging.log4j:log4j-jul:2.23.1 - https://logging.apache.org/log4j/2.x/log4j/log4j-jul/) + * Apache Log4j 1.x Compatibility API (org.apache.logging.log4j:log4j-1.2-api:2.17.2 - https://logging.apache.org/log4j/2.x/log4j-1.2-api/) + * Apache Log4j API (org.apache.logging.log4j:log4j-api:2.24.3 - https://logging.apache.org/log4j/2.x/log4j/log4j-api/) + * Apache Log4j Core (org.apache.logging.log4j:log4j-core:2.24.3 - https://logging.apache.org/log4j/2.x/log4j/log4j-core/) + * Apache Log4j JUL Adapter (org.apache.logging.log4j:log4j-jul:2.24.3 - https://logging.apache.org/log4j/2.x/log4j/log4j-jul/) * Apache Log4j Layout for JSON template (org.apache.logging.log4j:log4j-layout-template-json:2.17.2 - https://logging.apache.org/log4j/2.x/log4j-layout-template-json/) - * Apache Log4j SLF4J Binding (org.apache.logging.log4j:log4j-slf4j-impl:2.23.1 - https://logging.apache.org/log4j/2.x/log4j/log4j-slf4j-impl/) - * Apache Log4j SLF4J 2.0 Binding (org.apache.logging.log4j:log4j-slf4j2-impl:2.21.1 - https://logging.apache.org/log4j/2.x/log4j/log4j-slf4j2-impl/) - * Apache Log4j Web (org.apache.logging.log4j:log4j-web:2.23.1 - https://logging.apache.org/log4j/2.x/log4j/log4j-web/) - * Lucene Common Analyzers (org.apache.lucene:lucene-analyzers-common:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-analyzers-common) - * Lucene ICU Analysis Components (org.apache.lucene:lucene-analyzers-icu:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-analyzers-icu) - * Lucene Kuromoji Japanese Morphological Analyzer (org.apache.lucene:lucene-analyzers-kuromoji:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-analyzers-kuromoji) - * Lucene Nori Korean Morphological Analyzer (org.apache.lucene:lucene-analyzers-nori:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-analyzers-nori) - * Lucene Phonetic Filters (org.apache.lucene:lucene-analyzers-phonetic:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-analyzers-phonetic) - * Lucene Smart Chinese Analyzer (org.apache.lucene:lucene-analyzers-smartcn:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-analyzers-smartcn) - * Lucene Stempel Analyzer (org.apache.lucene:lucene-analyzers-stempel:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-analyzers-stempel) - * Lucene Memory (org.apache.lucene:lucene-backward-codecs:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-backward-codecs) - * Lucene Classification (org.apache.lucene:lucene-classification:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-classification) - * Lucene codecs (org.apache.lucene:lucene-codecs:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-codecs) - * Lucene Core (org.apache.lucene:lucene-core:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-core) - * Lucene Expressions (org.apache.lucene:lucene-expressions:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-expressions) - * Lucene Grouping (org.apache.lucene:lucene-grouping:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-grouping) - * Lucene Highlighter (org.apache.lucene:lucene-highlighter:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-highlighter) - * Lucene Join (org.apache.lucene:lucene-join:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-join) - * Lucene Memory (org.apache.lucene:lucene-memory:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-memory) - * Lucene Miscellaneous (org.apache.lucene:lucene-misc:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-misc) - * Lucene Queries (org.apache.lucene:lucene-queries:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-queries) - * Lucene QueryParsers (org.apache.lucene:lucene-queryparser:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-queryparser) - * Lucene Sandbox (org.apache.lucene:lucene-sandbox:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-sandbox) - * Lucene Spatial Extras (org.apache.lucene:lucene-spatial-extras:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-spatial-extras) - * Lucene Spatial 3D (org.apache.lucene:lucene-spatial3d:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-spatial3d) - * Lucene Suggest (org.apache.lucene:lucene-suggest:8.11.3 - https://lucene.apache.org/lucene-parent/lucene-suggest) - * Apache FontBox (org.apache.pdfbox:fontbox:2.0.31 - http://pdfbox.apache.org/) + * Apache Log4j SLF4J Binding (org.apache.logging.log4j:log4j-slf4j-impl:2.17.2 - https://logging.apache.org/log4j/2.x/log4j-slf4j-impl/) + * SLF4J 2 Provider for Log4j API (org.apache.logging.log4j:log4j-slf4j2-impl:2.24.3 - https://logging.apache.org/log4j/2.x/log4j/log4j-slf4j2-impl/) + * Apache Log4j Web (org.apache.logging.log4j:log4j-web:2.17.2 - https://logging.apache.org/log4j/2.x/log4j-web/) + * Lucene Common Analyzers (org.apache.lucene:lucene-analyzers-common:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-common) + * Lucene ICU Analysis Components (org.apache.lucene:lucene-analyzers-icu:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-icu) + * Lucene Kuromoji Japanese Morphological Analyzer (org.apache.lucene:lucene-analyzers-kuromoji:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-kuromoji) + * Lucene Nori Korean Morphological Analyzer (org.apache.lucene:lucene-analyzers-nori:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-nori) + * Lucene Phonetic Filters (org.apache.lucene:lucene-analyzers-phonetic:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-phonetic) + * Lucene Smart Chinese Analyzer (org.apache.lucene:lucene-analyzers-smartcn:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-smartcn) + * Lucene Stempel Analyzer (org.apache.lucene:lucene-analyzers-stempel:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-stempel) + * Lucene Memory (org.apache.lucene:lucene-backward-codecs:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-backward-codecs) + * Lucene Classification (org.apache.lucene:lucene-classification:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-classification) + * Lucene codecs (org.apache.lucene:lucene-codecs:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-codecs) + * Lucene Core (org.apache.lucene:lucene-core:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-core) + * Lucene Expressions (org.apache.lucene:lucene-expressions:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-expressions) + * Lucene Grouping (org.apache.lucene:lucene-grouping:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-grouping) + * Lucene Highlighter (org.apache.lucene:lucene-highlighter:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-highlighter) + * Lucene Join (org.apache.lucene:lucene-join:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-join) + * Lucene Memory (org.apache.lucene:lucene-memory:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-memory) + * Lucene Miscellaneous (org.apache.lucene:lucene-misc:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-misc) + * Lucene Queries (org.apache.lucene:lucene-queries:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-queries) + * Lucene QueryParsers (org.apache.lucene:lucene-queryparser:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-queryparser) + * Lucene Sandbox (org.apache.lucene:lucene-sandbox:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-sandbox) + * Lucene Spatial Extras (org.apache.lucene:lucene-spatial-extras:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-spatial-extras) + * Lucene Spatial 3D (org.apache.lucene:lucene-spatial3d:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-spatial3d) + * Lucene Suggest (org.apache.lucene:lucene-suggest:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-suggest) + * Apache FontBox (org.apache.pdfbox:fontbox:2.0.33 - http://pdfbox.apache.org/) * PDFBox JBIG2 ImageIO plugin (org.apache.pdfbox:jbig2-imageio:3.0.4 - https://www.apache.org/jbig2-imageio/) * Apache JempBox (org.apache.pdfbox:jempbox:1.8.17 - http://www.apache.org/pdfbox-parent/jempbox/) - * Apache PDFBox (org.apache.pdfbox:pdfbox:2.0.31 - https://www.apache.org/pdfbox-parent/pdfbox/) + * Apache PDFBox (org.apache.pdfbox:pdfbox:2.0.33 - https://www.apache.org/pdfbox-parent/pdfbox/) * Apache PDFBox tools (org.apache.pdfbox:pdfbox-tools:2.0.31 - https://www.apache.org/pdfbox-parent/pdfbox-tools/) * Apache XmpBox (org.apache.pdfbox:xmpbox:2.0.31 - https://www.apache.org/pdfbox-parent/xmpbox/) * Apache POI - Common (org.apache.poi:poi:5.2.5 - https://poi.apache.org/) * Apache POI - API based on OPC and OOXML schemas (org.apache.poi:poi-ooxml:5.2.5 - https://poi.apache.org/) * Apache POI (org.apache.poi:poi-ooxml-lite:5.2.5 - https://poi.apache.org/) * Apache POI (org.apache.poi:poi-scratchpad:5.2.5 - https://poi.apache.org/) - * Apache Solr Core (org.apache.solr:solr-core:8.11.3 - https://lucene.apache.org/solr-parent/solr-core) - * Apache Solr Solrj (org.apache.solr:solr-solrj:8.11.3 - https://lucene.apache.org/solr-parent/solr-solrj) + * Apache Solr Core (org.apache.solr:solr-core:8.11.4 - https://lucene.apache.org/solr-parent/solr-core) + * Apache Solr Solrj (org.apache.solr:solr-solrj:8.11.4 - https://lucene.apache.org/solr-parent/solr-solrj) * Apache Standard Taglib Implementation (org.apache.taglibs:taglibs-standard-impl:1.2.5 - http://tomcat.apache.org/taglibs/standard-1.2.5/taglibs-standard-impl) * Apache Standard Taglib Specification API (org.apache.taglibs:taglibs-standard-spec:1.2.5 - http://tomcat.apache.org/taglibs/standard-1.2.5/taglibs-standard-spec) - * Apache Thrift (org.apache.thrift:libthrift:0.18.1 - http://thrift.apache.org) + * Apache Thrift (org.apache.thrift:libthrift:0.19.0 - http://thrift.apache.org) * Apache Tika core (org.apache.tika:tika-core:2.9.2 - https://tika.apache.org/) * Apache Tika Apple parser module (org.apache.tika:tika-parser-apple-module:2.9.2 - https://tika.apache.org/tika-parser-apple-module/) * Apache Tika audiovideo parser module (org.apache.tika:tika-parser-audiovideo-module:2.9.2 - https://tika.apache.org/tika-parser-audiovideo-module/) @@ -304,20 +309,21 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Apache Tika XMP commons (org.apache.tika:tika-parser-xmp-commons:2.9.2 - https://tika.apache.org/tika-parser-xmp-commons/) * Apache Tika ZIP commons (org.apache.tika:tika-parser-zip-commons:2.9.2 - https://tika.apache.org/tika-parser-zip-commons/) * Apache Tika standard parser package (org.apache.tika:tika-parsers-standard-package:2.9.2 - https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) - * tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:10.1.24 - https://tomcat.apache.org/) - * tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:10.1.24 - https://tomcat.apache.org/) - * tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:10.1.24 - https://tomcat.apache.org/) - * Apache Velocity - Engine (org.apache.velocity:velocity-engine-core:2.3 - http://velocity.apache.org/engine/devel/velocity-engine-core/) - * Apache Velocity - JSR 223 Scripting (org.apache.velocity:velocity-engine-scripting:2.2 - http://velocity.apache.org/engine/devel/velocity-engine-scripting/) + * tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:10.1.34 - https://tomcat.apache.org/) + * tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:10.1.34 - https://tomcat.apache.org/) + * tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:10.1.34 - https://tomcat.apache.org/) + * Apache Velocity - Engine (org.apache.velocity:velocity-engine-core:2.4.1 - http://velocity.apache.org/engine/devel/velocity-engine-core/) + * Apache Velocity - JSR 223 Scripting (org.apache.velocity:velocity-engine-scripting:2.3 - http://velocity.apache.org/engine/devel/velocity-engine-scripting/) + * Apache Velocity Tools - Generic tools (org.apache.velocity.tools:velocity-tools-generic:3.1 - https://velocity.apache.org/tools/devel/velocity-tools-generic/) * Axiom API (org.apache.ws.commons.axiom:axiom-api:1.2.14 - http://ws.apache.org/axiom/) * Axiom Impl (org.apache.ws.commons.axiom:axiom-impl:1.2.14 - http://ws.apache.org/axiom/) * XmlBeans (org.apache.xmlbeans:xmlbeans:5.2.0 - https://xmlbeans.apache.org/) * Apache ZooKeeper - Server (org.apache.zookeeper:zookeeper:3.6.2 - http://zookeeper.apache.org/zookeeper) * Apache ZooKeeper - Jute (org.apache.zookeeper:zookeeper-jute:3.6.2 - http://zookeeper.apache.org/zookeeper-jute) * org.apiguardian:apiguardian-api (org.apiguardian:apiguardian-api:1.1.2 - https://github.com/apiguardian-team/apiguardian) - * AssertJ Core (org.assertj:assertj-core:3.24.2 - https://assertj.github.io/doc/#assertj-core) + * AssertJ Core (org.assertj:assertj-core:3.26.3 - https://assertj.github.io/doc/#assertj-core) * Evo Inflector (org.atteo:evo-inflector:1.3 - http://atteo.org/static/evo-inflector) - * Awaitility (org.awaitility:awaitility:4.2.1 - http://awaitility.org) + * Awaitility (org.awaitility:awaitility:4.2.2 - http://awaitility.org) * jose4j (org.bitbucket.b_c:jose4j:0.6.5 - https://bitbucket.org/b_c/jose4j/) * TagSoup (org.ccil.cowan.tagsoup:tagsoup:1.2.1 - http://home.ccil.org/~cowan/XML/tagsoup/) * Woodstox (org.codehaus.woodstox:wstx-asl:3.2.6 - http://woodstox.codehaus.org) @@ -335,45 +341,48 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Jetty :: Asynchronous HTTP Client (org.eclipse.jetty:jetty-client:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-client) * Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-continuation) - * Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-deploy) - * Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-http) - * Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-io) + * Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.57.v20241219 - https://jetty.org/jetty-deploy/) + * Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.57.v20241219 - https://jetty.org/jetty-http/) + * Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.57.v20241219 - https://jetty.org/jetty-io/) * Jetty :: JMX Management (org.eclipse.jetty:jetty-jmx:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-jmx) * Jetty :: JNDI Naming (org.eclipse.jetty:jetty-jndi:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Jetty :: Plus (org.eclipse.jetty:jetty-plus:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Jetty :: Rewrite Handler (org.eclipse.jetty:jetty-rewrite:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-rewrite) * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-security) - * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-security) - * Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-server) - * Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-servlet) + * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.57.v20241219 - https://jetty.org/jetty-security/) + * Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.57.v20241219 - https://jetty.org/jetty-server/) + * Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.57.v20241219 - https://jetty.org/jetty-servlet/) * Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-servlets) - * Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-util) - * Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-util-ajax) - * Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-webapp) + * Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.57.v20241219 - https://jetty.org/jetty-util/) + * Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.57.v20241219 - https://jetty.org/jetty-util-ajax/) + * Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.57.v20241219 - https://jetty.org/jetty-webapp/) * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-xml) - * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-xml) + * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.57.v20241219 - https://jetty.org/jetty-xml/) * Jetty :: ALPN :: API (org.eclipse.jetty.alpn:alpn-api:1.1.3.v20160715 - http://www.eclipse.org/jetty/alpn-api) * Jetty :: HTTP2 :: Client (org.eclipse.jetty.http2:http2-client:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-client) - * Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.54.v20240208 - https://eclipse.org/jetty/http2-parent/http2-common) + * Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.57.v20241219 - https://jetty.org/http2-parent/http2-common/) * Jetty :: HTTP2 :: HPACK (org.eclipse.jetty.http2:http2-hpack:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-hpack) * Jetty :: HTTP2 :: HTTP Client Transport (org.eclipse.jetty.http2:http2-http-client-transport:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-http-client-transport) * Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.15.v20190215 - https://eclipse.org/jetty/http2-parent/http2-server) * Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-server) * Jetty :: Schemas (org.eclipse.jetty.toolchain:jetty-schemas:3.1.2 - https://eclipse.org/jetty/jetty-schemas) * Ehcache (org.ehcache:ehcache:3.10.8 - http://ehcache.org) - * flyway-core (org.flywaydb:flyway-core:10.10.0 - https://flywaydb.org/flyway-core) - * flyway-database-postgresql (org.flywaydb:flyway-database-postgresql:10.10.0 - https://flywaydb.org/flyway-database-postgresql) + * flyway-core (org.flywaydb:flyway-core:10.22.0 - https://flywaydb.org/flyway-core) + * flyway-database-postgresql (org.flywaydb:flyway-database-postgresql:10.22.0 - https://flywaydb.org/flyway-database-postgresql) * Ogg and Vorbis for Java, Core (org.gagravarr:vorbis-java-core:0.8 - https://github.com/Gagravarr/VorbisJava) * Apache Tika plugin for Ogg, Vorbis and FLAC (org.gagravarr:vorbis-java-tika:0.8 - https://github.com/Gagravarr/VorbisJava) - * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) * Hibernate Validator Engine (org.hibernate.validator:hibernate-validator:8.0.1.Final - http://hibernate.org/validator/hibernate-validator) * Hibernate Validator Portable Extension (org.hibernate.validator:hibernate-validator-cdi:8.0.1.Final - http://hibernate.org/validator/hibernate-validator-cdi) * org.immutables.value-annotations (org.immutables:value-annotations:2.9.2 - http://immutables.org/value-annotations) * leveldb (org.iq80.leveldb:leveldb:0.12 - http://github.com/dain/leveldb/leveldb) * leveldb-api (org.iq80.leveldb:leveldb-api:0.12 - http://github.com/dain/leveldb/leveldb-api) - * Javassist (org.javassist:javassist:3.29.2-GA - http://www.javassist.org/) - * JBoss Logging 3 (org.jboss.logging:jboss-logging:3.4.3.Final - http://www.jboss.org) + * Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/) + * JBoss Logging 3 (org.jboss.logging:jboss-logging:3.6.1.Final - http://www.jboss.org) * JDOM (org.jdom:jdom2:2.0.6.1 - http://www.jdom.org) * jtwig-core (org.jtwig:jtwig-core:5.87.0.RELEASE - http://jtwig.org) * jtwig-reflection (org.jtwig:jtwig-reflection:5.87.0.RELEASE - http://jtwig.org) @@ -382,77 +391,70 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * jtwig-web (org.jtwig:jtwig-web:5.87.0.RELEASE - http://jtwig.org) * Proj4J (org.locationtech.proj4j:proj4j:1.1.5 - https://github.com/locationtech/proj4j) * Spatial4J (org.locationtech.spatial4j:spatial4j:0.7 - https://projects.eclipse.org/projects/locationtech.spatial4j) - * MockServer Java Client (org.mock-server:mockserver-client-java:5.11.2 - http://www.mock-server.com) - * MockServer Core (org.mock-server:mockserver-core:5.11.2 - http://www.mock-server.com) - * MockServer JUnit 4 Integration (org.mock-server:mockserver-junit-rule:5.11.2 - http://www.mock-server.com) - * MockServer & Proxy Netty (org.mock-server:mockserver-netty:5.11.2 - http://www.mock-server.com) - * Jetty Server (org.mortbay.jetty:jetty:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/modules/jetty) - * Jetty Servlet Tester (org.mortbay.jetty:jetty-servlet-tester:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/jetty-servlet-tester) - * Jetty Utilities (org.mortbay.jetty:jetty-util:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/jetty-util) - * Servlet Specification API (org.mortbay.jetty:servlet-api:2.5-20081211 - http://jetty.mortbay.org/servlet-api) + * MockServer Java Client (org.mock-server:mockserver-client-java:5.15.0 - https://www.mock-server.com) + * MockServer Core (org.mock-server:mockserver-core:5.15.0 - https://www.mock-server.com) + * MockServer JUnit 4 Integration (org.mock-server:mockserver-junit-rule:5.15.0 - https://www.mock-server.com) + * MockServer & Proxy Netty (org.mock-server:mockserver-netty:5.15.0 - https://www.mock-server.com) * jwarc (org.netpreserve:jwarc:0.29.0 - https://github.com/iipc/jwarc) * Objenesis (org.objenesis:objenesis:3.2 - http://objenesis.org/objenesis) - * parboiled-core (org.parboiled:parboiled-core:1.3.1 - http://parboiled.org) - * parboiled-java (org.parboiled:parboiled-java:1.3.1 - http://parboiled.org) - * org.roaringbitmap:RoaringBitmap (org.roaringbitmap:RoaringBitmap:0.9.45 - https://github.com/RoaringBitmap/RoaringBitmap) - * org.roaringbitmap:shims (org.roaringbitmap:shims:0.9.45 - https://github.com/RoaringBitmap/RoaringBitmap) + * parboiled-core (org.parboiled:parboiled-core:1.1.7 - http://parboiled.org) + * parboiled-java (org.parboiled:parboiled-java:1.1.7 - http://parboiled.org) + * org.roaringbitmap:RoaringBitmap (org.roaringbitmap:RoaringBitmap:1.0.0 - https://github.com/RoaringBitmap/RoaringBitmap) * RRD4J (org.rrd4j:rrd4j:3.5 - https://github.com/rrd4j/rrd4j/) - * Scala Library (org.scala-lang:scala-library:2.13.11 - https://www.scala-lang.org/) + * Scala Library (org.scala-lang:scala-library:2.13.2 - https://www.scala-lang.org/) * Scala Compiler (org.scala-lang:scala-reflect:2.13.0 - https://www.scala-lang.org/) * scala-collection-compat (org.scala-lang.modules:scala-collection-compat_2.13:2.1.6 - http://www.scala-lang.org/) * scala-java8-compat (org.scala-lang.modules:scala-java8-compat_2.13:0.9.0 - http://www.scala-lang.org/) * scala-parser-combinators (org.scala-lang.modules:scala-parser-combinators_2.13:1.1.2 - http://www.scala-lang.org/) * scala-xml (org.scala-lang.modules:scala-xml_2.13:1.3.0 - http://www.scala-lang.org/) - * JSONassert (org.skyscreamer:jsonassert:1.5.1 - https://github.com/skyscreamer/JSONassert) - * JCL 1.2 implemented over SLF4J (org.slf4j:jcl-over-slf4j:2.0.11 - http://www.slf4j.org) - * Spring AOP (org.springframework:spring-aop:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Beans (org.springframework:spring-beans:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Context (org.springframework:spring-context:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Context Support (org.springframework:spring-context-support:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Core (org.springframework:spring-core:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Expression Language (SpEL) (org.springframework:spring-expression:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Commons Logging Bridge (org.springframework:spring-jcl:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring JDBC (org.springframework:spring-jdbc:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Object/Relational Mapping (org.springframework:spring-orm:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring TestContext Framework (org.springframework:spring-test:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Transaction (org.springframework:spring-tx:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Web (org.springframework:spring-web:6.1.8 - https://github.com/spring-projects/spring-framework) - * Spring Web MVC (org.springframework:spring-webmvc:6.1.8 - https://github.com/spring-projects/spring-framework) - * spring-boot (org.springframework.boot:spring-boot:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-actuator (org.springframework.boot:spring-boot-actuator:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:3.2.6 - https://spring.io/projects/spring-boot) + * JSONassert (org.skyscreamer:jsonassert:1.5.3 - https://github.com/skyscreamer/JSONassert) + * JCL 1.2 implemented over SLF4J (org.slf4j:jcl-over-slf4j:2.0.16 - http://www.slf4j.org) + * Spring AOP (org.springframework:spring-aop:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Beans (org.springframework:spring-beans:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Context (org.springframework:spring-context:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Context Support (org.springframework:spring-context-support:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Core (org.springframework:spring-core:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Expression Language (SpEL) (org.springframework:spring-expression:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Commons Logging Bridge (org.springframework:spring-jcl:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring JDBC (org.springframework:spring-jdbc:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Object/Relational Mapping (org.springframework:spring-orm:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring TestContext Framework (org.springframework:spring-test:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Transaction (org.springframework:spring-tx:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Web (org.springframework:spring-web:6.2.2 - https://github.com/spring-projects/spring-framework) + * Spring Web MVC (org.springframework:spring-webmvc:6.2.2 - https://github.com/spring-projects/spring-framework) + * spring-boot (org.springframework.boot:spring-boot:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-actuator (org.springframework.boot:spring-boot-actuator:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:3.4.2 - https://spring.io/projects/spring-boot) * Spring Boot Configuration Processor (org.springframework.boot:spring-boot-configuration-processor:2.0.0.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-tools/spring-boot-configuration-processor) - * spring-boot-starter (org.springframework.boot:spring-boot-starter:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-aop (org.springframework.boot:spring-boot-starter-aop:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-cache (org.springframework.boot:spring-boot-starter-cache:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-data-rest (org.springframework.boot:spring-boot-starter-data-rest:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-log4j2 (org.springframework.boot:spring-boot-starter-log4j2:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-security (org.springframework.boot:spring-boot-starter-security:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-test (org.springframework.boot:spring-boot-starter-test:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-test (org.springframework.boot:spring-boot-test:3.2.6 - https://spring.io/projects/spring-boot) - * spring-boot-test-autoconfigure (org.springframework.boot:spring-boot-test-autoconfigure:3.2.6 - https://spring.io/projects/spring-boot) - * Spring Data Core (org.springframework.data:spring-data-commons:3.2.6 - https://spring.io/projects/spring-data) - * Spring Data REST - Core (org.springframework.data:spring-data-rest-core:4.2.6 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-core) - * Spring Data REST - WebMVC (org.springframework.data:spring-data-rest-webmvc:4.2.6 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-webmvc) - * Spring HATEOAS (org.springframework.hateoas:spring-hateoas:2.2.2 - https://github.com/spring-projects/spring-hateoas) + * spring-boot-starter (org.springframework.boot:spring-boot-starter:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-aop (org.springframework.boot:spring-boot-starter-aop:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-cache (org.springframework.boot:spring-boot-starter-cache:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-data-rest (org.springframework.boot:spring-boot-starter-data-rest:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-log4j2 (org.springframework.boot:spring-boot-starter-log4j2:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-security (org.springframework.boot:spring-boot-starter-security:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-test (org.springframework.boot:spring-boot-starter-test:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-test (org.springframework.boot:spring-boot-test:3.4.2 - https://spring.io/projects/spring-boot) + * spring-boot-test-autoconfigure (org.springframework.boot:spring-boot-test-autoconfigure:3.4.2 - https://spring.io/projects/spring-boot) + * Spring Data Core (org.springframework.data:spring-data-commons:3.4.2 - https://spring.io/projects/spring-data) + * Spring Data REST - Core (org.springframework.data:spring-data-rest-core:4.4.2 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-core) + * Spring Data REST - WebMVC (org.springframework.data:spring-data-rest-webmvc:4.4.2 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-webmvc) + * Spring HATEOAS (org.springframework.hateoas:spring-hateoas:2.4.1 - https://github.com/spring-projects/spring-hateoas) * Spring Plugin - Core (org.springframework.plugin:spring-plugin-core:3.0.0 - https://github.com/spring-projects/spring-plugin/spring-plugin-core) - * spring-security-config (org.springframework.security:spring-security-config:6.2.4 - https://spring.io/projects/spring-security) - * spring-security-core (org.springframework.security:spring-security-core:6.2.4 - https://spring.io/projects/spring-security) - * spring-security-crypto (org.springframework.security:spring-security-crypto:6.2.4 - https://spring.io/projects/spring-security) - * spring-security-test (org.springframework.security:spring-security-test:6.2.4 - https://spring.io/projects/spring-security) - * spring-security-web (org.springframework.security:spring-security-web:6.2.4 - https://spring.io/projects/spring-security) + * spring-security-config (org.springframework.security:spring-security-config:6.4.2 - https://spring.io/projects/spring-security) + * spring-security-core (org.springframework.security:spring-security-core:6.4.2 - https://spring.io/projects/spring-security) + * spring-security-crypto (org.springframework.security:spring-security-crypto:6.4.2 - https://spring.io/projects/spring-security) + * spring-security-test (org.springframework.security:spring-security-test:6.4.2 - https://spring.io/projects/spring-security) + * spring-security-web (org.springframework.security:spring-security-web:6.4.2 - https://spring.io/projects/spring-security) * snappy-java (org.xerial.snappy:snappy-java:1.1.10.1 - https://github.com/xerial/snappy-java) * xml-matchers (org.xmlmatchers:xml-matchers:0.10 - http://code.google.com/p/xml-matchers/) * org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.10.0 - https://www.xmlunit.org/) - * org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.9.1 - https://www.xmlunit.org/) - * org.xmlunit:xmlunit-placeholders (org.xmlunit:xmlunit-placeholders:2.8.0 - https://www.xmlunit.org/xmlunit-placeholders/) - * SnakeYAML (org.yaml:snakeyaml:2.2 - https://bitbucket.org/snakeyaml/snakeyaml) - * software.amazon.ion:ion-java (software.amazon.ion:ion-java:1.0.2 - https://github.com/amznlabs/ion-java/) + * org.xmlunit:xmlunit-placeholders (org.xmlunit:xmlunit-placeholders:2.9.1 - https://www.xmlunit.org/xmlunit-placeholders/) + * SnakeYAML (org.yaml:snakeyaml:2.3 - https://bitbucket.org/snakeyaml/snakeyaml) * Xerces2-j (xerces:xercesImpl:2.12.2 - https://xerces.apache.org/xerces2-j/) BSD License: @@ -463,25 +465,29 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * JSONLD Java :: Core (com.github.jsonld-java:jsonld-java:0.13.4 - http://github.com/jsonld-java/jsonld-java/jsonld-java/) * curvesapi (com.github.virtuald:curvesapi:1.08 - https://github.com/virtuald/curvesapi) * Protocol Buffers [Core] (com.google.protobuf:protobuf-java:3.15.0 - https://developers.google.com/protocol-buffers/protobuf-java/) - * Protocol Buffers [Core] (com.google.protobuf:protobuf-java:3.23.3 - https://developers.google.com/protocol-buffers/protobuf-java/) + * Protocol Buffers [Core] (com.google.protobuf:protobuf-java:3.24.3 - https://developers.google.com/protocol-buffers/protobuf-java/) * JZlib (com.jcraft:jzlib:1.1.3 - http://www.jcraft.com/jzlib/) - * dnsjava (dnsjava:dnsjava:2.1.9 - http://www.dnsjava.org) + * jmustache (com.samskivert:jmustache:1.15 - http://github.com/samskivert/jmustache) + * dnsjava (dnsjava:dnsjava:3.6.2 - https://github.com/dnsjava/dnsjava) * jaxen (jaxen:jaxen:2.0.0 - http://www.cafeconleche.org/jaxen/jaxen) - * ANTLR 4 Runtime (org.antlr:antlr4-runtime:4.13.1 - https://www.antlr.org/antlr4-runtime/) + * ANTLR 4 Runtime (org.antlr:antlr4-runtime:4.13.2 - https://www.antlr.org/antlr4-runtime/) * commons-compiler (org.codehaus.janino:commons-compiler:3.1.8 - http://janino-compiler.github.io/commons-compiler/) * janino (org.codehaus.janino:janino:3.1.8 - http://janino-compiler.github.io/janino/) * Stax2 API (org.codehaus.woodstox:stax2-api:4.2.1 - http://github.com/FasterXML/stax2-api) * Hamcrest Date (org.exparity:hamcrest-date:2.0.8 - https://github.com/exparity/hamcrest-date) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) * Hamcrest (org.hamcrest:hamcrest:2.2 - http://hamcrest.org/JavaHamcrest/) * Hamcrest Core (org.hamcrest:hamcrest-core:2.2 - http://hamcrest.org/JavaHamcrest/) - * HdrHistogram (org.hdrhistogram:HdrHistogram:2.1.12 - http://hdrhistogram.github.io/HdrHistogram/) + * HdrHistogram (org.hdrhistogram:HdrHistogram:2.2.2 - http://hdrhistogram.github.io/HdrHistogram/) * JBibTeX (org.jbibtex:jbibtex:1.0.20 - http://www.jbibtex.org) * asm (org.ow2.asm:asm:8.0.1 - http://asm.ow2.io/) * asm-analysis (org.ow2.asm:asm-analysis:8.0.1 - http://asm.ow2.io/) * asm-commons (org.ow2.asm:asm-commons:8.0.1 - http://asm.ow2.io/) * asm-tree (org.ow2.asm:asm-tree:8.0.1 - http://asm.ow2.io/) - * asm-util (org.ow2.asm:asm-util:7.1 - http://asm.ow2.org/) - * PostgreSQL JDBC Driver (org.postgresql:postgresql:42.7.3 - https://jdbc.postgresql.org) + * ASM Util (org.ow2.asm:asm-util:5.0.3 - http://asm.objectweb.org/asm-util/) + * PostgreSQL JDBC Driver (org.postgresql:postgresql:42.7.5 - https://jdbc.postgresql.org) * Reflections (org.reflections:reflections:0.9.12 - http://github.com/ronmamo/reflections) * JMatIO (org.tallison:jmatio:1.5 - https://github.com/tballison/jmatio) * XMLUnit for Java (xmlunit:xmlunit:1.3 - http://xmlunit.sourceforge.net/) @@ -497,7 +503,7 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Old JAXB Runtime (com.sun.xml.bind:jaxb-impl:2.3.1 - http://jaxb.java.net/jaxb-bundles/jaxb-impl) * Jakarta Annotations API (jakarta.annotation:jakarta.annotation-api:2.1.1 - https://projects.eclipse.org/projects/ee4j.ca) * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.3 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api) - * Jakarta Servlet (jakarta.servlet:jakarta.servlet-api:6.0.0 - https://projects.eclipse.org/projects/ee4j.servlet) + * Jakarta Servlet (jakarta.servlet:jakarta.servlet-api:6.1.0 - https://projects.eclipse.org/projects/ee4j.servlet) * jakarta.transaction API (jakarta.transaction:jakarta.transaction-api:2.0.1 - https://projects.eclipse.org/projects/ee4j.jta) * JavaBeans Activation Framework API jar (javax.activation:javax.activation-api:1.2.0 - http://java.net/all/javax.activation-api/) * javax.annotation API (javax.annotation:javax.annotation-api:1.3 - http://jcp.org/en/jsr/detail?id=250) @@ -506,13 +512,13 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * jaxb-api (javax.xml.bind:jaxb-api:2.3.1 - https://github.com/javaee/jaxb-spec/jaxb-api) * JHighlight (org.codelibs:jhighlight:1.1.0 - https://github.com/codelibs/jhighlight) * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.3 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail) - * HK2 API module (org.glassfish.hk2:hk2-api:3.0.5 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-api) - * ServiceLocator Default Implementation (org.glassfish.hk2:hk2-locator:3.0.5 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-locator) - * HK2 Implementation Utilities (org.glassfish.hk2:hk2-utils:3.0.5 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-utils) + * HK2 API module (org.glassfish.hk2:hk2-api:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-api) + * ServiceLocator Default Implementation (org.glassfish.hk2:hk2-locator:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-locator) + * HK2 Implementation Utilities (org.glassfish.hk2:hk2-utils:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-utils) * OSGi resource locator (org.glassfish.hk2:osgi-resource-locator:1.0.3 - https://projects.eclipse.org/projects/ee4j/osgi-resource-locator) - * aopalliance version 1.0 repackaged as a module (org.glassfish.hk2.external:aopalliance-repackaged:3.0.5 - https://github.com/eclipse-ee4j/glassfish-hk2/external/aopalliance-repackaged) - * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) - * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * aopalliance version 1.0 repackaged as a module (org.glassfish.hk2.external:aopalliance-repackaged:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/external/aopalliance-repackaged) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) Cordra (Version 2) License Agreement: @@ -536,8 +542,8 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * JAXB Core (org.glassfish.jaxb:jaxb-core:4.0.5 - https://eclipse-ee4j.github.io/jaxb-ri/) * JAXB Runtime (org.glassfish.jaxb:jaxb-runtime:4.0.5 - https://eclipse-ee4j.github.io/jaxb-ri/) * TXW2 Runtime (org.glassfish.jaxb:txw2:4.0.5 - https://eclipse-ee4j.github.io/jaxb-ri/) - * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) - * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) * MIME streaming extension (org.jvnet.mimepull:mimepull:1.9.15 - https://github.com/eclipse-ee4j/metro-mimepull) * org.locationtech.jts:jts-core (org.locationtech.jts:jts-core:1.19.0 - https://www.locationtech.org/projects/technology.jts/jts-modules/jts-core) @@ -546,16 +552,16 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines Eclipse Public License: * System Rules (com.github.stefanbirkner:system-rules:1.19.0 - http://stefanbirkner.github.io/system-rules/) - * H2 Database Engine (com.h2database:h2:2.2.224 - https://h2database.com) + * H2 Database Engine (com.h2database:h2:2.3.232 - https://h2database.com) * Jakarta Annotations API (jakarta.annotation:jakarta.annotation-api:2.1.1 - https://projects.eclipse.org/projects/ee4j.ca) * Jakarta Expression Language API (jakarta.el:jakarta.el-api:5.0.1 - https://projects.eclipse.org/projects/ee4j.el) * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.3 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api) * Jakarta Persistence API (jakarta.persistence:jakarta.persistence-api:3.1.0 - https://github.com/eclipse-ee4j/jpa-api) - * Jakarta Servlet (jakarta.servlet:jakarta.servlet-api:6.0.0 - https://projects.eclipse.org/projects/ee4j.servlet) + * Jakarta Servlet (jakarta.servlet:jakarta.servlet-api:6.1.0 - https://projects.eclipse.org/projects/ee4j.servlet) * jakarta.transaction API (jakarta.transaction:jakarta.transaction-api:2.0.1 - https://projects.eclipse.org/projects/ee4j.jta) * Jakarta RESTful WS API (jakarta.ws.rs:jakarta.ws.rs-api:3.1.0 - https://github.com/eclipse-ee4j/jaxrs-api) * JUnit (junit:junit:4.13.2 - http://junit.org) - * AspectJ Weaver (org.aspectj:aspectjweaver:1.9.22 - https://www.eclipse.org/aspectj/) + * AspectJ Weaver (org.aspectj:aspectjweaver:1.9.22.1 - https://www.eclipse.org/aspectj/) * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.3 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail) * Jetty :: Apache JSP Implementation (org.eclipse.jetty:apache-jsp:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Apache :: JSTL module (org.eclipse.jetty:apache-jstl:9.4.15.v20190215 - http://tomcat.apache.org/taglibs/standard/) @@ -569,53 +575,59 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Jetty :: Asynchronous HTTP Client (org.eclipse.jetty:jetty-client:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-client) * Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-continuation) - * Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-deploy) - * Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-http) - * Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-io) + * Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.57.v20241219 - https://jetty.org/jetty-deploy/) + * Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.57.v20241219 - https://jetty.org/jetty-http/) + * Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.57.v20241219 - https://jetty.org/jetty-io/) * Jetty :: JMX Management (org.eclipse.jetty:jetty-jmx:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-jmx) * Jetty :: JNDI Naming (org.eclipse.jetty:jetty-jndi:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Jetty :: Plus (org.eclipse.jetty:jetty-plus:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Jetty :: Rewrite Handler (org.eclipse.jetty:jetty-rewrite:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-rewrite) * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-security) - * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-security) - * Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-server) - * Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-servlet) + * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.57.v20241219 - https://jetty.org/jetty-security/) + * Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.57.v20241219 - https://jetty.org/jetty-server/) + * Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.57.v20241219 - https://jetty.org/jetty-servlet/) * Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-servlets) - * Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-util) - * Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-util-ajax) - * Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-webapp) + * Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.57.v20241219 - https://jetty.org/jetty-util/) + * Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.57.v20241219 - https://jetty.org/jetty-util-ajax/) + * Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.57.v20241219 - https://jetty.org/jetty-webapp/) * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-xml) - * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.54.v20240208 - https://eclipse.org/jetty/jetty-xml) + * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.57.v20241219 - https://jetty.org/jetty-xml/) * Jetty :: ALPN :: API (org.eclipse.jetty.alpn:alpn-api:1.1.3.v20160715 - http://www.eclipse.org/jetty/alpn-api) * Jetty :: HTTP2 :: Client (org.eclipse.jetty.http2:http2-client:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-client) - * Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.54.v20240208 - https://eclipse.org/jetty/http2-parent/http2-common) + * Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.57.v20241219 - https://jetty.org/http2-parent/http2-common/) * Jetty :: HTTP2 :: HPACK (org.eclipse.jetty.http2:http2-hpack:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-hpack) * Jetty :: HTTP2 :: HTTP Client Transport (org.eclipse.jetty.http2:http2-http-client-transport:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-http-client-transport) * Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.15.v20190215 - https://eclipse.org/jetty/http2-parent/http2-server) * Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-server) * Jetty :: Schemas (org.eclipse.jetty.toolchain:jetty-schemas:3.1.2 - https://eclipse.org/jetty/jetty-schemas) * JSON-P Default Provider (org.glassfish:jakarta.json:2.0.1 - https://github.com/eclipse-ee4j/jsonp) - * HK2 API module (org.glassfish.hk2:hk2-api:3.0.5 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-api) - * ServiceLocator Default Implementation (org.glassfish.hk2:hk2-locator:3.0.5 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-locator) - * HK2 Implementation Utilities (org.glassfish.hk2:hk2-utils:3.0.5 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-utils) + * HK2 API module (org.glassfish.hk2:hk2-api:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-api) + * ServiceLocator Default Implementation (org.glassfish.hk2:hk2-locator:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-locator) + * HK2 Implementation Utilities (org.glassfish.hk2:hk2-utils:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-utils) * OSGi resource locator (org.glassfish.hk2:osgi-resource-locator:1.0.3 - https://projects.eclipse.org/projects/ee4j/osgi-resource-locator) - * aopalliance version 1.0 repackaged as a module (org.glassfish.hk2.external:aopalliance-repackaged:3.0.5 - https://github.com/eclipse-ee4j/glassfish-hk2/external/aopalliance-repackaged) - * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) - * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common) - * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * aopalliance version 1.0 repackaged as a module (org.glassfish.hk2.external:aopalliance-repackaged:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/external/aopalliance-repackaged) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) * org.locationtech.jts:jts-core (org.locationtech.jts:jts-core:1.19.0 - https://www.locationtech.org/projects/technology.jts/jts-modules/jts-core) * org.locationtech.jts.io:jts-io-common (org.locationtech.jts.io:jts-io-common:1.19.0 - https://www.locationtech.org/projects/technology.jts/jts-modules/jts-io/jts-io-common) - * Jetty Server (org.mortbay.jetty:jetty:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/modules/jetty) - * Jetty Servlet Tester (org.mortbay.jetty:jetty-servlet-tester:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/jetty-servlet-tester) - * Jetty Utilities (org.mortbay.jetty:jetty-util:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/jetty-util) + + GENERAL PUBLIC LICENSE, version 3 (GPL-3.0): + + * juniversalchardet (com.github.albfernandez:juniversalchardet:2.4.0 - https://github.com/albfernandez/juniversalchardet) + + GNU LESSER GENERAL PUBLIC LICENSE, version 3 (LGPL-3.0): + + * juniversalchardet (com.github.albfernandez:juniversalchardet:2.4.0 - https://github.com/albfernandez/juniversalchardet) GNU Lesser General Public License (LGPL): * btf (com.github.java-json-tools:btf:1.3 - https://github.com/java-json-tools/btf) * jackson-coreutils (com.github.java-json-tools:jackson-coreutils:2.0 - https://github.com/java-json-tools/jackson-coreutils) * jackson-coreutils-equivalence (com.github.java-json-tools:jackson-coreutils-equivalence:1.0 - https://github.com/java-json-tools/jackson-coreutils) + * json-patch (com.github.java-json-tools:json-patch:1.13 - https://github.com/java-json-tools/json-patch) * json-schema-core (com.github.java-json-tools:json-schema-core:1.2.14 - https://github.com/java-json-tools/json-schema-core) * json-schema-validator (com.github.java-json-tools:json-schema-validator:2.2.14 - https://github.com/java-json-tools/json-schema-validator) * msg-simple (com.github.java-json-tools:msg-simple:1.2 - https://github.com/java-json-tools/msg-simple) @@ -627,7 +639,7 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Hibernate ORM - hibernate-jcache (org.hibernate.orm:hibernate-jcache:6.4.8.Final - https://hibernate.org/orm) * Hibernate ORM - hibernate-jpamodelgen (org.hibernate.orm:hibernate-jpamodelgen:6.4.8.Final - https://hibernate.org/orm) * im4java (org.im4java:im4java:1.4.0 - http://sourceforge.net/projects/im4java/) - * Javassist (org.javassist:javassist:3.29.2-GA - http://www.javassist.org/) + * Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/) * XOM (xom:xom:1.3.9 - https://xom.nu) Go License: @@ -648,25 +660,22 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * better-files (com.github.pathikrit:better-files_2.13:3.9.1 - https://github.com/pathikrit/better-files) * Java SemVer (com.github.zafarkhaja:java-semver:0.9.0 - https://github.com/zafarkhaja/jsemver) * dd-plist (com.googlecode.plist:dd-plist:1.28 - http://www.github.com/3breadt/dd-plist) - * DigitalCollections: IIIF API Library (de.digitalcollections.iiif:iiif-apis:0.3.10 - https://github.com/dbmdz/iiif-apis) + * DigitalCollections: IIIF API Library (de.digitalcollections.iiif:iiif-apis:0.3.11 - https://github.com/dbmdz/iiif-apis) * s3mock (io.findify:s3mock_2.13:0.2.6 - https://github.com/findify/s3mock) * ClassGraph (io.github.classgraph:classgraph:4.8.165 - https://github.com/classgraph/classgraph) * JOpt Simple (net.sf.jopt-simple:jopt-simple:5.0.4 - http://jopt-simple.github.io/jopt-simple) * Bouncy Castle S/MIME API (org.bouncycastle:bcmail-jdk18on:1.77 - https://www.bouncycastle.org/java.html) - * Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk15on:1.67 - http://www.bouncycastle.org/java.html) - * Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk18on:1.78.1 - https://www.bouncycastle.org/java.html) - * Bouncy Castle Provider (org.bouncycastle:bcprov-jdk15on:1.67 - http://www.bouncycastle.org/java.html) - * Bouncy Castle Provider (org.bouncycastle:bcprov-jdk18on:1.78.1 - https://www.bouncycastle.org/java.html) - * Bouncy Castle ASN.1 Extension and Utility APIs (org.bouncycastle:bcutil-jdk18on:1.78.1 - https://www.bouncycastle.org/java.html) + * Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk18on:1.80 - https://www.bouncycastle.org/download/bouncy-castle-java/) + * Bouncy Castle Provider (org.bouncycastle:bcprov-jdk18on:1.80 - https://www.bouncycastle.org/download/bouncy-castle-java/) + * Bouncy Castle ASN.1 Extension and Utility APIs (org.bouncycastle:bcutil-jdk18on:1.80 - https://www.bouncycastle.org/download/bouncy-castle-java/) * org.brotli:dec (org.brotli:dec:0.1.2 - http://brotli.org/dec) - * Checker Qual (org.checkerframework:checker-qual:3.31.0 - https://checkerframework.org) - * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) - * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * Checker Qual (org.checkerframework:checker-qual:3.48.4 - https://checkerframework.org/) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) * mockito-core (org.mockito:mockito-core:3.12.4 - https://github.com/mockito/mockito) * mockito-inline (org.mockito:mockito-inline:3.12.4 - https://github.com/mockito/mockito) - * SLF4J API Module (org.slf4j:slf4j-api:2.0.11 - http://www.slf4j.org) - * SLF4J Extensions Module (org.slf4j:slf4j-ext:1.7.28 - http://www.slf4j.org) + * SLF4J API Module (org.slf4j:slf4j-api:2.0.16 - http://www.slf4j.org) * HAL Browser (org.webjars:hal-browser:ad9b865 - http://webjars.org) * toastr (org.webjars.bowergithub.codeseven:toastr:2.1.4 - http://webjars.org) * backbone (org.webjars.bowergithub.jashkenas:backbone:1.4.1 - https://www.webjars.org) @@ -674,24 +683,24 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * jquery (org.webjars.bowergithub.jquery:jquery-dist:3.7.1 - https://www.webjars.org) * urijs (org.webjars.bowergithub.medialize:uri.js:1.19.11 - https://www.webjars.org) * bootstrap (org.webjars.bowergithub.twbs:bootstrap:4.6.2 - https://www.webjars.org) - * core-js (org.webjars.npm:core-js:3.37.1 - https://www.webjars.org) - * @json-editor/json-editor (org.webjars.npm:json-editor__json-editor:2.6.1 - https://www.webjars.org) + * core-js (org.webjars.npm:core-js:3.40.0 - https://www.webjars.org) + * @json-editor/json-editor (org.webjars.npm:json-editor__json-editor:2.15.1 - https://www.webjars.org) Mozilla Public License: * juniversalchardet (com.github.albfernandez:juniversalchardet:2.4.0 - https://github.com/albfernandez/juniversalchardet) - * H2 Database Engine (com.h2database:h2:2.2.224 - https://h2database.com) + * H2 Database Engine (com.h2database:h2:2.3.232 - https://h2database.com) * Saxon-HE (net.sf.saxon:Saxon-HE:9.8.0-14 - http://www.saxonica.com/) - * Javassist (org.javassist:javassist:3.29.2-GA - http://www.javassist.org/) + * Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/) * Mozilla Rhino (org.mozilla:rhino:1.7.7.2 - https://developer.mozilla.org/en/Rhino) Public Domain: - * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) - * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common) - * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) - * HdrHistogram (org.hdrhistogram:HdrHistogram:2.1.12 - http://hdrhistogram.github.io/HdrHistogram/) + * HdrHistogram (org.hdrhistogram:HdrHistogram:2.2.2 - http://hdrhistogram.github.io/HdrHistogram/) * JSON in Java (org.json:json:20231013 - https://github.com/douglascrockford/JSON-java) * LatencyUtils (org.latencyutils:LatencyUtils:2.0.3 - http://latencyutils.github.io/LatencyUtils/) * Reflections (org.reflections:reflections:0.9.12 - http://github.com/ronmamo/reflections) @@ -703,16 +712,16 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines Unicode/ICU License: - * ICU4J (com.ibm.icu:icu4j:62.1 - http://icu-project.org/) + * ICU4J (com.ibm.icu:icu4j:62.2 - http://icu-project.org/) W3C license: - * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) - * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) jQuery license: - * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) - * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.5 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) + * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) + * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) diff --git a/pom.xml b/pom.xml index ba9af988ab41..ae8cca4a57a0 100644 --- a/pom.xml +++ b/pom.xml @@ -719,7 +719,7 @@ Apache Software License, Version 2.0|The SAX License|The W3C License Apache Software License, Version 2.0|Similar to Apache License but with the acknowledgment clause removed - BSD License|The BSD License|BSD licence|BSD license|BSD|BSD-style license|New BSD License|New BSD license|Revised BSD License|BSD 2-Clause license|3-Clause BSD License|BSD 2-Clause|BSD 3-clause New License|BSD Licence 3|BSD-2-Clause|BSD-3-Clause|Modified BSD|The New BSD License|The BSD 3-Clause License (BSD3)|BSD License 3|BSD License 2.0 + BSD License|The BSD License|BSD licence|BSD license|BSD|BSD-style license|New BSD License|New BSD license|Revised BSD License|BSD 2-Clause license|3-Clause BSD License|BSD 2-Clause|BSD 3-clause New License|BSD Licence 3|BSD-2-Clause|BSD-3-Clause|Modified BSD|The New BSD License|The BSD 3-Clause License (BSD3)|BSD License 3|BSD License 2.0|The (New) BSD License BSD License|DSpace BSD License|DSpace Sourcecode License From 6181f2723ccc0cba6b8260e8241d6b20f5bcfcd9 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 7 Feb 2025 10:57:02 -0600 Subject: [PATCH 439/632] [maven-release-plugin] prepare release dspace-7.6.3 --- dspace-api/pom.xml | 2 +- dspace-iiif/pom.xml | 2 +- dspace-oai/pom.xml | 2 +- dspace-rdf/pom.xml | 2 +- dspace-rest/pom.xml | 4 ++-- dspace-server-webapp/pom.xml | 2 +- dspace-services/pom.xml | 2 +- dspace-sword/pom.xml | 2 +- dspace-swordv2/pom.xml | 2 +- dspace/modules/additions/pom.xml | 2 +- dspace/modules/pom.xml | 2 +- dspace/modules/rest/pom.xml | 2 +- dspace/modules/server/pom.xml | 2 +- dspace/pom.xml | 2 +- pom.xml | 32 ++++++++++++++++---------------- 15 files changed, 31 insertions(+), 31 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 77adf3b9675f..fa46d10104de 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -12,7 +12,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index 86702fe01b96..1dbdd4ab73e1 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index f7acdae99292..ac9805ee6917 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -8,7 +8,7 @@ dspace-parent org.dspace - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index 64d88b63c780..d7550e4693f6 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace-rest/pom.xml b/dspace-rest/pom.xml index fa4e15e8b626..e67b1e391007 100644 --- a/dspace-rest/pom.xml +++ b/dspace-rest/pom.xml @@ -3,7 +3,7 @@ org.dspace dspace-rest war - 7.6.3-SNAPSHOT + 7.6.3 DSpace (Deprecated) REST Webapp DSpace RESTful Web Services API. NOTE: this REST API is DEPRECATED. Please consider using the REST API in the dspace-server-webapp instead! @@ -12,7 +12,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 63de9fe721cd..79e5320ed97b 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 6504ae2e4b2a..5c8d1ac1b0ef 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index c48266454604..f3bc891ddc86 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 7cae05672470..944c8df23af6 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -13,7 +13,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace/modules/additions/pom.xml b/dspace/modules/additions/pom.xml index db9343804013..e91395783368 100644 --- a/dspace/modules/additions/pom.xml +++ b/dspace/modules/additions/pom.xml @@ -17,7 +17,7 @@ org.dspace modules - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace/modules/pom.xml b/dspace/modules/pom.xml index 3f15bdd01f4f..d48c14803b09 100644 --- a/dspace/modules/pom.xml +++ b/dspace/modules/pom.xml @@ -11,7 +11,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 ../../pom.xml diff --git a/dspace/modules/rest/pom.xml b/dspace/modules/rest/pom.xml index e2e0041cb298..39271f9599d7 100644 --- a/dspace/modules/rest/pom.xml +++ b/dspace/modules/rest/pom.xml @@ -13,7 +13,7 @@ org.dspace modules - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index cdbec2f60c8b..ea04eddd9501 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -13,7 +13,7 @@ just adding new jar in the classloader modules org.dspace - 7.6.3-SNAPSHOT + 7.6.3 .. diff --git a/dspace/pom.xml b/dspace/pom.xml index b3b474bfbcbc..7fd41160492a 100644 --- a/dspace/pom.xml +++ b/dspace/pom.xml @@ -16,7 +16,7 @@ org.dspace dspace-parent - 7.6.3-SNAPSHOT + 7.6.3 ../pom.xml diff --git a/pom.xml b/pom.xml index e8a2b39faf4e..afd5cef2e972 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.dspace dspace-parent pom - 7.6.3-SNAPSHOT + 7.6.3 DSpace Parent Project DSpace open source software is a turnkey institutional repository application. @@ -875,14 +875,14 @@ org.dspace dspace-rest - 7.6.3-SNAPSHOT + 7.6.3 jar classes org.dspace dspace-rest - 7.6.3-SNAPSHOT + 7.6.3 war @@ -1033,69 +1033,69 @@ org.dspace dspace-api - 7.6.3-SNAPSHOT + 7.6.3 org.dspace dspace-api test-jar - 7.6.3-SNAPSHOT + 7.6.3 test org.dspace.modules additions - 7.6.3-SNAPSHOT + 7.6.3 org.dspace dspace-sword - 7.6.3-SNAPSHOT + 7.6.3 org.dspace dspace-swordv2 - 7.6.3-SNAPSHOT + 7.6.3 org.dspace dspace-oai - 7.6.3-SNAPSHOT + 7.6.3 org.dspace dspace-services - 7.6.3-SNAPSHOT + 7.6.3 org.dspace dspace-server-webapp test-jar - 7.6.3-SNAPSHOT + 7.6.3 test org.dspace dspace-rdf - 7.6.3-SNAPSHOT + 7.6.3 org.dspace dspace-iiif - 7.6.3-SNAPSHOT + 7.6.3 org.dspace dspace-server-webapp - 7.6.3-SNAPSHOT + 7.6.3 jar classes org.dspace dspace-server-webapp - 7.6.3-SNAPSHOT + 7.6.3 war @@ -1948,7 +1948,7 @@ scm:git:git@github.com:DSpace/DSpace.git scm:git:git@github.com:DSpace/DSpace.git git@github.com:DSpace/DSpace.git - dspace-7_x + dspace-7.6.3 From 708826c5f4b762ab30adc091b1c6b9a21a143c9c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 7 Feb 2025 11:53:02 -0600 Subject: [PATCH 440/632] [maven-release-plugin] prepare release dspace-8.1 --- dspace-api/pom.xml | 2 +- dspace-iiif/pom.xml | 2 +- dspace-oai/pom.xml | 2 +- dspace-rdf/pom.xml | 2 +- dspace-server-webapp/pom.xml | 2 +- dspace-services/pom.xml | 2 +- dspace-sword/pom.xml | 2 +- dspace-swordv2/pom.xml | 2 +- dspace/modules/additions/pom.xml | 2 +- dspace/modules/pom.xml | 2 +- dspace/modules/server-boot/pom.xml | 2 +- dspace/modules/server/pom.xml | 2 +- dspace/pom.xml | 2 +- pom.xml | 28 ++++++++++++++-------------- 14 files changed, 27 insertions(+), 27 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index acb59fb2d492..487d5cab953f 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -12,7 +12,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index e1d6c4cbfbe4..d1a71e664e65 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 1447fc6e19a0..813c1f594b27 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -8,7 +8,7 @@ dspace-parent org.dspace - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index f8e1bb9e36c4..aeaecf8a9849 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index c8bb82f0ea2e..edc34eafcf92 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -14,7 +14,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 05b490df7610..0b3c3f33da38 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index 48a6392d3dba..0487692a8202 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 2e6b1a27d838..64754b1995ca 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -13,7 +13,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace/modules/additions/pom.xml b/dspace/modules/additions/pom.xml index f658388c3594..49a09d303893 100644 --- a/dspace/modules/additions/pom.xml +++ b/dspace/modules/additions/pom.xml @@ -17,7 +17,7 @@ org.dspace modules - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace/modules/pom.xml b/dspace/modules/pom.xml index c78450137759..8a4684617770 100644 --- a/dspace/modules/pom.xml +++ b/dspace/modules/pom.xml @@ -11,7 +11,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 ../../pom.xml diff --git a/dspace/modules/server-boot/pom.xml b/dspace/modules/server-boot/pom.xml index f2f79bb73869..066378348061 100644 --- a/dspace/modules/server-boot/pom.xml +++ b/dspace/modules/server-boot/pom.xml @@ -11,7 +11,7 @@ modules org.dspace - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index 916689516a1c..5b9eb4d43044 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -7,7 +7,7 @@ modules org.dspace - 8.1-SNAPSHOT + 8.1 .. diff --git a/dspace/pom.xml b/dspace/pom.xml index ef17eb40862d..abb081b32369 100644 --- a/dspace/pom.xml +++ b/dspace/pom.xml @@ -16,7 +16,7 @@ org.dspace dspace-parent - 8.1-SNAPSHOT + 8.1 ../pom.xml diff --git a/pom.xml b/pom.xml index ae8cca4a57a0..7541b2effee2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.dspace dspace-parent pom - 8.1-SNAPSHOT + 8.1 DSpace Parent Project DSpace open source software is a turnkey institutional repository application. @@ -1018,68 +1018,68 @@ org.dspace dspace-api - 8.1-SNAPSHOT + 8.1 org.dspace dspace-api test-jar - 8.1-SNAPSHOT + 8.1 test org.dspace.modules additions - 8.1-SNAPSHOT + 8.1 org.dspace.modules server classes - 8.1-SNAPSHOT + 8.1 org.dspace dspace-sword - 8.1-SNAPSHOT + 8.1 org.dspace dspace-swordv2 - 8.1-SNAPSHOT + 8.1 org.dspace dspace-oai - 8.1-SNAPSHOT + 8.1 org.dspace dspace-services - 8.1-SNAPSHOT + 8.1 org.dspace dspace-server-webapp test-jar - 8.1-SNAPSHOT + 8.1 test org.dspace dspace-rdf - 8.1-SNAPSHOT + 8.1 org.dspace dspace-iiif - 8.1-SNAPSHOT + 8.1 org.dspace dspace-server-webapp - 8.1-SNAPSHOT + 8.1 @@ -1917,7 +1917,7 @@ scm:git:git@github.com:DSpace/DSpace.git scm:git:git@github.com:DSpace/DSpace.git git@github.com:DSpace/DSpace.git - dspace-8_x + dspace-8.1 From 8773da722271f98e1770a8e496db304b0f6143b4 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 7 Feb 2025 11:53:06 -0600 Subject: [PATCH 441/632] [maven-release-plugin] prepare for next development iteration --- dspace-api/pom.xml | 2 +- dspace-iiif/pom.xml | 2 +- dspace-oai/pom.xml | 2 +- dspace-rdf/pom.xml | 2 +- dspace-server-webapp/pom.xml | 2 +- dspace-services/pom.xml | 2 +- dspace-sword/pom.xml | 2 +- dspace-swordv2/pom.xml | 2 +- dspace/modules/additions/pom.xml | 2 +- dspace/modules/pom.xml | 2 +- dspace/modules/server-boot/pom.xml | 2 +- dspace/modules/server/pom.xml | 2 +- dspace/pom.xml | 2 +- pom.xml | 28 ++++++++++++++-------------- 14 files changed, 27 insertions(+), 27 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 487d5cab953f..6c24afee9507 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -12,7 +12,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index d1a71e664e65..71b88d92ca9b 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 813c1f594b27..b824b7396e03 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -8,7 +8,7 @@ dspace-parent org.dspace - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index aeaecf8a9849..4662433d49c1 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index edc34eafcf92..91e83fc40435 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -14,7 +14,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 0b3c3f33da38..973790ec435f 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index 0487692a8202..bdab97fee787 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 64754b1995ca..84e1e412b945 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -13,7 +13,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace/modules/additions/pom.xml b/dspace/modules/additions/pom.xml index 49a09d303893..ec1153e1c9a5 100644 --- a/dspace/modules/additions/pom.xml +++ b/dspace/modules/additions/pom.xml @@ -17,7 +17,7 @@ org.dspace modules - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace/modules/pom.xml b/dspace/modules/pom.xml index 8a4684617770..5394ccd3248a 100644 --- a/dspace/modules/pom.xml +++ b/dspace/modules/pom.xml @@ -11,7 +11,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT ../../pom.xml diff --git a/dspace/modules/server-boot/pom.xml b/dspace/modules/server-boot/pom.xml index 066378348061..9d7251e78e2b 100644 --- a/dspace/modules/server-boot/pom.xml +++ b/dspace/modules/server-boot/pom.xml @@ -11,7 +11,7 @@ modules org.dspace - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index 5b9eb4d43044..35c7f161e91b 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -7,7 +7,7 @@ modules org.dspace - 8.1 + 8.2-SNAPSHOT .. diff --git a/dspace/pom.xml b/dspace/pom.xml index abb081b32369..6690264d7c07 100644 --- a/dspace/pom.xml +++ b/dspace/pom.xml @@ -16,7 +16,7 @@ org.dspace dspace-parent - 8.1 + 8.2-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 7541b2effee2..d115999d9328 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.dspace dspace-parent pom - 8.1 + 8.2-SNAPSHOT DSpace Parent Project DSpace open source software is a turnkey institutional repository application. @@ -1018,68 +1018,68 @@ org.dspace dspace-api - 8.1 + 8.2-SNAPSHOT org.dspace dspace-api test-jar - 8.1 + 8.2-SNAPSHOT test org.dspace.modules additions - 8.1 + 8.2-SNAPSHOT org.dspace.modules server classes - 8.1 + 8.2-SNAPSHOT org.dspace dspace-sword - 8.1 + 8.2-SNAPSHOT org.dspace dspace-swordv2 - 8.1 + 8.2-SNAPSHOT org.dspace dspace-oai - 8.1 + 8.2-SNAPSHOT org.dspace dspace-services - 8.1 + 8.2-SNAPSHOT org.dspace dspace-server-webapp test-jar - 8.1 + 8.2-SNAPSHOT test org.dspace dspace-rdf - 8.1 + 8.2-SNAPSHOT org.dspace dspace-iiif - 8.1 + 8.2-SNAPSHOT org.dspace dspace-server-webapp - 8.1 + 8.2-SNAPSHOT @@ -1917,7 +1917,7 @@ scm:git:git@github.com:DSpace/DSpace.git scm:git:git@github.com:DSpace/DSpace.git git@github.com:DSpace/DSpace.git - dspace-8.1 + dspace-8_x From 56977216a0453a9e16c6f2ae56324024d653b672 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 10 Feb 2025 10:14:36 -0600 Subject: [PATCH 442/632] Remove unused byte-buddy (cherry picked from commit ccfee04f4ac994ed2ee436c73f1c0071d9c46d05) --- pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pom.xml b/pom.xml index 370b61c79c0c..2b0da5fa008b 100644 --- a/pom.xml +++ b/pom.xml @@ -1808,13 +1808,6 @@ jakarta.annotation-api ${jakarta-annotation.version} - - - - net.bytebuddy - byte-buddy - 1.16.1 - From f2243468df9c6e981a262d15d4a3e1d5adc7dd37 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 10 Feb 2025 10:22:42 -0600 Subject: [PATCH 443/632] Remove joda-time and the one place it is used. Fix to use java.time instead (cherry picked from commit d71265d17e3462a11b8d47b65dee702dabcc98e1) --- .../org/dspace/access/status/DefaultAccessStatusHelper.java | 4 ++-- pom.xml | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/access/status/DefaultAccessStatusHelper.java b/dspace-api/src/main/java/org/dspace/access/status/DefaultAccessStatusHelper.java index 5f0e6d8b259b..52cdec3517bc 100644 --- a/dspace-api/src/main/java/org/dspace/access/status/DefaultAccessStatusHelper.java +++ b/dspace-api/src/main/java/org/dspace/access/status/DefaultAccessStatusHelper.java @@ -8,6 +8,7 @@ package org.dspace.access.status; import java.sql.SQLException; +import java.time.Instant; import java.util.Date; import java.util.List; import java.util.Objects; @@ -26,7 +27,6 @@ import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.eperson.Group; -import org.joda.time.LocalDate; /** * Default plugin implementation of the access status helper. @@ -230,7 +230,7 @@ private Date retrieveShortestEmbargo(Context context, Bitstream bitstream) throw // If the policy is not valid there is an active embargo Date startDate = policy.getStartDate(); - if (startDate != null && !startDate.before(LocalDate.now().toDate())) { + if (startDate != null && !startDate.before(Date.from(Instant.now()))) { // There is an active embargo: aim to take the shortest embargo (account for rare cases where // more than one resource policy exists) if (embargoDate == null) { diff --git a/pom.xml b/pom.xml index 2b0da5fa008b..68f848d987db 100644 --- a/pom.xml +++ b/pom.xml @@ -1538,11 +1538,6 @@ commons-validator 1.9.0 - - joda-time - joda-time - 2.13.0 - jakarta.activation jakarta.activation-api From 4f54d582a3afda744d81cdd54bc11b78b478c807 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 23:22:10 +0000 Subject: [PATCH 444/632] Bump com.github.spotbugs:spotbugs in the build-tools group Bumps the build-tools group with 1 update: [com.github.spotbugs:spotbugs](https://github.com/spotbugs/spotbugs). Updates `com.github.spotbugs:spotbugs` from 4.9.0 to 4.9.1 - [Release notes](https://github.com/spotbugs/spotbugs/releases) - [Changelog](https://github.com/spotbugs/spotbugs/blob/master/CHANGELOG.md) - [Commits](https://github.com/spotbugs/spotbugs/compare/4.9.0...4.9.1) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3477e48edd96..d7e0a48509a5 100644 --- a/pom.xml +++ b/pom.xml @@ -313,7 +313,7 @@ com.github.spotbugs spotbugs - 4.9.0 + 4.9.1 From 6ebde005fe76309238124bd9fda874de43a45651 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 23:22:30 +0000 Subject: [PATCH 445/632] Bump commons-logging:commons-logging in the apache-commons group Bumps the apache-commons group with 1 update: commons-logging:commons-logging. Updates `commons-logging:commons-logging` from 1.3.4 to 1.3.5 --- updated-dependencies: - dependency-name: commons-logging:commons-logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3477e48edd96..03a4d1ef6a98 100644 --- a/pom.xml +++ b/pom.xml @@ -1511,7 +1511,7 @@ commons-logging commons-logging - 1.3.4 + 1.3.5 org.apache.commons From d7261481d1d46eaeaca716b8aff77b684c602898 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 23:23:18 +0000 Subject: [PATCH 446/632] Bump tika.version from 2.9.2 to 2.9.3 Bumps `tika.version` from 2.9.2 to 2.9.3. Updates `org.apache.tika:tika-core` from 2.9.2 to 2.9.3 - [Changelog](https://github.com/apache/tika/blob/2.9.3/CHANGES.txt) - [Commits](https://github.com/apache/tika/compare/2.9.2...2.9.3) Updates `org.apache.tika:tika-parsers-standard-package` from 2.9.2 to 2.9.3 --- updated-dependencies: - dependency-name: org.apache.tika:tika-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.tika:tika-parsers-standard-package dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3477e48edd96..a2883f98eac4 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ 2.0.33 1.19.0 2.0.16 - 2.9.2 + 2.9.3 1.80 8.0.1 From 6265c3d45b508c2bc35d5c23c3d7fca40fdf2568 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 11 Feb 2025 10:39:16 -0600 Subject: [PATCH 447/632] Dependency convergence fix --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index a2883f98eac4..7cb9ee80c4e8 100644 --- a/pom.xml +++ b/pom.xml @@ -1312,6 +1312,12 @@ bcutil-jdk18on ${bouncycastle.version} + + + com.healthmarketscience.jackcess + jackcess + 4.0.8 + org.apache.james From 0c0a0d56ffd5b82467298f4d4d80767949efd9b8 Mon Sep 17 00:00:00 2001 From: DSpace Bot <68393067+dspace-bot@users.noreply.github.com> Date: Wed, 12 Feb 2025 07:57:47 -0600 Subject: [PATCH 448/632] [Port dspace-8_x] Fixing Crossref document type issue with new metadata mapping processor (#10401) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * new metadata mapping processor for crossref document type (cherry picked from commit 9ab6b8fce22445da658f90010b00a071d2f4e3a1) * adjust crossref test to consider mapped dc.type to Article (cherry picked from commit 2d15f3ef54fbdc2b320eaf0503bd8ea5b684b4fa) * correcting english (cherry picked from commit d9c8366be08d29c2d7ad46c4c110b2fcbd7ae485) * dspace-api: remove trailing whitespace (cherry picked from commit 175075cf5ee83821468e9cc61404912f06e6b24d) --------- Co-authored-by: Paulo Graça Co-authored-by: Alan Orth --- ...nValueMappingMetadataProcessorService.java | 86 +++++++++++++++++++ ...CrossRefImportMetadataSourceServiceIT.java | 6 +- ...sref-to-dspace-publication-type.properties | 29 +++++++ .../spring/api/crossref-integration.xml | 10 +++ 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/StringJsonValueMappingMetadataProcessorService.java create mode 100644 dspace/config/crosswalks/mapConverter-crossref-to-dspace-publication-type.properties diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/StringJsonValueMappingMetadataProcessorService.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/StringJsonValueMappingMetadataProcessorService.java new file mode 100644 index 000000000000..1a5e50e4ac39 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/transform/StringJsonValueMappingMetadataProcessorService.java @@ -0,0 +1,86 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.importer.external.metadatamapping.transform; + +import static java.util.Optional.ofNullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Optional; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.importer.external.metadatamapping.contributor.JsonPathMetadataProcessor; +import org.dspace.util.SimpleMapConverter; + +/** + * This class is a Metadata processor from a structured JSON Metadata result + * and uses a SimpleMapConverter, with a mapping properties file + * to map to a single string value based on mapped keys.
    + * Like:
    + * journal-article = Article + * + * @author paulo-graca + * + */ +public class StringJsonValueMappingMetadataProcessorService implements JsonPathMetadataProcessor { + + private final static Logger log = LogManager.getLogger(); + /** + * The value map converter. + * a list of values to map from + */ + private SimpleMapConverter valueMapConverter; + private String path; + + @Override + public Collection processMetadata(String json) { + JsonNode rootNode = convertStringJsonToJsonNode(json); + Optional abstractNode = Optional.of(rootNode.at(path)); + Collection values = new ArrayList<>(); + + if (abstractNode.isPresent() && abstractNode.get().getNodeType().equals(JsonNodeType.STRING)) { + + String stringValue = abstractNode.get().asText(); + values.add(ofNullable(stringValue) + .map(value -> valueMapConverter != null ? valueMapConverter.getValue(value) : value) + .orElse(valueMapConverter.getValue(null))); + } + return values; + } + + private JsonNode convertStringJsonToJsonNode(String json) { + ObjectMapper mapper = new ObjectMapper(); + JsonNode body = null; + try { + body = mapper.readTree(json); + } catch (JsonProcessingException e) { + log.error("Unable to process json response.", e); + } + return body; + } + + /* Getters and Setters */ + + public String convertType(String type) { + return valueMapConverter != null ? valueMapConverter.getValue(type) : type; + } + + public void setValueMapConverter(SimpleMapConverter valueMapConverter) { + this.valueMapConverter = valueMapConverter; + } + + public void setPath(String path) { + this.path = path; + } + +} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java index 37bd3a90eeda..f68bfe48db1b 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java @@ -163,7 +163,8 @@ private ArrayList getRecords() { "State of Awareness of Freshers’ Groups Chortkiv State" + " Medical College of Prevention of Iodine Deficiency Diseases"); MetadatumDTO author = createMetadatumDTO("dc", "contributor", "author", "Senyuk, L.V."); - MetadatumDTO type = createMetadatumDTO("dc", "type", null, "journal-article"); + // is expected the dc.type to be mapped from journal-article to Article + MetadatumDTO type = createMetadatumDTO("dc", "type", null, "Article"); MetadatumDTO date = createMetadatumDTO("dc", "date", "issued", "2016-05-19"); MetadatumDTO ispartof = createMetadatumDTO("dc", "relation", "ispartof", "Ukraïnsʹkij žurnal medicini, bìologìï ta sportu"); @@ -192,7 +193,8 @@ private ArrayList getRecords() { MetadatumDTO title2 = createMetadatumDTO("dc", "title", null, "Ischemic Heart Disease and Role of Nurse of Cardiology Department"); MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "Kozak, K. І."); - MetadatumDTO type2 = createMetadatumDTO("dc", "type", null, "journal-article"); + // is expected the dc.type to be mapped from journal-article to Article + MetadatumDTO type2 = createMetadatumDTO("dc", "type", null, "Article"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2016-05-19"); MetadatumDTO ispartof2 = createMetadatumDTO("dc", "relation", "ispartof", "Ukraïnsʹkij žurnal medicini, bìologìï ta sportu"); diff --git a/dspace/config/crosswalks/mapConverter-crossref-to-dspace-publication-type.properties b/dspace/config/crosswalks/mapConverter-crossref-to-dspace-publication-type.properties new file mode 100644 index 000000000000..3bd4468148d6 --- /dev/null +++ b/dspace/config/crosswalks/mapConverter-crossref-to-dspace-publication-type.properties @@ -0,0 +1,29 @@ +# based on Crossref content type at https://crossref.gitlab.io/knowledge_base/docs/topics/content-types/#types-in-cayenne-rest-api +# Mapping between work type supported by Crossref and the DSpace common publication's types +journal-article = Article +journal-issue = Other +journal-volume = Other +journal = Other +proceedings-article = Other +proceedings = Other +dataset = Dataset +component = Other +report = Other +report-series = Other +standard = Other +standard-series = Other +edited-book = Other +monograph = Other +reference-book = Other +book = Book +book-series = Other +book-set = Other +book-chapter = Book chapter +book-section = Other +book-part = Other +book-track = Other +reference-entry = Other +dissertation = Other +posted-content = Other +peer-review = Other +other = Other \ No newline at end of file diff --git a/dspace/config/spring/api/crossref-integration.xml b/dspace/config/spring/api/crossref-integration.xml index 4786c44a7865..6fe9723d796b 100644 --- a/dspace/config/spring/api/crossref-integration.xml +++ b/dspace/config/spring/api/crossref-integration.xml @@ -49,9 +49,19 @@ + + + + + + + + + + From 4c044adcf388a291dced77b53a9b816a6a11659c Mon Sep 17 00:00:00 2001 From: Martin Walk Date: Thu, 13 Feb 2025 14:34:28 +0100 Subject: [PATCH 449/632] Fix #10405 bug in log4j-cli --- dspace/config/log4j2-cli.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dspace/config/log4j2-cli.xml b/dspace/config/log4j2-cli.xml index 73acab877f1f..6cac529978fc 100644 --- a/dspace/config/log4j2-cli.xml +++ b/dspace/config/log4j2-cli.xml @@ -25,6 +25,7 @@ From 474c7d763cd1447ef1215623e32994b2e1dac3be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 22:43:55 +0000 Subject: [PATCH 450/632] Bump com.github.spotbugs:spotbugs-maven-plugin in the build-tools group Bumps the build-tools group with 1 update: [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin). Updates `com.github.spotbugs:spotbugs-maven-plugin` from 4.8.6.6 to 4.9.1.0 - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.8.6.6...spotbugs-maven-plugin-4.9.1.0) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9701c50884b4..2be10fe819b5 100644 --- a/pom.xml +++ b/pom.xml @@ -303,7 +303,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.8.6.6 + 4.9.1.0 Max Low From e4e7fb16d129cd0b56e6e2fcec4730bf68b30cbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 22:44:13 +0000 Subject: [PATCH 451/632] Bump commons-beanutils:commons-beanutils in the apache-commons group Bumps the apache-commons group with 1 update: commons-beanutils:commons-beanutils. Updates `commons-beanutils:commons-beanutils` from 1.10.0 to 1.10.1 --- updated-dependencies: - dependency-name: commons-beanutils:commons-beanutils dependency-type: direct:production update-type: version-update:semver-patch dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9701c50884b4..cc3d6e1433c4 100644 --- a/pom.xml +++ b/pom.xml @@ -1468,7 +1468,7 @@ commons-beanutils commons-beanutils - 1.10.0 + 1.10.1 commons-cli From de85bb4b9358f7b4a9e7f26e4c72462328edb646 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 22:45:37 +0000 Subject: [PATCH 452/632] Bump the spring group with 12 updates Bumps the spring group with 12 updates: | Package | From | To | | --- | --- | --- | | [org.springframework:spring-orm](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-beans](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-aop](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-context-support](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-tx](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-jdbc](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-expression](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | | [org.springframework:spring-test](https://github.com/spring-projects/spring-framework) | `6.2.2` | `6.2.3` | Updates `org.springframework:spring-orm` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-core` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-beans` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-aop` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-context` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-context-support` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-tx` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-jdbc` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-web` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-webmvc` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-expression` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-test` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-core` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-beans` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-aop` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-context` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-context-support` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-tx` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-jdbc` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-web` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-webmvc` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-expression` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) Updates `org.springframework:spring-test` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.2...v6.2.3) --- updated-dependencies: - dependency-name: org.springframework:spring-orm dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9701c50884b4..6e2f7fdb818c 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 17 - 6.2.2 + 6.2.3 3.4.2 6.4.2 6.4.8.Final From 013b0e6b84aaeccf113d8bf56dd9d754800f9044 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 22:45:59 +0000 Subject: [PATCH 453/632] Bump net.minidev:json-smart from 2.5.1 to 2.5.2 Bumps [net.minidev:json-smart](https://github.com/netplex/json-smart-v2) from 2.5.1 to 2.5.2. - [Release notes](https://github.com/netplex/json-smart-v2/releases) - [Commits](https://github.com/netplex/json-smart-v2/compare/2.5.1...2.5.2) --- updated-dependencies: - dependency-name: net.minidev:json-smart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index fdd884cd5c26..4b0e612a7608 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -552,7 +552,7 @@ net.minidev json-smart - 2.5.1 + 2.5.2 From c2b5cd0b88abdf5fb7531dca3f0ad866a291900d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 22:46:41 +0000 Subject: [PATCH 454/632] Bump com.amazonaws:aws-java-sdk-s3 from 1.12.780 to 1.12.781 Bumps [com.amazonaws:aws-java-sdk-s3](https://github.com/aws/aws-sdk-java) from 1.12.780 to 1.12.781. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.780...1.12.781) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-s3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 94270abf4cf9..dda9683e1ebd 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -735,7 +735,7 @@ com.amazonaws aws-java-sdk-s3 - 1.12.780 + 1.12.781 + + diff --git a/dspace/config/ldn/announce-relationship b/dspace/config/ldn/announce-relationship index 205a61adb46c..c9b0cf6c3591 100644 --- a/dspace/config/ldn/announce-relationship +++ b/dspace/config/ldn/announce-relationship @@ -17,7 +17,7 @@ { "@context": [ "https://www.w3.org/ns/activitystreams", - "https://purl.org/coar/notify" + "https://coar-notify.net/" ], "actor": { "id": "${params[0]}", diff --git a/dspace/config/ldn/request-endorsement b/dspace/config/ldn/request-endorsement index 443a7029159f..7c241db9cec2 100644 --- a/dspace/config/ldn/request-endorsement +++ b/dspace/config/ldn/request-endorsement @@ -1,6 +1,6 @@ ## generate LDN message json when request-endorsement of an item ## -## Parameters: {0} config 'dspace.ui.url' +## Parameters: {0} config 'dspace.ui.url' or submitter email id (e.g. 'mailto:submitter-email') depending on the service configuration ## {1} config 'ldn.notify.inbox' ## {2} config 'dspace.name' ## {3} Notify Service url @@ -10,16 +10,18 @@ ## {7} the url to the primary bitstream or the first bitstream in the ORIGINAL bundle if there is no primary bitstream. The url is 'dspace.ui.url'/bitstreams/:uuid/download ## {8} the bitstream MimeType or get User Format MimeType if getFormat is 'Unknown' ## {9} id of the created LDNMessage +## {13} type of actor: Service or Person +## {14} config 'dspace.ui.url' { "@context": [ "https://www.w3.org/ns/activitystreams", - "https://purl.org/coar/notify" + "https://coar-notify.net/" ], "actor": { "id": "${params[0]}", "name": "${params[2]}", - "type": "Service" + "type": "${params[13]}" }, "id": "${params[9]}", "object": { @@ -36,7 +38,7 @@ } }, "origin": { - "id": "${params[0]}", + "id": "${params[14]}", "inbox": "${params[1]}", "type": "Service" }, diff --git a/dspace/config/ldn/request-endorsement-resubmission b/dspace/config/ldn/request-endorsement-resubmission new file mode 100644 index 000000000000..edb6bf151ae5 --- /dev/null +++ b/dspace/config/ldn/request-endorsement-resubmission @@ -0,0 +1,56 @@ +## generate LDN message json when request-endorsement of an item +## +## Parameters: {0} config 'dspace.ui.url' or submitter email id (e.g. 'mailto:submitter-email') depending on the service configuration +## {1} config 'ldn.notify.inbox' +## {2} config 'dspace.name' +## {3} Notify Service url +## {4} Notify Service ldnUrl +## {5} 'dspace.ui.url'/handle/xxxx/yyy +## {6} metadata value of 'dc.identifier.uri' +## {7} the url to the primary bitstream or the first bitstream in the ORIGINAL bundle if there is no primary bitstream. The url is 'dspace.ui.url'/bitstreams/:uuid/download +## {8} the bitstream MimeType or get User Format MimeType if getFormat is 'Unknown' +## {9} id of the created LDNMessage +## {13} type of actor: Service or Person +## {14} config 'dspace.ui.url' +## {15} for endorsement resubmissions the inReplyTo notification URN + +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://coar-notify.net/" + ], + "actor": { + "id": "${params[0]}", + "name": "${params[2]}", + "type": "${params[13]}" + }, + "id": "${params[9]}", + "object": { + "id": "${params[5]}", + "ietf:cite-as": "${params[6]}", + "type": "sorg:AboutPage", + "ietf:item": { + "id": "${params[7]}", + "mediaType": "${params[8]}", + "type": [ + "Article", + "sorg:ScholarlyArticle" + ] + } + }, + ${params[15]} + "origin": { + "id": "${params[14]}", + "inbox": "${params[1]}", + "type": "Service" + }, + "target": { + "id": "${params[3]}", + "inbox": "${params[4]}", + "type": "Service" + }, + "type": [ + "Offer", + "coar-notify:EndorsementAction" + ] +} \ No newline at end of file diff --git a/dspace/config/ldn/request-ingest b/dspace/config/ldn/request-ingest index 701f3929c826..e34072ae0ce6 100644 --- a/dspace/config/ldn/request-ingest +++ b/dspace/config/ldn/request-ingest @@ -14,7 +14,7 @@ { "@context": [ "https://www.w3.org/ns/activitystreams", - "https://purl.org/coar/notify" + "https://coar-notify.net/" ], "actor": { "id": "${params[0]}", diff --git a/dspace/config/ldn/request-review b/dspace/config/ldn/request-review index 01f177b6cc18..1e711c0b7ae9 100644 --- a/dspace/config/ldn/request-review +++ b/dspace/config/ldn/request-review @@ -1,6 +1,6 @@ ## generate LDN message json when request-review of an item ## -## Parameters: {0} config 'dspace.ui.url' +## Parameters: {0} config 'dspace.ui.url' or submitter email id (e.g. 'mailto:submitter-email') depending on the service configuration ## {1} config 'ldn.notify.inbox' ## {2} config 'dspace.name' ## {3} Notify Service url @@ -10,11 +10,12 @@ ## {7} the url to the primary bitstream or the first bitstream in the ORIGINAL bundle if there is no primary bitstream. The url is 'dspace.ui.url'/bitstreams/:uuid/download ## {8} the bitstream MimeType or get User Format MimeType if getFormat is 'Unknown' ## {9} id of the created LDNMessage +## {14} config 'dspace.ui.url' { "@context": [ "https://www.w3.org/ns/activitystreams", - "https://purl.org/coar/notify" + "https://coar-notify.net/" ], "actor": { "id": "${params[0]}", @@ -36,7 +37,7 @@ } }, "origin": { - "id": "${params[0]}", + "id": "${params[14]}", "inbox": "${params[1]}", "type": "Service" }, diff --git a/dspace/config/modules/ldn.cfg b/dspace/config/modules/ldn.cfg index 57f1c878ed35..96d4e39ffc11 100644 --- a/dspace/config/modules/ldn.cfg +++ b/dspace/config/modules/ldn.cfg @@ -25,7 +25,7 @@ ldn.queue.timeout.checker.cron = 0 0 */1 * * ? # LDN Queue extractor elaborates LDN Message entities with max_attempts < than ldn.processor.max.attempts ldn.processor.max.attempts = 5 -# LDN Queue extractor sets LDN Message Entity queue_timeout property every time it tryies a new elaboration +# LDN Queue extractor sets LDN Message Entity queue_timeout property every time it tries a new elaboration # of the message. LDN Message with a future queue_timeout is not elaborated. This property is used to calculateas: # a new timeout, such as: new_timeout = now + ldn.processor.queue.msg.timeout (in minutes) ldn.processor.queue.msg.timeout = 60 @@ -42,5 +42,13 @@ ldn.notify.inbox.block-untrusted-ip = true # EMAIL CONFIGURATION - +# Supported values for actionSendFilter are: +# single email, "GROUP:" or "SUBMITTER" ldn.notification.email = ${mail.admin} +# Review and endorsement notifications may make use of submitter email for requests, as this could be null, +# provide a configurable fallback email option +ldn.notification.email.submitter.fallback = ${mail.admin} +# Review and endorsement notifications may require using an Email Actor ID +# Configure whether the specified service (by service ID) requires using an Email Actor ID +# when sending requests as opposed to a Service URL +# ldn.notification.supportsActorEmailId. = true diff --git a/dspace/config/modules/signposting.cfg b/dspace/config/modules/signposting.cfg index fba80da41481..6acfa74bdd07 100644 --- a/dspace/config/modules/signposting.cfg +++ b/dspace/config/modules/signposting.cfg @@ -32,4 +32,7 @@ signposting.enabled = true signposting.describedby.crosswalk-name = DataCite # Mime-type of response of handling of 'describedby' links. -signposting.describedby.mime-type = application/vnd.datacite.datacite+xml \ No newline at end of file +signposting.describedby.mime-type = application/vnd.datacite.datacite+xml + +# Optional, to expose the profile attribute, required by PCI workflow () +# signposting.describedby.profile = http://datacite.org/schema/kernel-4 \ No newline at end of file diff --git a/dspace/config/spring/api/ldn-coar-notify.xml b/dspace/config/spring/api/ldn-coar-notify.xml index 2329925a5413..ce00d7b30353 100644 --- a/dspace/config/spring/api/ldn-coar-notify.xml +++ b/dspace/config/spring/api/ldn-coar-notify.xml @@ -70,6 +70,15 @@ + + + + TentativeAccept + coar-notify:EndorsementAction + + + + @@ -77,6 +86,15 @@ coar-notify:EndorsementAction + + + + + + Reject + coar-notify:EndorsementAction + + @@ -260,6 +278,18 @@ + + + + + + + + + + + + From 5c19f73bf8c3fe0a3df285c737504ac7f1fdd08a Mon Sep 17 00:00:00 2001 From: Agustina Martinez Date: Wed, 26 Feb 2025 08:59:04 +0000 Subject: [PATCH 457/632] Add integration tests --- .../dspace/app/ldn/LDNMessageConsumer.java | 5 +- .../dspace/app/rest/LDNInboxControllerIT.java | 138 ++++++++++++++++++ .../app/rest/ldn_ack_endorsement_reject.json | 34 +++++ .../app/rest/ldn_ack_review_reject.json | 2 +- 4 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_ack_endorsement_reject.json diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java index d5a756093f6f..58c365557c01 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java @@ -89,6 +89,9 @@ public void consume(Context context, Event event) throws Exception { } Item item = (Item) event.getSubject(context); + if (item == null) { + return; + } createManualLDNMessages(context, item); createAutomaticLDNMessages(context, item); } @@ -190,7 +193,7 @@ private void createLDNMessage(Context context, Item item, NotifyServiceEntity se appendGeneratedMessage(ldn, ldnMessage, actorID, - (actorID != null && item.getSubmitter() != null) ? item.getSubmitter().getFullName() : null, + (actorID != null && item.getSubmitter() != null) ? item.getSubmitter().getName() : null, resubmissionID); ObjectMapper mapper = new ObjectMapper(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java index 78410af2e686..1092f0273f52 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java @@ -26,23 +26,32 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.IOUtils; import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.app.ldn.NotifyPatternToTrigger; import org.dspace.app.ldn.NotifyServiceEntity; import org.dspace.app.ldn.model.Notification; import org.dspace.app.ldn.service.LDNMessageService; +import org.dspace.app.ldn.service.NotifyPatternToTriggerService; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; import org.dspace.builder.NotifyServiceBuilder; +import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; +import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.WorkspaceItemService; import org.dspace.matcher.QASourceMatcher; import org.dspace.matcher.QATopicMatcher; import org.dspace.qaevent.QANotifyPatterns; import org.dspace.qaevent.service.QAEventService; import org.dspace.services.ConfigurationService; import org.dspace.utils.DSpace; +import org.dspace.versioning.Version; +import org.dspace.versioning.service.VersioningService; +import org.dspace.xmlworkflow.service.XmlWorkflowService; import org.junit.After; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -65,6 +74,21 @@ public class LDNInboxControllerIT extends AbstractControllerIntegrationTest { private QAEventService qaEventService = new DSpace().getSingletonService(QAEventService.class); + @Autowired + private XmlWorkflowService workflowService; + + @Autowired + private VersioningService versioningService; + + @Autowired + private InstallItemService installItemService; + + @Autowired + private WorkspaceItemService workspaceItemService; + + @Autowired + private NotifyPatternToTriggerService notifyPatternToTriggerService; + @Test public void ldnInboxAnnounceEndorsementTest() throws Exception { context.turnOffAuthorisationSystem(); @@ -213,6 +237,46 @@ public void ldnInboxOfferReviewAndACKTest() throws Exception { } + @Test + public void ldnInboxOfferReviewAndTentativeRejectTest() throws Exception { + context.turnOffAuthorisationSystem(); + Community community = CommunityBuilder.createCommunity(context).withName("community").build(); + Collection collection = CollectionBuilder.createCollection(context, community).build(); + Item item = ItemBuilder.createItem(context, collection) + .withTitle("Test Item") + .build(); + String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); + NotifyServiceEntity notifyServiceEntity = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") + .withDescription("service description") + .withUrl("https://review-service.com/inbox/about/") + .withLdnUrl("https://review-service.com/inbox/") + .withScore(BigDecimal.valueOf(0.6d)) + .withStatus(true) + .withLowerIp("127.0.0.1") + .withUpperIp("127.0.0.3") + .build(); + InputStream ackReviewStream = getClass().getResourceAsStream("ldn_ack_review_reject.json"); + String ackReview = IOUtils.toString(ackReviewStream, Charset.defaultCharset()); + String ackMessage = ackReview.replaceAll("<>", object); + ackMessage = ackMessage.replaceAll("<>", + "urn:uuid:0370c0fb-bb78-4a9b-87f5-bed307a509da"); + + ObjectMapper mapper = new ObjectMapper(); + Notification notification = mapper.readValue(ackMessage, Notification.class); + getClient() + .perform(post("/ldn/inbox") + .contentType("application/ld+json") + .content(ackMessage)) + .andExpect(status().isAccepted()); + + int processed = ldnMessageService.extractAndProcessMessageFromQueue(context); + assertEquals(processed, 1); + processed = ldnMessageService.extractAndProcessMessageFromQueue(context); + assertEquals(processed, 0); + // check Tentative Reject is correctly received + } + @Test public void ldnInboxAnnounceReleaseTest() throws Exception { context.turnOffAuthorisationSystem(); @@ -387,6 +451,80 @@ public void ldnInboxOutOfRangeIPwithDisabledCheckTest() throws Exception { assertEquals(ldnMessage.getQueueStatus(), LDNMessageEntity.QUEUE_STATUS_UNTRUSTED_IP); } + + @Test + public void testLDNMessageConsumerRequestEndorsementResubmission() throws Exception { + context.turnOffAuthorisationSystem(); + + Community community = CommunityBuilder.createCommunity(context).withName("community").build(); + Collection collection = CollectionBuilder.createCollection(context, community).build(); + NotifyServiceEntity notifyServiceEntity = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") + .withDescription("service description") + .withUrl("https://review-service.com/inbox/about/") + .withLdnUrl("https://review-service.com/inbox/") + .withScore(BigDecimal.valueOf(0.6d)) + .withStatus(true) + .withLowerIp("127.0.0.1") + .withUpperIp("127.0.0.3") + .build(); + WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection) + .withTitle("Submission Item") + .withIssueDate("2023-11-20") + .withFulltext("test.txt", "test", InputStream.nullInputStream()) + .grantLicense() + .withCOARNotifyService(notifyServiceEntity, "request-endorsement") + .build(); + Item item = installItemService.installItem(context, workspaceItem); + + context.commit(); + int processed = ldnMessageService.extractAndProcessMessageFromQueue(context); + assertEquals(processed, 1); + List messages = ldnMessageService.findAll(context); + String notificationId = messages.get(0).getID(); + processed = ldnMessageService.extractAndProcessMessageFromQueue(context); + assertEquals(processed, 0); + + String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); + InputStream ackReviewStream = getClass().getResourceAsStream("ldn_ack_review_reject.json"); + String ackReview = IOUtils.toString(ackReviewStream, Charset.defaultCharset()); + String ackMessage = ackReview.replaceAll("<>", object); + ackMessage = ackMessage.replaceAll("<>", notificationId); + + ObjectMapper mapper = new ObjectMapper(); + Notification notification = mapper.readValue(ackMessage, Notification.class); + getClient() + .perform(post("/ldn/inbox") + .contentType("application/ld+json") + .content(ackMessage)) + .andExpect(status().isAccepted()); + + processed = ldnMessageService.extractAndProcessMessageFromQueue(context); + assertEquals(processed, 1); + processed = ldnMessageService.extractAndProcessMessageFromQueue(context); + assertEquals(processed, 0); + + // We received a first notification for rejectance + + + Version version = versioningService.createNewVersion(context, context.reloadEntity(item)); + WorkspaceItem wsi = workspaceItemService.findByItem(context, version.getItem()); + + NotifyPatternToTrigger notifyPatternToTrigger = notifyPatternToTriggerService.create(context); + notifyPatternToTrigger.setItem(wsi.getItem()); + notifyPatternToTrigger.setNotifyService(notifyServiceEntity); + notifyPatternToTrigger.setPattern("request-endorsement"); + notifyPatternToTriggerService.update(context, notifyPatternToTrigger); + installItemService.installItem(context, wsi); + context.commit(); + + processed = ldnMessageService.extractAndProcessMessageFromQueue(context); + assertEquals(processed, 1); + processed = ldnMessageService.extractAndProcessMessageFromQueue(context); + assertEquals(processed, 0); + + } + private static RequestPostProcessor remoteHost(final String remoteHost, final String remoteAddr) { return request -> { request.setRemoteHost(remoteHost); diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_ack_endorsement_reject.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_ack_endorsement_reject.json new file mode 100644 index 000000000000..6d06ecbce853 --- /dev/null +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_ack_endorsement_reject.json @@ -0,0 +1,34 @@ +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://purl.org/coar/notify" + ], + "actor": { + "id": "https://generic-service.com", + "name": "Generic Service", + "type": "Service" + }, + "context": { + "id": "<>", + "ietf:cite-as": "https://doi.org/10.4598/12123487", + "type": "Document" + }, + "id": "urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4", + "inReplyTo": "<>", + "object": { + "id": "<>", + "object": "https://some-organisation.org/resource/0021", + "type": "Offer" + }, + "origin": { + "id": "https://review-service.com/inbox/about/", + "inbox": "https://review-service.com/inbox/", + "type": "Service" + }, + "target": { + "id": "https://some-organisation.org", + "inbox": "hop", + "type": "Organization" + }, + "type": ["TentativeReject"] +} \ No newline at end of file diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_ack_review_reject.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_ack_review_reject.json index 2ac1f1a15a4a..4323571ec87c 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_ack_review_reject.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_ack_review_reject.json @@ -21,7 +21,7 @@ "type": "Offer" }, "origin": { - "id": "https://generic-service.com/system", + "id": "https://review-service.com/inbox/about/", "inbox": "https://review-service.com/inbox/", "type": "Service" }, From 05a3d30b04798d449f54dcd02960ac3400cebc0f Mon Sep 17 00:00:00 2001 From: Agustina Martinez Date: Thu, 27 Feb 2025 18:18:20 +0000 Subject: [PATCH 458/632] Update LDNMessageConsumer.java Replace getName call with getFullName to retrieve full name rather than email --- .../src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java index 58c365557c01..8698559a5f89 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java @@ -193,7 +193,7 @@ private void createLDNMessage(Context context, Item item, NotifyServiceEntity se appendGeneratedMessage(ldn, ldnMessage, actorID, - (actorID != null && item.getSubmitter() != null) ? item.getSubmitter().getName() : null, + (actorID != null && item.getSubmitter() != null) ? item.getSubmitter().getFullName() : null, resubmissionID); ObjectMapper mapper = new ObjectMapper(); From f74fe75b60d5ec188dc151aae29626e34b9d78f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 22:52:24 +0000 Subject: [PATCH 459/632] Bump slf4j.version from 2.0.16 to 2.0.17 Bumps `slf4j.version` from 2.0.16 to 2.0.17. Updates `org.slf4j:jcl-over-slf4j` from 2.0.16 to 2.0.17 Updates `org.slf4j:slf4j-api` from 2.0.16 to 2.0.17 --- updated-dependencies: - dependency-name: org.slf4j:jcl-over-slf4j dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 155fac66ddb2..8a93c0bf067b 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ 2.24.3 2.0.33 1.19.0 - 2.0.16 + 2.0.17 2.9.3 1.80 From 113553dc620e4bae480b4b392e9744bbc4516db6 Mon Sep 17 00:00:00 2001 From: Toni Prieto Date: Fri, 28 Feb 2025 11:27:36 +0100 Subject: [PATCH 460/632] Use NestableJsonFacet to process browse entries count response (cherry picked from commit 7ba09b7a857f6f3545d88b26940c1089692a860a) --- .../java/org/dspace/discovery/SolrServiceImpl.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 75f0a0ac4d05..a493edad310b 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -41,6 +41,8 @@ import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.response.FacetField; import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.client.solrj.response.json.BucketBasedJsonFacet; +import org.apache.solr.client.solrj.response.json.NestableJsonFacet; import org.apache.solr.client.solrj.util.ClientUtils; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; @@ -1105,13 +1107,11 @@ protected DiscoverResult retrieveResult(Context context, DiscoverQuery query) */ private void resolveEntriesCount(DiscoverResult result, QueryResponse solrQueryResponse) { - Object facetsObj = solrQueryResponse.getResponse().get("facets"); - if (facetsObj instanceof NamedList) { - NamedList facets = (NamedList) facetsObj; - Object bucketsInfoObj = facets.get("entries_count"); - if (bucketsInfoObj instanceof NamedList) { - NamedList bucketsInfo = (NamedList) bucketsInfoObj; - result.setTotalEntries((int) bucketsInfo.get("numBuckets")); + NestableJsonFacet response = solrQueryResponse.getJsonFacetingResponse(); + if (response != null) { + BucketBasedJsonFacet facet = response.getBucketBasedFacets("entries_count"); + if (facet != null) { + result.setTotalEntries(facet.getNumBucketsCount()); } } } From d77982683dce105f96990f4715397da2077f31db Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 11 Mar 2025 14:37:32 +0100 Subject: [PATCH 461/632] #10476: Fix debug port conflicts in Dockerfile test env Reset JAVA_TOOL_OPTIONS in the launcher Include commented example of CLI debugging in launcher (cherry picked from commit 1dcb880e00256fb6251d6c8d92907819f0fd7b5f) --- dspace/bin/dspace | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dspace/bin/dspace b/dspace/bin/dspace index 24644aae9112..05d0ec2d2376 100644 --- a/dspace/bin/dspace +++ b/dspace/bin/dspace @@ -33,7 +33,14 @@ if [ "$1" = "classpath" ]; then exit 0 fi -#Allow user to specify java options through JAVA_OPTS variable +# Reset JAVA_TOOL_OPTIONS to empty, so that any debug ports don't conflict +JAVA_TOOL_OPTIONS="" +# Note, if you wish to also debug the CLI launcher, the following line is an +# example of how to do so - note the different port number and 'suspend=y' which +# means the JVM will not begin execution until a debugger is attached. +#JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:1043" + +# Allow user to specify java options through JAVA_OPTS variable if [ "$JAVA_OPTS" = "" ]; then #Default Java to use 256MB of memory JAVA_OPTS="-Xmx256m -Dfile.encoding=UTF-8" From 08be12a9329a2dfcb844806d0225d2992887e08e Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 11 Mar 2025 16:02:28 +0100 Subject: [PATCH 462/632] #10476: Fix debug port conflicts in Dockerfile test env Unset JAVA_TOOL_OPTIONS rather than overwriting (cherry picked from commit f93e498f9b7a7509c508a2739fd32ede335c4884) --- dspace/bin/dspace | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/bin/dspace b/dspace/bin/dspace index 05d0ec2d2376..ca9832fe2b2f 100644 --- a/dspace/bin/dspace +++ b/dspace/bin/dspace @@ -33,8 +33,8 @@ if [ "$1" = "classpath" ]; then exit 0 fi -# Reset JAVA_TOOL_OPTIONS to empty, so that any debug ports don't conflict -JAVA_TOOL_OPTIONS="" +# Unset JAVA_TOOL_OPTIONS (exported by Dockerfile) so that any debug ports don't conflict +unset JAVA_TOOL_OPTIONS # Note, if you wish to also debug the CLI launcher, the following line is an # example of how to do so - note the different port number and 'suspend=y' which # means the JVM will not begin execution until a debugger is attached. From 0cb255ca7cd891d672dabd53b91041999c496189 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 23:20:36 +0000 Subject: [PATCH 463/632] Bump the spring group across 1 directory with 24 updates Bumps the spring group with 24 updates in the / directory: | Package | From | To | | --- | --- | --- | | [org.springframework:spring-orm](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-beans](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-aop](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-context-support](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-tx](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-jdbc](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-expression](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework:spring-test](https://github.com/spring-projects/spring-framework) | `6.2.3` | `6.2.4` | | [org.springframework.boot:spring-boot-starter-test](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter-tomcat](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-maven-plugin](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter-cache](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter-web](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter-data-rest](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter-security](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter-aop](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter-actuator](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.boot:spring-boot-starter-log4j2](https://github.com/spring-projects/spring-boot) | `3.4.2` | `3.4.3` | | [org.springframework.security:spring-security-test](https://github.com/spring-projects/spring-security) | `6.4.2` | `6.4.4` | Updates `org.springframework:spring-orm` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-core` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-beans` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-aop` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-context` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-context-support` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-tx` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-jdbc` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-web` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-webmvc` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-expression` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-test` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-core` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-beans` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-aop` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-context` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-context-support` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-tx` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-jdbc` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-web` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-webmvc` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-expression` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework:spring-test` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.3...v6.2.4) Updates `org.springframework.boot:spring-boot-starter-test` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.security:spring-security-test` from 6.4.2 to 6.4.4 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/6.4.2...6.4.4) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.2 to 3.4.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) --- updated-dependencies: - dependency-name: org.springframework:spring-orm dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 155fac66ddb2..4907e7a12ee6 100644 --- a/pom.xml +++ b/pom.xml @@ -19,9 +19,9 @@ 17 - 6.2.3 - 3.4.2 - 6.4.2 + 6.2.4 + 3.4.3 + 6.4.4 6.4.8.Final 8.0.1.Final 42.7.5 From 705f71f36988868d19d1da1951bcfb582ddb3e2f Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 21 Mar 2025 14:20:07 +0100 Subject: [PATCH 464/632] add missing whitespace in exception message (cherry picked from commit 9a904ab4c93775257f1e17d3bd3991e6c7257754) --- .../java/org/dspace/discovery/utils/DiscoverQueryBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/utils/DiscoverQueryBuilder.java b/dspace-api/src/main/java/org/dspace/discovery/utils/DiscoverQueryBuilder.java index 92a973dff883..b816e222539a 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/utils/DiscoverQueryBuilder.java +++ b/dspace-api/src/main/java/org/dspace/discovery/utils/DiscoverQueryBuilder.java @@ -302,7 +302,7 @@ private void configureSorting(String sortProperty, String sortDirection, Discove if (StringUtils.isNotBlank(sortBy) && !isConfigured(sortBy, searchSortConfiguration)) { throw new SearchServiceException( - "The field: " + sortBy + "is not configured for the configuration!"); + "The field: " + sortBy + " is not configured for the configuration!"); } From 21df5d0f38552e3325d2d75b335ce0e6d1e7c29f Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 21 Mar 2025 14:34:04 +0100 Subject: [PATCH 465/632] add missing whitespace (cherry picked from commit 4ea49580937e60978035daf76b22588e3b979215) --- .../src/main/java/org/dspace/app/util/DCInputsReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java index 8dc8239ca507..c77c3bf10e08 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java @@ -379,7 +379,7 @@ private void processRow(String formName, int rowIdx, Node n, List Date: Fri, 21 Mar 2025 19:01:09 +0000 Subject: [PATCH 466/632] Add bitstream null check to XOAI (cherry picked from commit 54602f47b1d35a7cb75b28acde08d43a93461e8a) --- dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java index 5c29b259deab..c8babc036e3c 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java @@ -110,7 +110,7 @@ private List getFileFormats(Item item) { try { for (Bundle b : itemService.getBundles(item, "ORIGINAL")) { for (Bitstream bs : b.getBitstreams()) { - if (!formats.contains(bs.getFormat(context).getMIMEType())) { + if (bs != null && !formats.contains(bs.getFormat(context).getMIMEType())) { formats.add(bs.getFormat(context).getMIMEType()); } } From f0abeea477b0740bae704c535757f53bf22626da Mon Sep 17 00:00:00 2001 From: DSpace Bot <68393067+dspace-bot@users.noreply.github.com> Date: Mon, 24 Mar 2025 14:03:50 -0500 Subject: [PATCH 467/632] [Port dspace-8_x] Add null check in SolrServiceFileInfoPlugin for index-discovery (#10518) * Add null check in SolrServiceFileInfoPlugin for index-discovery (cherry picked from commit d07f1e0caad7632231a7a98cf2f2ff119d6a3b89) * Fix starting curly brace. (cherry picked from commit e11994c0ee75baf7389446e67ca8252f5f16a8d2) * Update SolrServiceFileInfoPlugin.java (cherry picked from commit 18372ae07246c5b0829286f7bb20263017528518) --------- Co-authored-by: jameswsullivan <81947235+jameswsullivan@users.noreply.github.com> --- .../discovery/SolrServiceFileInfoPlugin.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java index 7aece5acf313..6142dd0dba4b 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java @@ -52,21 +52,23 @@ public void additionalIndex(Context context, IndexableObject indexableObject, So List bitstreams = bundle.getBitstreams(); if (bitstreams != null) { for (Bitstream bitstream : bitstreams) { - document.addField(SOLR_FIELD_NAME_FOR_FILENAMES, bitstream.getName()); - // Add _keyword and _filter fields which are necessary to support filtering and faceting - // for the file names - document.addField(SOLR_FIELD_NAME_FOR_FILENAMES + "_keyword", bitstream.getName()); - document.addField(SOLR_FIELD_NAME_FOR_FILENAMES + "_filter", bitstream.getName()); + if (bitstream != null) { + document.addField(SOLR_FIELD_NAME_FOR_FILENAMES, bitstream.getName()); + // Add _keyword and _filter fields which are necessary to + // support filtering and faceting for the file names + document.addField(SOLR_FIELD_NAME_FOR_FILENAMES + "_keyword", bitstream.getName()); + document.addField(SOLR_FIELD_NAME_FOR_FILENAMES + "_filter", bitstream.getName()); - String description = bitstream.getDescription(); - if ((description != null) && !description.isEmpty()) { - document.addField(SOLR_FIELD_NAME_FOR_DESCRIPTIONS, description); - // Add _keyword and _filter fields which are necessary to support filtering and - // faceting for the descriptions - document.addField(SOLR_FIELD_NAME_FOR_DESCRIPTIONS + "_keyword", - description); - document.addField(SOLR_FIELD_NAME_FOR_DESCRIPTIONS + "_filter", - description); + String description = bitstream.getDescription(); + if ((description != null) && !description.isEmpty()) { + document.addField(SOLR_FIELD_NAME_FOR_DESCRIPTIONS, description); + // Add _keyword and _filter fields which are necessary to support filtering and + // faceting for the descriptions + document.addField(SOLR_FIELD_NAME_FOR_DESCRIPTIONS + "_keyword", + description); + document.addField(SOLR_FIELD_NAME_FOR_DESCRIPTIONS + "_filter", + description); + } } } } From 867efc951dbcf5e4b442518a3ac75a44e0b3ad51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Mar 2025 22:55:01 +0000 Subject: [PATCH 468/632] Bump org.apache.httpcomponents.client5:httpclient5 from 5.4.2 to 5.4.3 Bumps [org.apache.httpcomponents.client5:httpclient5](https://github.com/apache/httpcomponents-client) from 5.4.2 to 5.4.3. - [Changelog](https://github.com/apache/httpcomponents-client/blob/rel/v5.4.3/RELEASE_NOTES.txt) - [Commits](https://github.com/apache/httpcomponents-client/compare/rel/v5.4.2...rel/v5.4.3) --- updated-dependencies: - dependency-name: org.apache.httpcomponents.client5:httpclient5 dependency-version: 5.4.3 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 4b0e612a7608..4b92e9f40170 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -590,7 +590,7 @@ org.apache.httpcomponents.client5 httpclient5 - 5.4.2 + 5.4.3 test From 8e2dc93cc8e6fc371768ea8518397160398e7cac Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Mon, 7 Oct 2024 11:42:35 +0200 Subject: [PATCH 469/632] More robust ORCID accessToken init, REST con. usage * Ensure that http client / IO exceptions don't cause a total DSpace startup failure because of unhandled exceptions in Spring service init methods. * Centralise access token retrieval method in factory utils. * Check for NULL rest connector since that can now happen and handle gracefully, with error logging (cherry picked from commit b72344ecfbdd85ce1cb98bfe0ee0d76ebd9439e6) --- .../orcid/Orcidv3SolrAuthorityImpl.java | 93 +++++++++---------- .../impl/OrcidV3AuthorDataProvider.java | 83 +++++++++-------- .../model/factory/OrcidFactoryUtils.java | 55 +++++++++++ .../org/dspace/authority/orcid/MockOrcid.java | 17 +++- 4 files changed, 157 insertions(+), 91 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authority/orcid/Orcidv3SolrAuthorityImpl.java b/dspace-api/src/main/java/org/dspace/authority/orcid/Orcidv3SolrAuthorityImpl.java index 6753a5d113b7..494daa97734a 100644 --- a/dspace-api/src/main/java/org/dspace/authority/orcid/Orcidv3SolrAuthorityImpl.java +++ b/dspace-api/src/main/java/org/dspace/authority/orcid/Orcidv3SolrAuthorityImpl.java @@ -7,27 +7,22 @@ */ package org.dspace.authority.orcid; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.net.URLEncoder; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.HttpClientBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.authority.AuthorityValue; import org.dspace.authority.SolrAuthorityInterface; import org.dspace.external.OrcidRestConnector; import org.dspace.external.provider.orcid.xml.XMLtoBio; -import org.json.JSONObject; +import org.dspace.orcid.model.factory.OrcidFactoryUtils; import org.orcid.jaxb.model.v3.release.common.OrcidIdentifier; import org.orcid.jaxb.model.v3.release.record.Person; import org.orcid.jaxb.model.v3.release.search.Result; @@ -50,6 +45,11 @@ public class Orcidv3SolrAuthorityImpl implements SolrAuthorityInterface { private String accessToken; + /** + * Maximum retries to allow for the access token retrieval + */ + private int maxClientRetries = 3; + public void setOAUTHUrl(String oAUTHUrl) { OAUTHUrl = oAUTHUrl; } @@ -62,46 +62,32 @@ public void setClientSecret(String clientSecret) { this.clientSecret = clientSecret; } + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + /** * Initialize the accessToken that is required for all subsequent calls to ORCID */ public void init() { - if (StringUtils.isBlank(accessToken) - && StringUtils.isNotBlank(clientSecret) - && StringUtils.isNotBlank(clientId) - && StringUtils.isNotBlank(OAUTHUrl)) { - String authenticationParameters = "?client_id=" + clientId + - "&client_secret=" + clientSecret + - "&scope=/read-public&grant_type=client_credentials"; - try { - HttpPost httpPost = new HttpPost(OAUTHUrl + authenticationParameters); - httpPost.addHeader("Accept", "application/json"); - httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); - - HttpClient httpClient = HttpClientBuilder.create().build(); - HttpResponse getResponse = httpClient.execute(httpPost); - - JSONObject responseObject = null; - try (InputStream is = getResponse.getEntity().getContent(); - BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, "UTF-8"))) { - String inputStr; - while ((inputStr = streamReader.readLine()) != null && responseObject == null) { - if (inputStr.startsWith("{") && inputStr.endsWith("}") && inputStr.contains("access_token")) { - try { - responseObject = new JSONObject(inputStr); - } catch (Exception e) { - //Not as valid as I'd hoped, move along - responseObject = null; - } - } - } - } - if (responseObject != null && responseObject.has("access_token")) { - accessToken = (String) responseObject.get("access_token"); - } - } catch (Exception e) { - throw new RuntimeException("Error during initialization of the Orcid connector", e); - } + // Initialize access token at spring instantiation. If it fails, the access token will be null rather + // than causing a fatal Spring startup error + initializeAccessToken(); + } + + public void initializeAccessToken() { + // If we have reaches max retries or the access token is already set, return immediately + if (maxClientRetries <= 0 || org.apache.commons.lang3.StringUtils.isNotBlank(accessToken)) { + return; + } + try { + accessToken = OrcidFactoryUtils.retrieveAccessToken(clientId, clientSecret, OAUTHUrl).orElse(null); + } catch (IOException e) { + log.error("Error retrieving ORCID access token, {} retries left", --maxClientRetries); } } @@ -116,7 +102,7 @@ public void setOrcidRestConnector(OrcidRestConnector orcidRestConnector) { */ @Override public List queryAuthorities(String text, int max) { - init(); + initializeAccessToken(); List bios = queryBio(text, max); List result = new ArrayList<>(); for (Person person : bios) { @@ -135,7 +121,7 @@ public List queryAuthorities(String text, int max) { */ @Override public AuthorityValue queryAuthorityID(String id) { - init(); + initializeAccessToken(); Person person = getBio(id); AuthorityValue valueFromPerson = Orcidv3AuthorityValue.create(person); return valueFromPerson; @@ -151,11 +137,14 @@ public Person getBio(String id) { if (!isValid(id)) { return null; } - init(); + if (orcidRestConnector == null) { + log.error("ORCID REST connector is null, returning null Person"); + return null; + } + initializeAccessToken(); InputStream bioDocument = orcidRestConnector.get(id + ((id.endsWith("/person")) ? "" : "/person"), accessToken); XMLtoBio converter = new XMLtoBio(); - Person person = converter.convertSinglePerson(bioDocument); - return person; + return converter.convertSinglePerson(bioDocument); } @@ -167,10 +156,16 @@ public Person getBio(String id) { * @return List */ public List queryBio(String text, int start, int rows) { - init(); if (rows > 100) { throw new IllegalArgumentException("The maximum number of results to retrieve cannot exceed 100."); } + // Check REST connector is initialized + if (orcidRestConnector == null) { + log.error("ORCID REST connector is not initialized, returning empty list"); + return Collections.emptyList(); + } + // Check / init access token + initializeAccessToken(); String searchPath = "search?q=" + URLEncoder.encode(text) + "&start=" + start + "&rows=" + rows; log.debug("queryBio searchPath=" + searchPath + " accessToken=" + accessToken); diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java index 125da8f7c67b..c7e41171a5bb 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java @@ -7,24 +7,17 @@ */ package org.dspace.external.provider.impl; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.HttpClientBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.content.dto.MetadataValueDTO; @@ -32,7 +25,7 @@ import org.dspace.external.model.ExternalDataObject; import org.dspace.external.provider.AbstractExternalDataProvider; import org.dspace.external.provider.orcid.xml.XMLtoBio; -import org.json.JSONObject; +import org.dspace.orcid.model.factory.OrcidFactoryUtils; import org.orcid.jaxb.model.v3.release.common.OrcidIdentifier; import org.orcid.jaxb.model.v3.release.record.Person; import org.orcid.jaxb.model.v3.release.search.Result; @@ -60,6 +53,11 @@ public class OrcidV3AuthorDataProvider extends AbstractExternalDataProvider { private XMLtoBio converter; + /** + * Maximum retries to allow for the access token retrieval + */ + private int maxClientRetries = 3; + public static final String ORCID_ID_SYNTAX = "\\d{4}-\\d{4}-\\d{4}-(\\d{3}X|\\d{4})"; private static final int MAX_INDEX = 10000; @@ -78,47 +76,37 @@ public OrcidV3AuthorDataProvider() { * @throws java.io.IOException passed through from HTTPclient. */ public void init() throws IOException { - if (StringUtils.isNotBlank(clientSecret) && StringUtils.isNotBlank(clientId) - && StringUtils.isNotBlank(OAUTHUrl)) { - String authenticationParameters = "?client_id=" + clientId + - "&client_secret=" + clientSecret + - "&scope=/read-public&grant_type=client_credentials"; - HttpPost httpPost = new HttpPost(OAUTHUrl + authenticationParameters); - httpPost.addHeader("Accept", "application/json"); - httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); - - HttpClient httpClient = HttpClientBuilder.create().build(); - HttpResponse getResponse = httpClient.execute(httpPost); - - JSONObject responseObject = null; - try (InputStream is = getResponse.getEntity().getContent(); - BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, "UTF-8"))) { - String inputStr; - while ((inputStr = streamReader.readLine()) != null && responseObject == null) { - if (inputStr.startsWith("{") && inputStr.endsWith("}") && inputStr.contains("access_token")) { - try { - responseObject = new JSONObject(inputStr); - } catch (Exception e) { - //Not as valid as I'd hoped, move along - responseObject = null; - } - } - } - } - if (responseObject != null && responseObject.has("access_token")) { - accessToken = (String) responseObject.get("access_token"); - } + // Initialize access token at spring instantiation. If it fails, the access token will be null rather + // than causing a fatal Spring startup error + initializeAccessToken(); + } + + /** + * Initialize access token, logging an error and decrementing remaining retries if an IOException is thrown. + * If the optional access token result is empty, set to null instead. + */ + public void initializeAccessToken() { + // If we have reaches max retries or the access token is already set, return immediately + if (maxClientRetries <= 0 || StringUtils.isNotBlank(accessToken)) { + return; + } + try { + accessToken = OrcidFactoryUtils.retrieveAccessToken(clientId, clientSecret, OAUTHUrl).orElse(null); + } catch (IOException e) { + log.error("Error retrieving ORCID access token, {} retries left", --maxClientRetries); } } @Override public Optional getExternalDataObject(String id) { + initializeAccessToken(); Person person = getBio(id); ExternalDataObject externalDataObject = convertToExternalDataObject(person); return Optional.of(externalDataObject); } protected ExternalDataObject convertToExternalDataObject(Person person) { + initializeAccessToken(); ExternalDataObject externalDataObject = new ExternalDataObject(sourceIdentifier); if (person.getName() != null) { String lastName = ""; @@ -167,6 +155,11 @@ public Person getBio(String id) { if (!isValid(id)) { return null; } + if (orcidRestConnector == null) { + log.error("ORCID REST connector is null, returning null ORCID Person Bio"); + return null; + } + initializeAccessToken(); InputStream bioDocument = orcidRestConnector.get(id + ((id.endsWith("/person")) ? "" : "/person"), accessToken); Person person = converter.convertSinglePerson(bioDocument); try { @@ -188,12 +181,18 @@ private boolean isValid(String text) { @Override public List searchExternalDataObjects(String query, int start, int limit) { + initializeAccessToken(); if (limit > 100) { throw new IllegalArgumentException("The maximum number of results to retrieve cannot exceed 100."); } if (start > MAX_INDEX) { throw new IllegalArgumentException("The starting number of results to retrieve cannot exceed 10000."); } + // Check REST connector is initialized + if (orcidRestConnector == null) { + log.error("ORCID REST connector is not initialized, returning empty list"); + return Collections.emptyList(); + } String searchPath = "search?q=" + URLEncoder.encode(query, StandardCharsets.UTF_8) + "&start=" + start @@ -218,9 +217,6 @@ public List searchExternalDataObjects(String query, int star } catch (IOException e) { log.error(e.getMessage(), e); } - if (Objects.isNull(bios)) { - return Collections.emptyList(); - } return bios.stream().map(bio -> convertToExternalDataObject(bio)).collect(Collectors.toList()); } @@ -231,6 +227,11 @@ public boolean supports(String source) { @Override public int getNumberOfResults(String query) { + if (orcidRestConnector == null) { + log.error("ORCID REST connector is null, returning 0"); + return 0; + } + initializeAccessToken(); String searchPath = "search?q=" + URLEncoder.encode(query, StandardCharsets.UTF_8) + "&start=" + 0 + "&rows=" + 0; diff --git a/dspace-api/src/main/java/org/dspace/orcid/model/factory/OrcidFactoryUtils.java b/dspace-api/src/main/java/org/dspace/orcid/model/factory/OrcidFactoryUtils.java index 4b8c1178efeb..38aa611ff3a0 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/model/factory/OrcidFactoryUtils.java +++ b/dspace-api/src/main/java/org/dspace/orcid/model/factory/OrcidFactoryUtils.java @@ -7,10 +7,21 @@ */ package org.dspace.orcid.model.factory; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.json.JSONObject; /** * Utility class for Orcid factory classes. This is used to parse the @@ -65,4 +76,48 @@ private static String[] parseConfiguration(String configuration) { return configurations; } + /** + * Retrieve access token from ORCID, given a client ID, client secret and OAuth URL + * + * @param clientId ORCID client ID + * @param clientSecret ORCID client secret + * @param oauthUrl ORCID oauth redirect URL + * @return response object as Optional string + * @throws IOException if any errors are encountered making the connection or reading a response + */ + public static Optional retrieveAccessToken(String clientId, String clientSecret, String oauthUrl) + throws IOException { + if (StringUtils.isNotBlank(clientSecret) && StringUtils.isNotBlank(clientId) + && StringUtils.isNotBlank(oauthUrl)) { + String authenticationParameters = "?client_id=" + clientId + + "&client_secret=" + clientSecret + + "&scope=/read-public&grant_type=client_credentials"; + HttpPost httpPost = new HttpPost(oauthUrl + authenticationParameters); + httpPost.addHeader("Accept", "application/json"); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); + + HttpResponse response; + try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { + response = httpClient.execute(httpPost); + } + JSONObject responseObject = null; + if (response != null && response.getStatusLine().getStatusCode() == 200) { + try (InputStream is = response.getEntity().getContent(); + BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, + StandardCharsets.UTF_8))) { + String inputStr; + while ((inputStr = streamReader.readLine()) != null && responseObject == null) { + if (inputStr.startsWith("{") && inputStr.endsWith("}") && inputStr.contains("access_token")) { + responseObject = new JSONObject(inputStr); + } + } + } + } + if (responseObject != null && responseObject.has("access_token")) { + return Optional.of((String) responseObject.get("access_token")); + } + } + // Return empty by default + return Optional.empty(); + } } diff --git a/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java b/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java index 562aa86a585e..82dc3fa5cc12 100644 --- a/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java +++ b/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java @@ -26,8 +26,24 @@ */ public class MockOrcid extends Orcidv3SolrAuthorityImpl { + public MockOrcid() { + setupMockConnector(); + setAccessToken("mock-access-token"); + } + @Override public void init() { + // Empty implementation as setup is now done in constructor + } + + @Override + public void initializeAccessToken() { + if (getAccessToken() == null) { + setAccessToken("mock-access-token"); + } + } + + private void setupMockConnector() { OrcidRestConnector orcidRestConnector = Mockito.mock(OrcidRestConnector.class); when(orcidRestConnector.get(ArgumentMatchers.startsWith("search?"), ArgumentMatchers.any())) .thenAnswer(new Answer() { @@ -53,5 +69,4 @@ public InputStream answer(InvocationOnMock invocation) { setOrcidRestConnector(orcidRestConnector); } - } From d9ee07ba4d76c0b8957fd9d23b174538b4afea98 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Sun, 30 Mar 2025 22:30:25 +0200 Subject: [PATCH 470/632] Fix some ORCID mock / test usage (cherry picked from commit 038ddeee9795c75b876ce1ea73db2b908a8c939c) --- .../spring/api/orcid-authority-services.xml | 2 +- .../org/dspace/authority/orcid/MockOrcid.java | 57 ++++++++++++------- .../app/rest/VocabularyRestRepositoryIT.java | 14 +++++ 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/orcid-authority-services.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/orcid-authority-services.xml index 4a73b215cd4b..3e38055b678a 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/orcid-authority-services.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/orcid-authority-services.xml @@ -16,7 +16,7 @@ - + diff --git a/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java b/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java index 82dc3fa5cc12..511df79f1e50 100644 --- a/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java +++ b/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java @@ -26,41 +26,47 @@ */ public class MockOrcid extends Orcidv3SolrAuthorityImpl { - public MockOrcid() { - setupMockConnector(); - setAccessToken("mock-access-token"); - } + OrcidRestConnector orcidRestConnector; @Override public void init() { - // Empty implementation as setup is now done in constructor + initializeAccessToken(); + orcidRestConnector = Mockito.mock(OrcidRestConnector.class); } - @Override - public void initializeAccessToken() { - if (getAccessToken() == null) { - setAccessToken("mock-access-token"); - } - } - - private void setupMockConnector() { - OrcidRestConnector orcidRestConnector = Mockito.mock(OrcidRestConnector.class); + /** + * Call this to set up mocking for any test classes that need it. We don't set it in init() + * or other AbstractIntegrationTest implementations will complain of unnecessary Mockito stubbing + */ + public void setupNoResultsSearch() { when(orcidRestConnector.get(ArgumentMatchers.startsWith("search?"), ArgumentMatchers.any())) - .thenAnswer(new Answer() { - @Override - public InputStream answer(InvocationOnMock invocation) { - return this.getClass().getResourceAsStream("orcid-search-noresults.xml"); - } - }); + .thenAnswer(new Answer() { + @Override + public InputStream answer(InvocationOnMock invocation) { + return this.getClass().getResourceAsStream("orcid-search-noresults.xml"); + } + }); + } + /** + * Call this to set up mocking for any test classes that need it. We don't set it in init() + * or other AbstractIntegrationTest implementations will complain of unnecessary Mockito stubbing + */ + public void setupSingleSearch() { when(orcidRestConnector.get(ArgumentMatchers.startsWith("search?q=Bollini"), ArgumentMatchers.any())) - .thenAnswer(new Answer() { + .thenAnswer(new Answer() { @Override public InputStream answer(InvocationOnMock invocation) { return this.getClass().getResourceAsStream("orcid-search.xml"); } }); + } + /** + * Call this to set up mocking for any test classes that need it. We don't set it in init() + * or other AbstractIntegrationTest implementations will complain of unnecessary Mockito stubbing + */ + public void setupSearchWithResults() { when(orcidRestConnector.get(ArgumentMatchers.endsWith("/person"), ArgumentMatchers.any())) - .thenAnswer(new Answer() { + .thenAnswer(new Answer() { @Override public InputStream answer(InvocationOnMock invocation) { return this.getClass().getResourceAsStream("orcid-person-record.xml"); @@ -69,4 +75,11 @@ public InputStream answer(InvocationOnMock invocation) { setOrcidRestConnector(orcidRestConnector); } + + @Override + public void initializeAccessToken() { + if (getAccessToken() == null) { + setAccessToken("mock-access-token"); + } + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/VocabularyRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/VocabularyRestRepositoryIT.java index 30890d7ef838..7a3bc738eb66 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/VocabularyRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/VocabularyRestRepositoryIT.java @@ -22,6 +22,7 @@ import org.dspace.authority.AuthorityValueServiceImpl; import org.dspace.authority.PersonAuthorityValue; import org.dspace.authority.factory.AuthorityServiceFactory; +import org.dspace.authority.orcid.MockOrcid; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.content.Collection; @@ -29,11 +30,13 @@ import org.dspace.content.authority.service.ChoiceAuthorityService; import org.dspace.core.service.PluginService; import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; /** * This class handles all Authority related IT. It alters some config to run the tests, but it gets cleared again @@ -56,6 +59,17 @@ public class VocabularyRestRepositoryIT extends AbstractControllerIntegrationTes @Before public void setup() throws Exception { super.setUp(); + + // Explicitly set stubbing for the MockOrcid class. We don't do it in the init() or constructor + // of the MockOrcid class itself or Mockito will complain of unnecessary stubbing in certain other + // AbstractIntegrationTest implementations (depending on how config is (re)loaded) + ApplicationContext applicationContext = DSpaceServicesFactory.getInstance() + .getServiceManager().getApplicationContext(); + MockOrcid mockOrcid = applicationContext.getBean(MockOrcid.class); + mockOrcid.setupNoResultsSearch(); + mockOrcid.setupSingleSearch(); + mockOrcid.setupSearchWithResults(); + configurationService.setProperty("plugin.named.org.dspace.content.authority.ChoiceAuthority", new String[] { "org.dspace.content.authority.SolrAuthority = SolrAuthorAuthority", From 70017e1c8e8c07d1673883db1f777d7d0d27312f Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 11 Mar 2025 10:58:08 +0100 Subject: [PATCH 471/632] Implement a SEOHealthIndicator which verifies all relevant parameters for SEO are ok (cherry picked from commit 4bd8a24ca75f6d2e6384e850b45c96c4f1229f02) --- .../configuration/ActuatorConfiguration.java | 7 ++ .../app/rest/health/SEOHealthIndicator.java | 77 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/configuration/ActuatorConfiguration.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/configuration/ActuatorConfiguration.java index 08a7e9aec8e9..670cff84581e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/configuration/ActuatorConfiguration.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/configuration/ActuatorConfiguration.java @@ -14,6 +14,7 @@ import org.apache.solr.client.solrj.SolrServerException; import org.dspace.app.rest.DiscoverableEndpointsService; import org.dspace.app.rest.health.GeoIpHealthIndicator; +import org.dspace.app.rest.health.SEOHealthIndicator; import org.dspace.app.rest.health.SolrHealthIndicator; import org.dspace.authority.AuthoritySolrServiceImpl; import org.dspace.discovery.SolrSearchCore; @@ -82,6 +83,12 @@ public SolrHealthIndicator solrOaiCoreHealthIndicator(SolrServerResolver solrSer return new SolrHealthIndicator(solrServerResolver.getServer()); } + @Bean + @ConditionalOnEnabledHealthIndicator("seo") + public SEOHealthIndicator seoHealthIndicator() { + return new SEOHealthIndicator(); + } + @Bean @ConditionalOnEnabledHealthIndicator("geoIp") public GeoIpHealthIndicator geoIpHealthIndicator() { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java new file mode 100644 index 000000000000..d936fce635e6 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java @@ -0,0 +1,77 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest.health; + +import org.apache.commons.lang3.StringUtils; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.springframework.boot.actuate.health.AbstractHealthIndicator; +import org.springframework.boot.actuate.health.Health; +import org.springframework.web.client.RestTemplate; + +/** + * Implementation of {@link org.springframework.boot.actuate.health.HealthIndicator} that verifies if the SEO of the + * DSpace instance is configured correctly. + * + * This is only relevant in a production environment, where the DSpace instance is exposed to the public. + */ +public class SEOHealthIndicator extends AbstractHealthIndicator { + + ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); + + private final RestTemplate restTemplate = new RestTemplate(); + + @Override + protected void doHealthCheck(Health.Builder builder) { + String baseUrl = configurationService.getProperty("dspace.ui.url"); + + boolean sitemapOk = checkUrl(baseUrl + "/sitemap_index.xml") || checkUrl(baseUrl + "/sitemap_index.html"); + boolean robotsTxtOk = checkRobotsTxt(baseUrl + "/robots.txt"); + boolean ssrOk = checkSSR(baseUrl); + + if (sitemapOk && robotsTxtOk && ssrOk) { + builder.up() + .withDetail("sitemap", "OK") + .withDetail("robots.txt", "OK") + .withDetail("ssr", "OK"); + } else { + builder.down() + .withDetail("sitemap", sitemapOk ? "OK" : "Missing or inaccessible") + .withDetail("robots.txt", robotsTxtOk ? "OK" : "Empty or contains local URLs") + .withDetail("ssr", ssrOk ? "OK" : "Server-side rendering might be disabled"); + } + } + + private boolean checkUrl(String url) { + try { + restTemplate.getForEntity(url, String.class); + return true; + } catch (Exception e) { + return false; + } + } + + private boolean checkRobotsTxt(String url) { + try { + String content = restTemplate.getForObject(url, String.class); + return StringUtils.isNotBlank(content) && !content.contains("localhost"); + } catch (Exception e) { + return false; + } + } + + private boolean checkSSR(String url) { + try { + String content = restTemplate.getForObject(url, String.class); + return content != null && !content.contains(""); + } catch (Exception e) { + return false; + } + } +} + From 54a3aea70dbfea9b38ca2c30ae6cf6a2f7427904 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 18 Mar 2025 10:04:36 +0100 Subject: [PATCH 472/632] Disable new actuator in IT (cherry picked from commit 20ab43ccccf84c83d6db9b431321e60256d30355) --- dspace-api/src/test/data/dspaceFolder/config/local.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index 43b6d05e5e42..962a1bcd9b22 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -158,6 +158,7 @@ proxies.trusted.include_ui_ip = true # For the tests we have to disable this health indicator because there isn't a mock server and the calculated status was DOWN management.health.solrOai.enabled = false +management.health.seo.enabled = false # Enable researcher profiles and orcid synchronization for tests researcher-profile.entity-type = Person @@ -189,4 +190,4 @@ ldn.notify.inbox.block-untrusted-ip = true # ERROR LOGGING # ########################################### # Log full stacktrace of other common 4xx errors (for easier debugging of these errors in tests) -logging.server.include-stacktrace-for-httpcode = 422, 400 \ No newline at end of file +logging.server.include-stacktrace-for-httpcode = 422, 400 From 698db1d3496b9cb14c0ff21b81c7570de8cf2837 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 1 Apr 2025 17:54:48 +0200 Subject: [PATCH 473/632] 127746: Implement different failures for robots file so we can differentiate between a missing file or an invalid file (cherry picked from commit 32c048428026f890c2f3bc7eca5a2f20717dc587) --- .../app/rest/health/SEOHealthIndicator.java | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java index d936fce635e6..a071e12088bd 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java @@ -31,19 +31,28 @@ protected void doHealthCheck(Health.Builder builder) { String baseUrl = configurationService.getProperty("dspace.ui.url"); boolean sitemapOk = checkUrl(baseUrl + "/sitemap_index.xml") || checkUrl(baseUrl + "/sitemap_index.html"); - boolean robotsTxtOk = checkRobotsTxt(baseUrl + "/robots.txt"); + RobotsTxtStatus robotsTxtStatus = checkRobotsTxt(baseUrl + "/robots.txt"); boolean ssrOk = checkSSR(baseUrl); - if (sitemapOk && robotsTxtOk && ssrOk) { + if (sitemapOk && robotsTxtStatus == RobotsTxtStatus.VALID && ssrOk) { builder.up() .withDetail("sitemap", "OK") .withDetail("robots.txt", "OK") .withDetail("ssr", "OK"); } else { - builder.down() - .withDetail("sitemap", sitemapOk ? "OK" : "Missing or inaccessible") - .withDetail("robots.txt", robotsTxtOk ? "OK" : "Empty or contains local URLs") - .withDetail("ssr", ssrOk ? "OK" : "Server-side rendering might be disabled"); + builder.down(); + builder.withDetail("sitemap", sitemapOk ? "OK" : "Missing or inaccessible"); + + if (robotsTxtStatus == RobotsTxtStatus.MISSING) { + builder.withDetail("robots.txt", "Missing or inaccessible. Please see the DSpace Documentation on " + + "Search Engine Optimization for how to create a robots.txt."); + } else if (robotsTxtStatus == RobotsTxtStatus.INVALID) { + builder.withDetail("robots.txt", "Invalid because it contains localhost URLs. This is often a sign " + + "that a proxy is failing to pass X-Forwarded headers to DSpace. Please see the DSpace " + + "Documentation on Search Engine Optimization for how to pass X-Forwarded headers."); + } + + builder.withDetail("ssr", ssrOk ? "OK" : "Server-side rendering might be disabled"); } } @@ -56,12 +65,18 @@ private boolean checkUrl(String url) { } } - private boolean checkRobotsTxt(String url) { + private RobotsTxtStatus checkRobotsTxt(String url) { try { String content = restTemplate.getForObject(url, String.class); - return StringUtils.isNotBlank(content) && !content.contains("localhost"); + if (StringUtils.isBlank(content)) { + return RobotsTxtStatus.MISSING; + } + if (content.contains("localhost")) { + return RobotsTxtStatus.INVALID; + } + return RobotsTxtStatus.VALID; } catch (Exception e) { - return false; + return RobotsTxtStatus.MISSING; } } @@ -73,5 +88,9 @@ private boolean checkSSR(String url) { return false; } } + + private enum RobotsTxtStatus { + VALID, MISSING, INVALID + } } From 980976484e51fca3d5a905a9caebfb7f12b3a2fe Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 1 Apr 2025 17:58:47 +0200 Subject: [PATCH 474/632] 127746: Add more detailed information messages on how to solve problems (cherry picked from commit 170dc9a44c5b16c28298a9e3133534e70967147d) --- .../org/dspace/app/rest/health/SEOHealthIndicator.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java index a071e12088bd..740c6ab6493e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java @@ -41,7 +41,8 @@ protected void doHealthCheck(Health.Builder builder) { .withDetail("ssr", "OK"); } else { builder.down(); - builder.withDetail("sitemap", sitemapOk ? "OK" : "Missing or inaccessible"); + builder.withDetail("sitemap", sitemapOk ? "OK" : "Sitemaps are missing or inaccessible. Please see the " + + "DSpace Documentation on Search Engine Optimization for how to enable Sitemaps."); if (robotsTxtStatus == RobotsTxtStatus.MISSING) { builder.withDetail("robots.txt", "Missing or inaccessible. Please see the DSpace Documentation on " + @@ -51,8 +52,9 @@ protected void doHealthCheck(Health.Builder builder) { "that a proxy is failing to pass X-Forwarded headers to DSpace. Please see the DSpace " + "Documentation on Search Engine Optimization for how to pass X-Forwarded headers."); } - - builder.withDetail("ssr", ssrOk ? "OK" : "Server-side rendering might be disabled"); + builder.withDetail("ssr", ssrOk ? "OK" : "Server-side rendering (SSR) appears to be disabled. Most " + + "search engines require enabling SSR for proper indexing. Please see the DSpace Documentation on" + + " Search Engine Optimization for more details."); } } From d9ade02675d90c81f27bdf52417a7111a25c9536 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Fri, 4 Apr 2025 16:51:56 +0200 Subject: [PATCH 475/632] 127746: Include success result for robots.txt check if other checks fail (cherry picked from commit 5dc12775fac0006dbc1d0106ffcdffbe893919d1) --- .../java/org/dspace/app/rest/health/SEOHealthIndicator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java index 740c6ab6493e..5b57f2d537fc 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SEOHealthIndicator.java @@ -51,6 +51,8 @@ protected void doHealthCheck(Health.Builder builder) { builder.withDetail("robots.txt", "Invalid because it contains localhost URLs. This is often a sign " + "that a proxy is failing to pass X-Forwarded headers to DSpace. Please see the DSpace " + "Documentation on Search Engine Optimization for how to pass X-Forwarded headers."); + } else { + builder.withDetail("robots.txt", "OK"); } builder.withDetail("ssr", ssrOk ? "OK" : "Server-side rendering (SSR) appears to be disabled. Most " + "search engines require enabling SSR for proper indexing. Please see the DSpace Documentation on" + From cdffd0639cac3078151bbad622ca87785651b4ba Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 7 Apr 2025 10:54:33 -0500 Subject: [PATCH 476/632] Update reusable-docker-build to use Ubuntu ARM64 runner for those images (cherry picked from commit 0177c123b3bcbf4cb2406d4ee4216b2c22c8c2a8) --- .github/workflows/reusable-docker-build.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index 7a8abda3e106..36907459747b 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -86,17 +86,16 @@ jobs: matrix: # Architectures / Platforms for which we will build Docker images arch: [ 'linux/amd64', 'linux/arm64' ] - os: [ ubuntu-latest ] isPr: - ${{ github.event_name == 'pull_request' }} # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. # The below exclude therefore ensures we do NOT build ARM64 for PRs. exclude: - isPr: true - os: ubuntu-latest arch: linux/arm64 - runs-on: ${{ matrix.os }} + # If ARM64, then use the Ubuntu ARM64 runner. Otherwise, use the Ubuntu AMD64 runner + runs-on: ${{ matrix.arch == 'linux/arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }} steps: # This step converts the slashes in the "arch" matrix values above into dashes & saves to env.ARCH_NAME @@ -122,10 +121,6 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - # https://github.com/docker/setup-qemu-action - - name: Set up QEMU emulation to build for multiple architectures - uses: docker/setup-qemu-action@v3 - # https://github.com/docker/setup-buildx-action - name: Setup Docker Buildx uses: docker/setup-buildx-action@v3 From d7a3f32397f542b04e2bb887e64722c2a98a0889 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 7 Apr 2025 14:57:31 -0500 Subject: [PATCH 477/632] Remove unused SWORD v1 client code. This is "dead code" which is unmaintained and obsolete --- .../java/org/purl/sword/client/Client.java | 463 ---------- .../purl/sword/client/ClientConstants.java | 40 - .../org/purl/sword/client/ClientFactory.java | 116 --- .../org/purl/sword/client/ClientOptions.java | 605 ------------- .../org/purl/sword/client/ClientType.java | 23 - .../java/org/purl/sword/client/CmdClient.java | 445 --------- .../purl/sword/client/DebugOutputStream.java | 44 - .../purl/sword/client/MessageOutputPanel.java | 138 --- .../purl/sword/client/PostDestination.java | 140 --- .../org/purl/sword/client/PostDialog.java | 599 ------------- .../org/purl/sword/client/PostMessage.java | 344 ------- .../purl/sword/client/PropertiesDialog.java | 240 ----- .../org/purl/sword/client/SWORDClient.java | 85 -- .../sword/client/SWORDClientException.java | 42 - .../org/purl/sword/client/SWORDComboBox.java | 129 --- .../org/purl/sword/client/SWORDFormPanel.java | 144 --- .../org/purl/sword/client/ServiceDialog.java | 227 ----- .../org/purl/sword/client/ServicePanel.java | 843 ------------------ .../sword/client/ServiceSelectedListener.java | 23 - .../java/org/purl/sword/client/Status.java | 61 -- 20 files changed, 4751 deletions(-) delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/Client.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/ClientConstants.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/ClientFactory.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/ClientOptions.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/ClientType.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/CmdClient.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/DebugOutputStream.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/MessageOutputPanel.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/PostDestination.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/PostDialog.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/PostMessage.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/PropertiesDialog.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/SWORDClient.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/SWORDClientException.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/SWORDComboBox.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/SWORDFormPanel.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/ServiceDialog.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/ServicePanel.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/ServiceSelectedListener.java delete mode 100644 dspace-sword/src/main/java/org/purl/sword/client/Status.java diff --git a/dspace-sword/src/main/java/org/purl/sword/client/Client.java b/dspace-sword/src/main/java/org/purl/sword/client/Client.java deleted file mode 100644 index c6d335d8dd16..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/Client.java +++ /dev/null @@ -1,463 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.NoSuchAlgorithmException; -import java.util.Properties; - -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.params.ConnRoutePNames; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.FileEntity; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpParams; -import org.apache.logging.log4j.Logger; -import org.purl.sword.base.ChecksumUtils; -import org.purl.sword.base.DepositResponse; -import org.purl.sword.base.HttpHeaders; -import org.purl.sword.base.ServiceDocument; -import org.purl.sword.base.SwordValidationInfo; -import org.purl.sword.base.UnmarshallException; - -/** - * This is an example Client implementation to demonstrate how to connect to a - * SWORD server. The client supports BASIC HTTP Authentication. This can be - * initialised by setting a username and password. - * - * @author Neil Taylor - */ -public class Client implements SWORDClient { - /** - * The status field for the response code from the recent network access. - */ - private Status status; - - /** - * The name of the server to contact. - */ - private String server; - - /** - * The port number for the server. - */ - private int port; - - /** - * Specifies if the network access should use HTTP authentication. - */ - private boolean doAuthentication; - - /** - * The username to use for Basic Authentication. - */ - private String username; - - /** - * User password that is to be used. - */ - private String password; - - /** - * The userAgent to identify this application. - */ - private String userAgent; - - /** - * The client that is used to send data to the specified server. - */ - private final DefaultHttpClient client; - - /** - * The default connection timeout. This can be modified by using the - * setSocketTimeout method. - */ - public static final int DEFAULT_TIMEOUT = 20000; - - /** - * Logger. - */ - private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(Client.class); - - /** - * Create a new Client. The client will not use authentication by default. - */ - public Client() { - client = new DefaultHttpClient(); - HttpParams params = client.getParams(); - params.setParameter("http.socket.timeout", - Integer.valueOf(DEFAULT_TIMEOUT)); - HttpHost proxyHost = (HttpHost) params - .getParameter(ConnRoutePNames.DEFAULT_PROXY); // XXX does this really work? - log.debug("proxy host: " + proxyHost.getHostName()); - log.debug("proxy port: " + proxyHost.getPort()); - doAuthentication = false; - } - - /** - * Initialise the server that will be used to send the network access. - * - * @param server server address/hostname - * @param port server port - */ - public void setServer(String server, int port) { - this.server = server; - this.port = port; - } - - /** - * Set the user credentials that will be used when making the access to the - * server. - * - * @param username The username. - * @param password The password. - */ - public void setCredentials(String username, String password) { - this.username = username; - this.password = password; - doAuthentication = true; - } - - /** - * Set the basic credentials. You must have previously set the server and - * port using setServer. - * - * @param username The username. - * @param password The password. - */ - private void setBasicCredentials(String username, String password) { - log.debug("server: " + server + " port: " + port + " u: '" + username - + "' p '" + password + "'"); - client.getCredentialsProvider().setCredentials(new AuthScope(server, port), - new UsernamePasswordCredentials(username, password)); - } - - /** - * Set a proxy that should be used by the client when trying to access the - * server. If this is not set, the client will attempt to make a direct - * direct connection to the server. The port is set to 80. - * - * @param host The hostname. - */ - public void setProxy(String host) { - setProxy(host, 80); - } - - /** - * Set a proxy that should be used by the client when trying to access the - * server. If this is not set, the client will attempt to make a direct - * direct connection to the server. - * - * @param host The name of the host. - * @param port The port. - */ - public void setProxy(String host, int port) { - client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, - new HttpHost(host, port)); // XXX does this really work? - } - - /** - * Clear the proxy setting. - */ - public void clearProxy() { - client.getParams().removeParameter(ConnRoutePNames.DEFAULT_PROXY); // XXX does this really work? - } - - /** - * Clear any user credentials that have been set for this client. - */ - public void clearCredentials() { - client.getCredentialsProvider().clear(); - doAuthentication = false; - } - - public void setUserAgent(String userAgent) { - this.userAgent = userAgent; - } - - /** - * Set the connection timeout for the socket. - * - * @param milliseconds The time, expressed as a number of milliseconds. - */ - public void setSocketTimeout(int milliseconds) { - client.getParams().setParameter("http.socket.timeout", - Integer.valueOf(milliseconds)); - } - - /** - * Retrieve the service document. The service document is located at the - * specified URL. This calls getServiceDocument(url,onBehalfOf). - * - * @param url The location of the service document. - * @return The ServiceDocument, or null if there was a - * problem accessing the document. e.g. invalid access. - * @throws SWORDClientException If there is an error accessing the resource. - */ - public ServiceDocument getServiceDocument(String url) - throws SWORDClientException { - return getServiceDocument(url, null); - } - - /** - * Retrieve the service document. The service document is located at the - * specified URL. This calls getServiceDocument(url,onBehalfOf). - * - * @param url The location of the service document. - * @return The ServiceDocument, or null if there was a - * problem accessing the document. e.g. invalid access. - * @throws SWORDClientException If there is an error accessing the resource. - */ - public ServiceDocument getServiceDocument(String url, String onBehalfOf) - throws SWORDClientException { - URL serviceDocURL = null; - try { - serviceDocURL = new URL(url); - } catch (MalformedURLException e) { - // Try relative URL - URL baseURL = null; - try { - baseURL = new URL("http", server, Integer.valueOf(port), "/"); - serviceDocURL = new URL(baseURL, (url == null) ? "" : url); - } catch (MalformedURLException e1) { - // No dice, can't even form base URL... - throw new SWORDClientException(url + " is not a valid URL (" - + e1.getMessage() - + "), and could not form a relative one from: " - + baseURL + " / " + url, e1); - } - } - - HttpGet httpget = new HttpGet(serviceDocURL.toExternalForm()); - if (doAuthentication) { - // this does not perform any check on the username password. It - // relies on the server to determine if the values are correct. - setBasicCredentials(username, password); - } - - Properties properties = new Properties(); - - if (containsValue(onBehalfOf)) { - log.debug("Setting on-behalf-of: " + onBehalfOf); - httpget.addHeader(url, url); - httpget.addHeader(HttpHeaders.X_ON_BEHALF_OF, onBehalfOf); - properties.put(HttpHeaders.X_ON_BEHALF_OF, onBehalfOf); - } - - if (containsValue(userAgent)) { - log.debug("Setting userAgent: " + userAgent); - httpget.addHeader(HttpHeaders.USER_AGENT, userAgent); - properties.put(HttpHeaders.USER_AGENT, userAgent); - } - - ServiceDocument doc = null; - - try { - HttpResponse response = client.execute(httpget); - StatusLine statusLine = response.getStatusLine(); - int statusCode = statusLine.getStatusCode(); - // store the status code - status = new Status(statusCode, statusLine.getReasonPhrase()); - - if (status.getCode() == HttpStatus.SC_OK) { - String message = readResponse(response.getEntity().getContent()); - log.debug("returned message is: " + message); - doc = new ServiceDocument(); - lastUnmarshallInfo = doc.unmarshall(message, properties); - } else { - throw new SWORDClientException( - "Received error from service document request: " - + status); - } - } catch (IOException ioex) { - throw new SWORDClientException(ioex.getMessage(), ioex); - } catch (UnmarshallException uex) { - throw new SWORDClientException(uex.getMessage(), uex); - } finally { - httpget.releaseConnection(); - } - - return doc; - } - - private SwordValidationInfo lastUnmarshallInfo; - - /** - * @return SWORD validation info - */ - public SwordValidationInfo getLastUnmarshallInfo() { - return lastUnmarshallInfo; - } - - /** - * Post a file to the server. The different elements of the post are encoded - * in the specified message. - * - * @param message The message that contains the post information. - * @throws SWORDClientException if there is an error during the post operation. - */ - public DepositResponse postFile(PostMessage message) - throws SWORDClientException { - if (message == null) { - throw new SWORDClientException("Message cannot be null."); - } - - HttpPost httppost = new HttpPost(message.getDestination()); - - if (doAuthentication) { - setBasicCredentials(username, password); - } - - DepositResponse response = null; - - String messageBody = ""; - - try { - if (message.isUseMD5()) { - String md5 = ChecksumUtils.generateMD5(message.getFilepath()); - if (message.getChecksumError()) { - md5 = "1234567890"; - } - log.debug("checksum error is: " + md5); - if (md5 != null) { - httppost.addHeader(HttpHeaders.CONTENT_MD5, md5); - } - } - - String filename = message.getFilename(); - if (!"".equals(filename)) { - httppost.addHeader(HttpHeaders.CONTENT_DISPOSITION, - " filename=" + filename); - } - - if (containsValue(message.getSlug())) { - httppost.addHeader(HttpHeaders.SLUG, message.getSlug()); - } - - if (message.getCorruptRequest()) { - // insert a header with an invalid boolean value - httppost.addHeader(HttpHeaders.X_NO_OP, "Wibble"); - } else { - httppost.addHeader(HttpHeaders.X_NO_OP, Boolean - .toString(message.isNoOp())); - } - httppost.addHeader(HttpHeaders.X_VERBOSE, Boolean - .toString(message.isVerbose())); - - String packaging = message.getPackaging(); - if (packaging != null && packaging.length() > 0) { - httppost.addHeader(HttpHeaders.X_PACKAGING, packaging); - } - - String onBehalfOf = message.getOnBehalfOf(); - if (containsValue(onBehalfOf)) { - httppost.addHeader(HttpHeaders.X_ON_BEHALF_OF, onBehalfOf); - } - - String userAgent = message.getUserAgent(); - if (containsValue(userAgent)) { - httppost.addHeader(HttpHeaders.USER_AGENT, userAgent); - } - - - FileEntity requestEntity = new FileEntity( - new File(message.getFilepath()), - ContentType.create(message.getFiletype())); - httppost.setEntity(requestEntity); - - HttpResponse httpResponse = client.execute(httppost); - StatusLine statusLine = httpResponse.getStatusLine(); - int statusCode = statusLine.getStatusCode(); - status = new Status(statusCode, statusLine.getReasonPhrase()); - - log.info("Checking the status code: " + status.getCode()); - - if (status.getCode() == HttpStatus.SC_ACCEPTED - || status.getCode() == HttpStatus.SC_CREATED) { - messageBody = readResponse(httpResponse.getEntity().getContent()); - response = new DepositResponse(status.getCode()); - response.setLocation(httpResponse.getFirstHeader("Location").getValue()); - // added call for the status code. - lastUnmarshallInfo = response.unmarshall(messageBody, new Properties()); - } else { - messageBody = readResponse(httpResponse.getEntity().getContent()); - response = new DepositResponse(status.getCode()); - response.unmarshallErrorDocument(messageBody); - } - return response; - - } catch (NoSuchAlgorithmException nex) { - throw new SWORDClientException("Unable to use MD5. " - + nex.getMessage(), nex); - } catch (IOException ioex) { - throw new SWORDClientException(ioex.getMessage(), ioex); - } catch (UnmarshallException uex) { - throw new SWORDClientException(uex.getMessage() + "(
    " + messageBody + "
    )", uex); - } finally { - httppost.releaseConnection(); - } - } - - /** - * Read a response from the stream and return it as a string. - * - * @param stream The stream that contains the response. - * @return The string extracted from the screen. - * @throws UnsupportedEncodingException - * @throws IOException A general class of exceptions produced by failed or interrupted I/O - * operations. - */ - private String readResponse(InputStream stream) - throws UnsupportedEncodingException, IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader( - stream, "UTF-8")); - String line = null; - StringBuffer buffer = new StringBuffer(); - while ((line = reader.readLine()) != null) { - buffer.append(line); - buffer.append("\n"); - } - return buffer.toString(); - } - - /** - * Return the status information that was returned from the most recent - * request sent to the server. - * - * @return The status code returned from the most recent access. - */ - public Status getStatus() { - return status; - } - - /** - * Check to see if the specified item contains a non-empty string. - * - * @param item The string to check. - * @return True if the string is not null and has a length greater than 0 - * after any whitespace is trimmed from the start and end. - * Otherwise, false. - */ - private boolean containsValue(String item) { - return ((item != null) && (item.trim().length() > 0)); - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/ClientConstants.java b/dspace-sword/src/main/java/org/purl/sword/client/ClientConstants.java deleted file mode 100644 index 124ed38d33d8..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/ClientConstants.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -/** - * Hold general constants for the client. - * - * @author Neil Taylor - */ -public class ClientConstants { - /** - * Current software version. - */ - public static final String CLIENT_VERSION = "1.1"; - - /** - * the name of this application - */ - public static final String SERVICE_NAME = "CASIS Test Client"; - - /** - * the name of this application - */ - public static final String NOT_DEFINED_TEXT = "Not defined"; - - /** - * The logging property file. - */ - public static final String LOGGING_PROPERTY_FILE = "log4j.properties"; - - /** - * Default constructor - */ - private ClientConstants() { } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/ClientFactory.java b/dspace-sword/src/main/java/org/purl/sword/client/ClientFactory.java deleted file mode 100644 index 00bd9c17a541..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/ClientFactory.java +++ /dev/null @@ -1,116 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -/** - * Entry point for the SWORD Demonstration Client. This will parse the list of - * command line options and load either a Command Line client or a GUI client. - * - * @author Neil Taylor - */ -public class ClientFactory { - /** - * Generate a string that specifies the command line options for this - * program. - * - * @return A list of the options for this program. - */ - public static String usage() { - StringBuilder buffer = new StringBuilder(); - buffer.append("swordclient: version "); - buffer.append(ClientConstants.CLIENT_VERSION); - buffer.append("\n"); - - buffer.append("GUI Mode: "); - buffer.append("swordclient [-gui] [-nocapture]"); - buffer.append("\n\n"); - - buffer.append("Command Mode: Service - Request a Service Document\n"); - buffer.append("swordclient -cmd -t service [user-options] [proxy-options] -href url [-onBehalfOf name] "); - buffer.append("\n\n"); - - buffer.append("Command Mode: Post - Post a file to a remote service.\n"); - buffer.append("swordclient -cmd -t post [user-options] [proxy-options] [post-options] \n"); - buffer.append(" [-file file] [-filetype type] [-onBehalfOf name]"); - buffer.append("\n\n"); - - buffer.append("Command Mode: MultiPost - Post a file to multiple remote services.\n"); - buffer.append("swordclient -cmd -t multipost [user-options] [proxy-options] [post-options] \n"); - buffer.append(" [-dest dest]"); - - buffer.append("\n\n"); - buffer.append("User options: \n"); - buffer.append(" -u username Specify a username to access the remote service.\n"); - buffer.append(" -p password Specify a password to access the remote service.\n"); - buffer.append(" Required if -u option is used."); - - buffer.append("\n\n"); - buffer.append("Proxy options: \n"); - buffer.append(" -host host Hostname of a proxy, wwwproxy.aber.ac.uk.\n"); - buffer.append(" -port port Proxy port number, e.g. 8080.\n"); - - buffer.append("\n\n"); - buffer.append("Post options: \n"); - buffer.append(" -noOp Specified to indicate that the post is a test operation.\n"); - buffer.append(" -md5 Use an MD5 checksum in the message header.\n"); - buffer.append(" -checksumError Mis-calculate the file checksum for server test purposes.\n"); - buffer.append(" -formatNamespace ns The format namespace value.\n"); - buffer.append(" -slug name The slug value.\n"); - buffer.append(" -verbose Request a verbose response from the server.\n"); - - buffer.append("\n\n"); - buffer.append("Other options: \n"); - buffer.append(" -help Show this message.\n"); - buffer.append(" -t type The type of operation: service, post or multipost.\n"); - buffer.append(" -href url The URL for the service or post document.\n"); - buffer.append(" Required for service. The post and multipost operations \n"); - buffer.append(" will prompt you if the value is not provided.\n"); - buffer.append(" -filetype type The filetype, e.g. application/zip. The post and multipost\n"); - buffer.append(" will prompt you for the value if it is not provided.\n"); - buffer.append(" -onBehalfOf name Specify this parameter to set the On Behalf Of value.\n"); - buffer.append(" -dest dest Specify the destination for a deposit. This can be repeated\n"); - buffer.append(" multiple times. The format is: \n"); - buffer.append(" []:@\n"); - buffer.append(" e.g. sword[nst]:swordpass@http://sword.aber.ac.uk/post/\n"); - buffer.append(" nst:pass@http://sword.aber.ac.uk/post\n"); - buffer.append(" -nocapture Do not capture System.out and System.err to a debug panel\n"); - buffer.append(" in the GUI panel."); - - return buffer.toString(); - } - - /** - * Create a client. If GUI mode is set, a GUI client is created. Otherwise, - * a command line client is created. - * - * @param options The list of options extracted from the command line. - * @return A new client. - */ - public ClientType createClient(ClientOptions options) { - return new CmdClient(); - } - - /** - * Start the application and determine which client should be loaded. The - * application currently has two modes: GUI and client. The GUI mode is the - * default option. - * - * @param args the command line arguments given - */ - public static void main(String[] args) { - ClientFactory factory = new ClientFactory(); - - ClientOptions options = new ClientOptions(); - if (options.parseOptions(args)) { - ClientType client = factory.createClient(options); - client.run(options); - } else { - System.out.println(usage()); - } - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/ClientOptions.java b/dspace-sword/src/main/java/org/purl/sword/client/ClientOptions.java deleted file mode 100644 index 1ffbfca022b2..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/ClientOptions.java +++ /dev/null @@ -1,605 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * List of options that are parsed from the command line. - * - * @author Neil Taylor - */ -public class ClientOptions { - /** - * Label for the service operation. - */ - public static final String TYPE_SERVICE = "service"; - - /** - * Label for the post operation. - */ - public static final String TYPE_POST = "post"; - - /** - * Label for the multipost operation. - */ - public static final String TYPE_MULTI_POST = "multipost"; - - /** - * The access type. - */ - private String accessType = null; - - /** - * Proxy host name. - */ - private String proxyHost = null; - - /** - * Proxy host port. - */ - private int proxyPort = 8080; - - /** - * Username to access the service/post server. - */ - private String username = null; - - /** - * Password to access the service/post server. - */ - private String password = null; - - /** - * HREF of the server to access. - */ - private String href = null; - - /** - * Filename to post. - */ - private String filename = null; - - /** - * File type. - */ - private String filetype = null; - - /** - * Specifies that the output streams are not to be captured by the GUI client. - */ - private boolean noCapture = false; - - - /** - * SLUG Header field. - */ - private String slug = null; - - /** - * NoOp, used to indicate an operation on the server that does not - * require the file to be stored. - */ - private boolean noOp = false; - - /** - * Request verbose output from the server. - */ - private boolean verbose = false; - - /** - * OnBehalfOf user id. - */ - private String onBehalfOf = null; - - /** - * Format namespace to be used for the posted file. - */ - private String formatNamespace = null; - - /** - * Introduce a checksum error. This is used to simulate an error with the - * MD5 value. - */ - private boolean checksumError = false; - - /** - * Logger. - */ - private static final Logger log = LogManager.getLogger(); - - /** - * List of multiple destination items. Used if the mode is set to multipost. - */ - private final List multiPost = new ArrayList<>(); - - /** - * Pattern string to extract the data from a destination parameter in multipost mode. - */ - private static final Pattern MULTI_PATTERN - = Pattern.compile("(.*?)(\\[(.*?)\\]) {0,1}(:(.*)) {0,1}@(http://.*)"); - - /** - * Flag that indicates if the GUI mode has been set. This is - * true by default. - */ - private boolean guiMode = true; - - /** - * Flat that indicates if the MD5 option has been selected. This - * is true by default. - */ - private boolean md5 = false; - - /** - * Parse the list of options contained in the specified array. - * - * @param args The array of options. - * @return True if the options were parsed successfully. - */ - public boolean parseOptions(String[] args) { - Options options = new Options(); - options.addOption(Option.builder().longOpt("md5").build()) - .addOption(Option.builder().longOpt("noOp").build()) - .addOption(Option.builder().longOpt("verbose").build()) - .addOption(Option.builder().longOpt("cmd").build()) - .addOption(Option.builder().longOpt("gui").build()) - .addOption(Option.builder().longOpt("help").build()) - .addOption(Option.builder().longOpt("nocapture").build()); - - Option option; - - option = Option.builder().longOpt("host").hasArg().build(); - options.addOption(option); - - option = Option.builder().longOpt("port").hasArg().build(); - options.addOption(option); - - option = Option.builder("u").hasArg().build(); - options.addOption(option); - - option = Option.builder("p").hasArg().build(); - options.addOption(option); - - option = Option.builder().longOpt("href").hasArg().build(); - options.addOption(option); - - option = Option.builder("t").hasArg().build(); - options.addOption(option); - - option = Option.builder().longOpt("file").hasArg().build(); - options.addOption(option); - - option = Option.builder().longOpt("filetype").hasArg().build(); - options.addOption(option); - - option = Option.builder().longOpt("slug").hasArg().build(); - options.addOption(option); - - option = Option.builder().longOpt("onBehalfOf").hasArg().build(); - options.addOption(option); - - option = Option.builder().longOpt("formatNamespace").hasArg().build(); - options.addOption(option); - - option = Option.builder().longOpt("checksumError").build(); - options.addOption(option); - - option = Option.builder().longOpt("dest").hasArg().build(); - options.addOption(option); - - DefaultParser parser = new DefaultParser(); - CommandLine command; - try { - command = parser.parse(options, args); - } catch (ParseException ex) { - log.error(ex.getMessage()); - return false; - } - - if (command.hasOption("help")) { - return false; // force the calling code to display the usage information. - } - md5 = command.hasOption("md5"); - noOp = command.hasOption("noOp"); - verbose = command.hasOption("verbose"); - if (command.hasOption("cmd")) { - guiMode = false; - } - if (command.hasOption("gui")) { - guiMode = true; - } - proxyHost = command.getOptionValue("host"); - if (command.hasOption("port")) { - proxyPort = Integer.parseInt(command.getOptionValue("port")); - } - username = command.getOptionValue("u"); - password = command.getOptionValue("p"); - href = command.getOptionValue("href"); - accessType = command.getOptionValue("t"); - filename = command.getOptionValue("file"); - filetype = command.getOptionValue("filetype"); - slug = command.getOptionValue("slug"); - onBehalfOf = command.getOptionValue("onBehalfOf"); - formatNamespace = command.getOptionValue("formatNamespace"); - checksumError = command.hasOption("checksumError"); - noCapture = command.hasOption("nocapture"); - if (command.hasOption("dest")) { - String dest = command.getOptionValue("dest"); - Matcher m = MULTI_PATTERN.matcher(dest); - if (!m.matches()) { - log.debug("Error with dest parameter. Ignoring value: {}", dest); - } else { - int numGroups = m.groupCount(); - for (int g = 0; g <= numGroups; g++) { - log.debug("Group ({}) is: {}", g, m.group(g)); - } - - String group_username = m.group(1); - String group_onBehalfOf = m.group(3); - String group_password = m.group(5); - String group_url = m.group(6); - PostDestination destination = new PostDestination(group_url, - group_username, group_password, group_onBehalfOf); - - multiPost.add(destination); - } - } - - try { - // apply any settings - if (href == null && "service".equals(accessType)) { - log.error("No href specified."); - return false; - } - - if (multiPost.isEmpty() && "multipost".equals(accessType)) { - log.error("No destinations specified"); - return false; - } - - if (accessType == null && !guiMode) { - log.error("No access type specified"); - return false; - } - - if ((username == null && password != null) || (username != null && password == null)) { - log.error( - "The username and/or password are not specified. If one is specified, the other must also be " + - "specified."); - return false; - } - } catch (ArrayIndexOutOfBoundsException ex) { - log.error("Error with parameters."); - return false; - } - - return true; - } - - /** - * Get the access type. - * - * @return The value, or null if the value is not set. - */ - public String getAccessType() { - return accessType; - } - - /** - * Set the access type. - * - * @param accessType The value, or null to clear the value. - */ - public void setAccessType(String accessType) { - this.accessType = accessType; - } - - /** - * Get the proxy host. - * - * @return The value, or null if the value is not set. - */ - public String getProxyHost() { - return proxyHost; - } - - /** - * Set the proxy host. - * - * @param proxyHost The value, or null to clear the value. - */ - public void setProxyHost(String proxyHost) { - this.proxyHost = proxyHost; - } - - /** - * Get the proxy port. - * - * @return The proxy port. Default value is 80. - */ - public int getProxyPort() { - return proxyPort; - } - - /** - * Set the proxy port. - * - * @param proxyPort The proxy port. - */ - public void setProxyPort(int proxyPort) { - this.proxyPort = proxyPort; - } - - /** - * Get the username. - * - * @return The value, or null if the value is not set. - */ - public String getUsername() { - return username; - } - - /** - * Set the username. - * - * @param username The value, or null to clear the value. - */ - public void setUsername(String username) { - this.username = username; - } - - /** - * Get the password. - * - * @return The value, or null if the value is not set. - */ - public String getPassword() { - return password; - } - - /** - * Set the password. - * - * @param password The value, or null to clear the value. - */ - public void setPassword(String password) { - this.password = password; - } - - /** - * Get the HREF of the service to access. - * - * @return The value, or null if the value is not set. - */ - public String getHref() { - return href; - } - - /** - * Set the HREF of the service to access. - * - * @param href The value, or null to clear the value. - */ - public void setHref(String href) { - this.href = href; - } - - /** - * Get the name of the file to post. - * - * @return The value, or null if the value is not set. - */ - public String getFilename() { - return filename; - } - - /** - * Set the name of the file to post. - * - * @param filename The value, or null to clear the value. - */ - public void setFilename(String filename) { - this.filename = filename; - } - - /** - * Get the type of the file to post. - * - * @return The filetype, or null if the value is not set. - */ - public String getFiletype() { - return filetype; - } - - /** - * Set the type of the file to post. - * - * @param filetype The value, or null to clear the value. - */ - public void setFiletype(String filetype) { - this.filetype = filetype; - } - - /** - * Determine if the tool is to be run in GUI mode. - * - * @return True if the tool is set for GUI mode. - */ - public boolean isGuiMode() { - return guiMode; - } - - /** - * Set the tool to run in GUI mode. - * - * @param guiMode True if the tool is to run in gui mode. - */ - public void setGuiMode(boolean guiMode) { - this.guiMode = guiMode; - } - - /** - * Get the MD5 setting. True if the tool is to use MD5 for post operations. - * - * @return The MD5 setting. - */ - public boolean isMd5() { - return md5; - } - - /** - * Set the MD5 setting. - * - * @param md5 True if the tool should use MD5 for post operations. - */ - public void setMd5(boolean md5) { - this.md5 = md5; - } - - /** - * Determine if the NoOp header should be sent. - * - * @return True if the header should be sent. - */ - public boolean isNoOp() { - return noOp; - } - - /** - * Set the NoOp setting. - * - * @param noOp True if the NoOp header should be used. - */ - public void setNoOp(boolean noOp) { - this.noOp = noOp; - } - - /** - * Determine if the verbose option is set. - * - * @return True if verbose option is set. - */ - public boolean isVerbose() { - return verbose; - } - - /** - * Set the verbose option. - * - * @param verbose True if verbose should be set. - */ - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - /** - * Get the onBehalfOf value. - * - * @return The value, or null to clear the value. - */ - public String getOnBehalfOf() { - return onBehalfOf; - } - - /** - * Set the onBehalf of Value. - * - * @param onBehalfOf The value, or null to clear the value. - */ - public void setOnBehalfOf(String onBehalfOf) { - this.onBehalfOf = onBehalfOf; - } - - /** - * Get the format namespace value. - * - * @return The value, or null if the value is not set. - */ - public String getFormatNamespace() { - return formatNamespace; - } - - /** - * Set the format namespace value. - * - * @param formatNamespace The value, or null to clear the value. - */ - public void setFormatNamespace(String formatNamespace) { - this.formatNamespace = formatNamespace; - } - - /** - * Get the checksum error value. - * - * @return True if an error should be introduced into the checksum. - */ - public boolean getChecksumError() { - return checksumError; - } - - /** - * Set the checksum error value. - * - * @param checksumError True if the error should be introduced. - */ - public void setChecksumError(boolean checksumError) { - this.checksumError = checksumError; - } - - /** - * Get the current slug header. - * - * @return The slug value, or null if the value is not set. - */ - public String getSlug() { - return this.slug; - } - - /** - * Set the text that is to be used for the slug header. - * - * @param slug The value, or null to clear the value. - */ - public void setSlug(String slug) { - this.slug = slug; - } - - /** - * Get the list of post destinations. - * - * @return An iterator over the list of PostDestination objects. - */ - public Iterator getMultiPost() { - return multiPost.iterator(); - } - - - /** - * Determine if the noCapture option is set. This indicates that the code - * should not attempt to redirect stdout and stderr to a different output - * destination. Intended for use in a GUI client. - * - * @return The noCapture setting. True if set. - */ - public boolean isNoCapture() { - return noCapture; - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/ClientType.java b/dspace-sword/src/main/java/org/purl/sword/client/ClientType.java deleted file mode 100644 index 11474782c1cf..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/ClientType.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -/** - * Interface for a client. This contains a single method that allows the factory - * to pass a set of command line options to the client. - * - * @author Neil Taylor - */ -public interface ClientType { - /** - * Run the client, processing the specified options. - * - * @param options The options extracted from the command line. - */ - public void run(ClientOptions options); -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/CmdClient.java b/dspace-sword/src/main/java/org/purl/sword/client/CmdClient.java deleted file mode 100644 index 842e9d483dca..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/CmdClient.java +++ /dev/null @@ -1,445 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Iterator; -import java.util.List; - -import org.apache.logging.log4j.Logger; -import org.purl.sword.atom.Author; -import org.purl.sword.atom.Content; -import org.purl.sword.atom.Contributor; -import org.purl.sword.atom.Generator; -import org.purl.sword.atom.Link; -import org.purl.sword.atom.Rights; -import org.purl.sword.atom.Summary; -import org.purl.sword.atom.Title; -import org.purl.sword.base.Collection; -import org.purl.sword.base.DepositResponse; -import org.purl.sword.base.SWORDEntry; -import org.purl.sword.base.ServiceDocument; -import org.purl.sword.base.SwordAcceptPackaging; -import org.purl.sword.base.Workspace; - -/** - * Example implementation of a command line client. This can send out service - * document requests and print out the results and process posting a file to - * either a single or multiple destinations. The command line options are - * initialised prior to calling the class. The options are passed into the - * run(ClientOptions) method. - * - * @author Neil Taylor - */ -public class CmdClient implements ClientType { - /** - * The client that is used to process the service and post requests. - */ - private SWORDClient client; - - /** - * List of the options that can be specified on the command line. - */ - private ClientOptions options; - - /** - * The logger. - */ - private static Logger log = org.apache.logging.log4j.LogManager.getLogger(CmdClient.class); - - /** - * Create a new instance of the class and create an instance of the - * client. - */ - public CmdClient() { - client = new Client(); - } - - /** - * Process the options that have been initialised from the command line. - * This will call one of service(), post() or multiPost(). - */ - public void process() { - if (options.getProxyHost() != null) { - client.setProxy(options.getProxyHost(), options.getProxyPort()); - } - - try { - String accessType = options.getAccessType(); - if (ClientOptions.TYPE_SERVICE.equals(accessType)) { - service(); - } else if (ClientOptions.TYPE_POST.equals(accessType)) { - post(); - } else if (ClientOptions.TYPE_MULTI_POST.equals(accessType)) { - System.out.println("checking multi-post"); - multiPost(); - } else { - System.out.println("Access type not recognised."); - } - - } catch (MalformedURLException mex) { - System.out - .println("The specified href was not valid: " + options.getHref() + " message: " + mex.getMessage()); - } catch (SWORDClientException ex) { - System.out.println("Exception: " + ex.getMessage()); - log.error("Unable to process request", ex); - } - } - - /** - * Process the service operation. Output the results of the service request. - * - * @throws SWORDClientException if there is an error processing the service request. - * @throws MalformedURLException if there is an error with the URL for the service request. - */ - private void service() - throws SWORDClientException, MalformedURLException { - String href = options.getHref(); - initialiseServer(href, options.getUsername(), options.getPassword()); - - ServiceDocument document = client.getServiceDocument(href, options.getOnBehalfOf()); - Status status = client.getStatus(); - System.out.println("The status is: " + status); - - if (status.getCode() == 200) { - log.debug("message is: " + document.marshall()); - - System.out.println("\nThe following Details were retrieved: "); - System.out.println("SWORD Version: " - + document.getService().getVersion()); - System.out.println("Supports NoOp? " + document.getService().isNoOp()); - System.out.println("Supports Verbose? " - + document.getService().isVerbose()); - System.out.println("Max Upload File Size " - + document.getService().getMaxUploadSize() + " kB"); - - Iterator workspaces = document.getService().getWorkspaces(); - for (; workspaces.hasNext(); ) { - Workspace workspace = workspaces.next(); - System.out.println("\nWorkspace Title: '" - + workspace.getTitle() + "'"); - - System.out.println("\n+ Collections ---"); - // process the collections - Iterator collections = workspace - .collectionIterator(); - for (; collections.hasNext(); ) { - Collection collection = collections.next(); - System.out.println("\nCollection location: " - + collection.getLocation()); - System.out.println("Collection title: " - + collection.getTitle()); - System.out - .println("Abstract: " + collection.getAbstract()); - System.out.println("Collection Policy: " - + collection.getCollectionPolicy()); - System.out.println("Treatment: " - + collection.getTreatment()); - System.out.println("Mediation: " - + collection.getMediation()); - - String[] accepts = collection.getAccepts(); - if (accepts != null && accepts.length == 0) { - System.out.println("Accepts: none specified"); - } else { - for (String s : accepts) { - System.out.println("Accepts: " + s); - } - } - List acceptsPackaging = collection.getAcceptPackaging(); - - StringBuilder acceptPackagingList = new StringBuilder(); - for (Iterator i = acceptsPackaging.iterator(); i.hasNext(); ) { - SwordAcceptPackaging accept = (SwordAcceptPackaging) i.next(); - acceptPackagingList.append(accept.getContent()).append(" (").append(accept.getQualityValue()) - .append("), "); - } - - System.out.println("Accepts Packaging: " + acceptPackagingList.toString()); - } - System.out.println("+ End of Collections ---"); - } - } - } - - /** - * Perform a post. If any of the destination URL, the filename and the - * filetype are missing, the user will be prompted to enter the values. - * - * @throws SWORDClientException if there is an error processing the post for a requested - * destination. - * @throws MalformedURLException if there is an error with the URL for the post. - */ - private void post() - throws SWORDClientException, MalformedURLException { - String url = options.getHref(); - if (url == null) { - url = readLine("Please enter the URL for the deposit: "); - } - - initialiseServer(url, options.getUsername(), options.getPassword()); - String file = options.getFilename(); - if (file == null) { - file = readLine("Please enter the filename to deposit: "); - } - String type = options.getFiletype(); - if (type == null) { - type = readLine("Please enter the file type, e.g. application/zip: "); - } - - PostMessage message = new PostMessage(); - message.setFilepath(file); - message.setDestination(url); - message.setFiletype(type); - message.setUseMD5(options.isMd5()); - message.setVerbose(options.isVerbose()); - message.setNoOp(options.isNoOp()); - message.setFormatNamespace(options.getFormatNamespace()); - message.setOnBehalfOf(options.getOnBehalfOf()); - message.setChecksumError(options.getChecksumError()); - message.setUserAgent(ClientConstants.SERVICE_NAME); - - processPost(message); - - } - - /** - * Perform a multi-post. Iterate over the list of -dest arguments in the command line - * options. For each -dest argument, attempt to post the file to the server. - * - * @throws SWORDClientException if there is an error processing the post for a requested - * destination. - * @throws MalformedURLException if there is an error with the URL for the post. - */ - private void multiPost() - throws SWORDClientException, MalformedURLException { - // request the common information - String file = options.getFilename(); - if (file == null) { - file = readLine("Please enter the filename to deposit: "); - } - String type = options.getFiletype(); - if (type == null) { - type = readLine("Please enter the file type, e.g. application/zip: "); - } - - // process this information for each of the specified destinations - PostDestination destination; - String url = null; - - Iterator iterator = options.getMultiPost(); - while (iterator.hasNext()) { - destination = iterator.next(); - url = destination.getUrl(); - initialiseServer(url, destination.getUsername(), destination.getPassword()); - - String onBehalfOf = destination.getOnBehalfOf(); - if (onBehalfOf == null) { - onBehalfOf = ""; - } else { - onBehalfOf = " on behalf of: " + onBehalfOf; - } - - System.out.println("Sending file to: " + url + " for: " + destination.getUsername() + - onBehalfOf); - PostMessage message = new PostMessage(); - message.setFilepath(file); - message.setDestination(url); - message.setFiletype(type); - message.setUseMD5(options.isMd5()); - message.setVerbose(options.isVerbose()); - message.setNoOp(options.isNoOp()); - message.setFormatNamespace(options.getFormatNamespace()); - message.setOnBehalfOf(destination.getOnBehalfOf()); - message.setChecksumError(options.getChecksumError()); - message.setUserAgent(ClientConstants.SERVICE_NAME); - - processPost(message); - } - - } - - /** - * Process the post response. The message contains the list of arguments - * for the post. The method will then print out the details of the - * response. - * - * @param message The post options. - * @throws SWORDClientException if there is an error accessing the - * post response. - */ - protected void processPost(PostMessage message) - throws SWORDClientException { - DepositResponse response = client.postFile(message); - - System.out.println("The status is: " + client.getStatus()); - - if (response != null) { - log.debug("message is: " + response.marshall()); - - // iterate over the data and output it - SWORDEntry entry = response.getEntry(); - - - System.out.println("Id: " + entry.getId()); - Title title = entry.getTitle(); - if (title != null) { - System.out.print("Title: " + title.getContent() + " type: "); - if (title.getType() != null) { - System.out.println(title.getType().toString()); - } else { - System.out.println("Not specified."); - } - } - - // process the authors - Iterator authors = entry.getAuthors(); - while (authors.hasNext()) { - Author author = authors.next(); - System.out.println("Author - " + author.toString()); - } - - Iterator categories = entry.getCategories(); - while (categories.hasNext()) { - System.out.println("Category: " + categories.next()); - } - - Iterator contributors = entry.getContributors(); - while (contributors.hasNext()) { - Contributor contributor = contributors.next(); - System.out.println("Contributor - " + contributor.toString()); - } - - Iterator links = entry.getLinks(); - while (links.hasNext()) { - Link link = links.next(); - System.out.println(link.toString()); - } - - Generator generator = entry.getGenerator(); - if (generator != null) { - System.out.println("Generator - " + generator.toString()); - } else { - System.out.println("There is no generator"); - } - - System.out.println("Published: " + entry.getPublished()); - - Content content = entry.getContent(); - if (content != null) { - System.out.println(content.toString()); - } else { - System.out.println("There is no content element."); - } - - Rights right = entry.getRights(); - if (right != null) { - System.out.println(right.toString()); - } else { - System.out.println("There is no right element."); - } - - Summary summary = entry.getSummary(); - if (summary != null) { - - System.out.println(summary.toString()); - } else { - System.out.println("There is no summary element."); - } - - System.out.println("Update: " + entry.getUpdated()); - System.out.println("Published: " + entry.getPublished()); - System.out.println("Verbose Description: " + entry.getVerboseDescription()); - System.out.println("Treatment: " + entry.getTreatment()); - System.out.println("Packaging: " + entry.getPackaging()); - - if (entry.isNoOpSet()) { - System.out.println("NoOp: " + entry.isNoOp()); - } - } else { - System.out.println("No valid Entry document was received from the server"); - } - } - - /** - * Initialise the server. Set the server that will be connected to and - * initialise any username and password. If the username and password are - * either null or contain empty strings, the user credentials will be cleared. - * - * @param location The location to connect to. This is a URL, of the format, - * http://a.host.com:port/. The host name and port number will - * be extracted. If the port is not specified, a default port of - * 80 will be used. - * @param username The username. If this is null or an empty string, the basic - * credentials will be cleared. - * @param password The password. If this is null or an empty string, the basic - * credentials will be cleared. - * @throws MalformedURLException if there is an error processing the URL. - */ - private void initialiseServer(String location, String username, String password) - throws MalformedURLException { - URL url = new URL(location); - int port = url.getPort(); - if (port == -1) { - port = 80; - } - - client.setServer(url.getHost(), port); - - if (username != null && username.length() > 0 && - password != null && password.length() > 0) { - log.info("Setting the username/password: " + username + " " - + password); - client.setCredentials(username, password); - } else { - client.clearCredentials(); - } - } - - /** - * Read a line of text from System.in. If there is an error reading - * from the input, the prompt will be redisplayed and the user asked - * to try again. - * - * @param prompt The prompt to display before the prompt. - * @return The string that is read from the line. - */ - private String readLine(String prompt) { - BufferedReader reader = new BufferedReader(new InputStreamReader( - System.in)); - String result = null; - - boolean ok = false; - while (!ok) { - try { - System.out.print(prompt); - System.out.flush(); - result = reader.readLine(); - ok = true; - } catch (IOException ex) { - System.out.println("There was an error with your input. Please try again."); - } - } - - return result; - } - - /** - * Run the client and process the specified options. - * - * @param options The command line options. - */ - public void run(ClientOptions options) { - this.options = options; - process(); - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/DebugOutputStream.java b/dspace-sword/src/main/java/org/purl/sword/client/DebugOutputStream.java deleted file mode 100644 index dfd8b6c60f26..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/DebugOutputStream.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * A stream that will write any output to the specified panel. - * - * @author Neil Taylor - */ -public class DebugOutputStream extends OutputStream { - /** - * Panel that will display the messages. - */ - private MessageOutputPanel panel; - - /** - * Create a new instance and specify the panel that will receive the output. - * - * @param panel The panel. - */ - public DebugOutputStream(MessageOutputPanel panel) { - this.panel = panel; - } - - /** - * Override the write method from OutputStream. Capture the char and - * send it to the panel. - * - * @param arg0 The output character, expressed as an integer. - * @see java.io.OutputStream#write(int) - */ - public void write(int arg0) throws IOException { - panel.addCharacter(Character.valueOf((char) arg0)); - } - -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/MessageOutputPanel.java b/dspace-sword/src/main/java/org/purl/sword/client/MessageOutputPanel.java deleted file mode 100644 index e703f79ccccb..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/MessageOutputPanel.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ - -/** - * Copyright (c) 2007, Aberystwyth University - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - Neither the name of the Centre for Advanced Software and - * Intelligent Systems (CASIS) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -package org.purl.sword.client; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import javax.swing.JButton; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; - -/** - * Panel to display output messages. Text or characters can be sent to the - * panel for display. The panel also includes a button to clear any - * text that is currently displayed. - * - * @author Neil Taylor - */ -public class MessageOutputPanel extends JPanel - implements ActionListener { - - /** - * The text area that displays the messages. - */ - private JTextArea messages = null; - - /** - * Create a new instance and initialise the panel. - */ - public MessageOutputPanel() { - super(); - - setLayout(new GridBagLayout()); - - messages = new JTextArea(); - - JScrollPane detailsPane = new JScrollPane(messages, - JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, - JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - JButton clearButton = new JButton("Clear"); - clearButton.addActionListener(this); - - //add components and set constraints - //dpc = details pane constraint - GridBagConstraints dpc = new GridBagConstraints(); - dpc.gridx = 0; - dpc.gridy = 0; - dpc.fill = GridBagConstraints.BOTH; - dpc.weightx = 0.75; - dpc.weighty = 0.45; - dpc.gridwidth = 2; - dpc.insets = new Insets(5, 5, 5, 5); - add(detailsPane, dpc); - - //cbc = clear button constraint - GridBagConstraints cbc = new GridBagConstraints(); - cbc.gridx = 1; - cbc.gridy = 1; - cbc.insets = new Insets(0, 0, 5, 5); - cbc.anchor = GridBagConstraints.LINE_END; - add(clearButton, cbc); - - } - - /** - * Add a message to the text area. The message will be added with a carriage return. - * - * @param message The message. - */ - public void addMessage(String message) { - messages.insert(message + "\n", messages.getDocument().getLength()); - } - - /** - * Add a single character to the text area. - * - * @param character The character. - */ - public void addCharacter(Character character) { - messages.insert(character.toString(), messages.getDocument().getLength()); - } - - /** - * Clear the text from the display. - * - * @param arg0 The action event. - * - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - public void actionPerformed(ActionEvent arg0) { - messages.setText(""); - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/PostDestination.java b/dspace-sword/src/main/java/org/purl/sword/client/PostDestination.java deleted file mode 100644 index 3124f02b45d7..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/PostDestination.java +++ /dev/null @@ -1,140 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -/** - * Details for a destination. This is used to represent a destination. If - * expressed as a string, the destination looks like: - *
    - * <user>[<onBehalfOf>]:<password>@<url>
    - * 
    - * - * @author Neil Taylor - */ -public class PostDestination { - /** - * URL for the post destination. - */ - private String url; - - /** - * The username. - */ - private String username; - - /** - * The password. - */ - private String password; - - /** - * The onBehalfOf ID. - */ - private String onBehalfOf; - - /** - * Create a new instance. - */ - public PostDestination() { - // No-Op - } - - /** - * Create a new instance. - * - * @param url The url. - * @param username The username. - * @param password The password. - * @param onBehalfOf The onBehalfOf id. - */ - public PostDestination(String url, String username, String password, String onBehalfOf) { - this.url = url; - this.username = username; - this.password = password; - this.onBehalfOf = onBehalfOf; - } - - /** - * @return the url - */ - public String getUrl() { - return url; - } - - /** - * @param url the url to set - */ - public void setUrl(String url) { - this.url = url; - } - - /** - * @return the username - */ - public String getUsername() { - return username; - } - - /** - * @param username the username to set - */ - public void setUsername(String username) { - this.username = username; - } - - /** - * @return the password - */ - public String getPassword() { - return password; - } - - /** - * @param password the password to set - */ - public void setPassword(String password) { - this.password = password; - } - - /** - * @return the onBehalfOf - */ - public String getOnBehalfOf() { - return onBehalfOf; - } - - /** - * @param onBehalfOf the onBehalfOf to set - */ - public void setOnBehalfOf(String onBehalfOf) { - this.onBehalfOf = onBehalfOf; - } - - /** - * Create a string representation of this object. - * - * @return The string. - */ - public String toString() { - StringBuffer buffer = new StringBuffer(); - buffer.append(username); - if (onBehalfOf != null) { - buffer.append("["); - buffer.append(onBehalfOf); - buffer.append("]"); - } - - if (password != null) { - buffer.append(":******"); - } - buffer.append("@"); - buffer.append(url); - - return buffer.toString(); - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/PostDialog.java b/dspace-sword/src/main/java/org/purl/sword/client/PostDialog.java deleted file mode 100644 index 84815b327e3b..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/PostDialog.java +++ /dev/null @@ -1,599 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ - -/** - * Copyright (c) 2007, Aberystwyth University - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - Neither the name of the Centre for Advanced Software and - * Intelligent Systems (CASIS) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -package org.purl.sword.client; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JScrollPane; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -/** - * Dialog for users to enter details of post destinations. - * - * @author Neil Taylor - */ -public class PostDialog - implements ActionListener, ChangeListener { - /** - * label for the browse command. - */ - protected static final String BROWSE = "browse"; - - /** - * label for the add command. - */ - protected static final String ADD = "add"; - - /** - * label for the edit command. - */ - protected static final String EDIT = "edit"; - - /** - * label for the delete command. - */ - protected static final String DELETE = "delete"; - - /** - * label for the clear command. - */ - protected static final String CLEAR = "clear"; - - /** - * Username combo box. - */ - private SWORDComboBox username; - - /** - * Post Location combo box. - */ - private SWORDComboBox postLocation; - - /** - * Password field. - */ - private JPasswordField password; - - /** - * The file combo box. - */ - private SWORDComboBox file; - - /** - * The filetype combo box. - */ - private SWORDComboBox fileType; - - /** - * The onBehalfOf combo box. - */ - private SWORDComboBox onBehalfOf; - - /** - * The md5 checkbox. - */ - private JCheckBox useMD5; - - /** - * The corruptMD5 checkbox. - */ - private JCheckBox corruptMD5; - - /** - * The corruptRequest checkbox. - */ - private JCheckBox corruptRequest; - - /** - * The useNoOp checkbox. - */ - private JCheckBox useNoOp; - - /** - * The verbose checkbox. - */ - private JCheckBox useVerbose; - - /** - * The format namespace combo box. - */ - private SWORDComboBox formatNamespace; - - /** - * The list of post destinations. - */ - private JList list; - - /** - * The parent frame for the dialog that is displayed. - */ - private JFrame parentFrame = null; - - /** - * Array that lists the labels for the buttons on the panel. - */ - private static Object[] options = {"Post File", "Cancel"}; - - /** - * The panel that holds the controls to show. - */ - private JPanel controls = null; - - /** - * - * @param parentFrame the parent of this dialog. - */ - public PostDialog(JFrame parentFrame) { - this.parentFrame = parentFrame; - controls = createControls(); - } - - /** - * Show the dialog with ok and cancel options. - * @return The return value from displaying JOptionPane. Either - * JOptionPane.OK_OPTION or JOptionPane.CANCEL_OPTION. - */ - public int show() { - int result = JOptionPane.showOptionDialog(parentFrame, - controls, - "Post Document", - JOptionPane.OK_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE, - null, - options, - null); - - if (result == JOptionPane.OK_OPTION) { - // update the combo boxes with the values - username.updateList(); - file.updateList(); - fileType.updateList(); - onBehalfOf.updateList(); - formatNamespace.updateList(); - } - - return result; - } - - /** - * Create the controls for the main panel. - * - * @return The panel. - */ - protected final JPanel createControls() { - file = new SWORDComboBox(); - JPanel filePanel = new JPanel(new BorderLayout()); - filePanel.add(file, BorderLayout.CENTER); - JButton browse = new JButton("Browse..."); - browse.setActionCommand(BROWSE); - browse.addActionListener(this); - - filePanel.add(browse, BorderLayout.SOUTH); - - fileType = new SWORDComboBox(); - String type = "application/zip"; - fileType.addItem(type); - fileType.setSelectedItem(type); - - // controls that will be used in the second dialog - postLocation = new SWORDComboBox(); - username = new SWORDComboBox(); - password = new JPasswordField(); - onBehalfOf = new SWORDComboBox(); - - - useMD5 = new JCheckBox(); - useMD5.addChangeListener(this); - corruptMD5 = new JCheckBox(); - corruptRequest = new JCheckBox(); - useNoOp = new JCheckBox(); - useVerbose = new JCheckBox(); - formatNamespace = new SWORDComboBox(); - - JLabel fileLabel = new JLabel("File:", JLabel.TRAILING); - JLabel fileTypeLabel = new JLabel("File Type:", JLabel.TRAILING); - JLabel useMD5Label = new JLabel("Use MD5:", JLabel.TRAILING); - JLabel corruptMD5Label = new JLabel("Corrupt MD5:", JLabel.TRAILING); - JLabel corruptRequestLabel = new JLabel("Corrupt Request:", JLabel.TRAILING); - //JLabel corruptMD5Label = new JLabel("Corrupt MD5:", JLabel.TRAILING); - JLabel useNoOpLabel = new JLabel("Use noOp:", JLabel.TRAILING); - JLabel useVerboseLabel = new JLabel("Use verbose:", JLabel.TRAILING); - JLabel formatNamespaceLabel = new JLabel("X-Packaging:", JLabel.TRAILING); - JLabel userAgentLabel = new JLabel("User Agent:", JLabel.TRAILING); - JLabel userAgentNameLabel = new JLabel(ClientConstants.SERVICE_NAME, JLabel.LEADING); - - SWORDFormPanel panel = new SWORDFormPanel(); - panel.addFirstRow(new JLabel("Please enter the details for the post operation")); - - JPanel destinations = createDestinationsPanel(); - - panel.addRow(new JLabel("Destinations:"), destinations); - panel.addRow(fileLabel, filePanel); - panel.addRow(fileTypeLabel, fileType); - panel.addRow(useMD5Label, useMD5); - panel.addRow(corruptMD5Label, corruptMD5); - panel.addRow(corruptRequestLabel, corruptRequest); - panel.addRow(useNoOpLabel, useNoOp); - panel.addRow(useVerboseLabel, useVerbose); - panel.addRow(formatNamespaceLabel, formatNamespace); - panel.addRow(userAgentLabel, userAgentNameLabel); - - return panel; - } - - /** - * Create the destinations panel. This contains a list and four buttons - * to operate on values in the list. - * - * @return The panel containing the controls. - */ - protected JPanel createDestinationsPanel() { - DefaultListModel model = new DefaultListModel(); - list = new JList(model); - JScrollPane jsp = new JScrollPane(list); - - JPanel destinations = new JPanel(new BorderLayout()); - destinations.add(jsp, BorderLayout.CENTER); - JPanel destinationButtons = new JPanel(); - - JButton addButton = new JButton("Add"); - addButton.setActionCommand(ADD); - addButton.addActionListener(this); - - JButton editButton = new JButton("Edit"); - editButton.setActionCommand(EDIT); - editButton.addActionListener(this); - - JButton deleteButton = new JButton("Delete"); - deleteButton.setActionCommand(DELETE); - deleteButton.addActionListener(this); - - JButton clearButton = new JButton("Clear"); - clearButton.setActionCommand(CLEAR); - clearButton.addActionListener(this); - - destinationButtons.add(addButton); - destinationButtons.add(editButton); - destinationButtons.add(deleteButton); - destinationButtons.add(clearButton); - - destinations.add(destinationButtons, BorderLayout.SOUTH); - - return destinations; - } - - /** - * Handle the button click to select a file to upload. - */ - public void actionPerformed(ActionEvent evt) { - String cmd = evt.getActionCommand(); - - if (BROWSE.equals(cmd)) { - JFileChooser chooser = new JFileChooser(); - chooser.setCurrentDirectory(new File(System.getProperty("user.dir"))); - int returnVal = chooser.showOpenDialog(parentFrame); - if (returnVal == JFileChooser.APPROVE_OPTION) { - file.setSelectedItem(chooser.getSelectedFile().getAbsolutePath()); - } - } else if (ADD.equals(cmd)) { - PostDestination dest = showDestinationDialog(null); - if (dest != null) { - ((DefaultListModel) list.getModel()).addElement(dest); - } - } else if (EDIT.equals(cmd)) { - PostDestination dest = (PostDestination) list.getSelectedValue(); - if (dest != null) { - showDestinationDialog(dest); - list.repaint(); - } - } else if (DELETE.equals(cmd)) { - if (list.getSelectedIndex() != -1) { - ((DefaultListModel) list.getModel()).removeElementAt(list.getSelectedIndex()); - } - } else if (CLEAR.equals(cmd)) { - ((DefaultListModel) list.getModel()).clear(); - } - } - - /** - * Show the destination dialog. This is used to enter the URL, - * username, password and onBehalfOf name for a destination. - * - * @param destination The post destination. If this is not null, the values - * in the object are used to set the current values - * in the dialog controls. - * @return The post destination value. - */ - public PostDestination showDestinationDialog(PostDestination destination) { - SWORDFormPanel panel = new SWORDFormPanel(); - panel.addFirstRow(new JLabel("Please enter the details for the post operation")); - - JLabel postLabel = new JLabel("Post Location:", JLabel.TRAILING); - JLabel userLabel = new JLabel("Username:", JLabel.TRAILING); - JLabel passwordLabel = new JLabel("Password:", JLabel.TRAILING); - JLabel onBehalfOfLabel = new JLabel("On Behalf Of:", JLabel.TRAILING); - - panel.addRow(postLabel, postLocation); - panel.addRow(userLabel, username); - panel.addRow(passwordLabel, password); - panel.addRow(onBehalfOfLabel, onBehalfOf); - - if (destination != null) { - postLocation.insertItem(destination.getUrl()); - username.insertItem(destination.getUsername()); - password.setText(destination.getPassword()); - onBehalfOf.insertItem(destination.getOnBehalfOf()); - } else { - String s = ""; - postLocation.insertItem(s); - //postLocation.setSelectedItem(s); - username.insertItem(s); - username.setSelectedItem(s); - password.setText(s); - onBehalfOf.insertItem(s); - onBehalfOf.setSelectedItem(s); - } - - int result = JOptionPane.showOptionDialog(null, - panel, - "Destination", - JOptionPane.OK_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE, - null, - new String[] {"OK", "Cancel"}, - null); - - if (result == JOptionPane.OK_OPTION) { - postLocation.updateList(); - username.updateList(); - onBehalfOf.updateList(); - - if (destination == null) { - destination = new PostDestination(); - } - - destination.setUrl(postLocation.getText()); - destination.setUsername(username.getText()); - String pass = new String(password.getPassword()); - if (pass.length() > 0) { - destination.setPassword(pass); - } else { - destination.setPassword(null); - } - - String obo = onBehalfOf.getText(); - if (obo.length() > 0) { - destination.setOnBehalfOf(onBehalfOf.getText()); - } else { - destination.setOnBehalfOf(null); - } - - } - - return destination; - } - - /** - * Get the list of Post Destinations. - * @return The destinations. - */ - public PostDestination[] getDestinations() { - DefaultListModel model = (DefaultListModel) list.getModel(); - PostDestination[] destinations = new PostDestination[model.size()]; - for (int i = 0; i < model.size(); i++) { - destinations[i] = (PostDestination) model.get(i); - } - return destinations; - } - - /** - * Get the file details. - * @return The value. - */ - public String getFile() { - return file.getText(); - } - - /** - * Get the filetype value. - * @return The value. - */ - public String getFileType() { - return fileType.getText(); - } - - /** - * Get the onBehalfOf value. - * @return The value. - */ - public String getOnBehalfOf() { - return onBehalfOf.getText(); - } - - /** - * Get the format namespace value. - * @return The value. - */ - public String getFormatNamespace() { - return formatNamespace.getText(); - } - - /** - * Determine if the MD5 checkbox is selected. - * - * @return True if the MD5 checkbox is selected. - */ - public boolean useMd5() { - return useMD5.isSelected(); - } - - /** - * Determine if the noOp checkbox is selected. - * - * @return True if the checkbox is selected. - */ - public boolean useNoOp() { - return useNoOp.isSelected(); - } - - /** - * Determine if the verbose checkbox is selected. - * - * @return True if the checkbox is selected. - */ - public boolean useVerbose() { - return useVerbose.isSelected(); - } - - /** - * Get the post location. - * @return The post location. - */ - public String getPostLocation() { - return postLocation.getText(); - } - - /** - * Determine if the MD5 hash should be corrupted. - * @return True if the corrupt MD5 checkbox is selected. The MD5 checkbox - * must also be selected. - */ - public boolean corruptMD5() { - return (corruptMD5.isEnabled() && corruptMD5.isSelected()); - } - - /** - * Determine if the POST request should be corrupted. - * @return True if the corrupt request checkbox is selected. - */ - public boolean corruptRequest() { - return (corruptRequest.isSelected()); - } - - /** - * Detect a state change event for the checkbox. - * - * @param evt The event. - */ - public void stateChanged(ChangeEvent evt) { - corruptMD5.setEnabled(useMD5.isSelected()); - } - - /** - * Add a list of user ids. - * - * @param users The user ids. - */ - public void addUserIds(String[] users) { - username.insertItems(users); - } - - /** - * Add a list of deposit URLs. - * - * @param deposits The URLs. - */ - public void addDepositUrls(String[] deposits) { - postLocation.insertItems(deposits); - } - - /** - * Add a list of onBehalfOf names. - * - * @param users The names. - */ - public void addOnBehalfOf(String[] users) { - onBehalfOf.insertItems(users); - } - - /** - * Add the list of formatNamespace strings. - * - * @param namespaces list of strings. - */ - public void addFormatNamespaces(String[] namespaces) { - formatNamespace.insertItems(namespaces); - } - - /** - * Add a list of file types. - * - * @param types The file types. - */ - public void addFileTypes(String[] types) { - fileType.insertItems(types); - } - - /** - * Add a list of file names. - * @param files The list of files. - */ - public void addFiles(String[] files) { - file.insertItems(files); - } - - /** - * Set the deposit location. - * - * @param location The location. - */ - public void setDepositLocation(String location) { - postLocation.insertItem(location); - postLocation.setSelectedItem(location); - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/PostMessage.java b/dspace-sword/src/main/java/org/purl/sword/client/PostMessage.java deleted file mode 100644 index a44f21ce2b88..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/PostMessage.java +++ /dev/null @@ -1,344 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ - -/** - * Copyright (c) 2007, Aberystwyth University - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - Neither the name of the Centre for Advanced Software and - * Intelligent Systems (CASIS) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -package org.purl.sword.client; - -import java.io.File; - -/** - * Represents the details of a post to a server. The message holds all of the possible values - * that are to be sent from the client to the server. Not all elements of the message - * must be filled in. Any required fields are defined in the current SWORD specification. - * - * @author Neil Taylor - */ -public class PostMessage { - /** - * The local filepath for the file to upload/deposit. - */ - private String filepath; - - /** - * The URL of the destination server. - */ - private String destination; - - /** - * The filetype of the package that is to be uploaded. - */ - private String filetype; - - /** - * The string with the username if the deposit is on behalf of another user. - */ - private String onBehalfOf; - - /** - * True if an MD5 checksum should be sent with the deposit. - */ - private boolean useMD5; - - /** - * True if the deposit is a test and should not result in an actual deposit. - */ - private boolean noOp; - - /** - * True if the verbose operation is requested. - */ - private boolean verbose; - - /** - * The packaging format for the deposit. - */ - private String packaging; - - /** - * True if the deposit should simulate a checksum error. The client should check this - * field to determine if a correct MD5 checksum should be sent or whether the checksum should - * be modified so that it generates an error at the server. - */ - private boolean checksumError; - - /** - * True if the deposit should corrupt the POST header. The client should check this - * field to determine if a correct header should be sent or whether the header should - * be modified so that it generates an error at the server. - */ - private boolean corruptRequest; - - /** - * The Slug header value. - */ - private String slug; - - /** - * The user agent name - */ - private String userAgent; - - /** - * Get the filepath. - * - * @return The filepath. - */ - public String getFilepath() { - return filepath; - } - - /** - * Get the filename. This is the last element of the filepath - * that has been set in this class. - * - * @return filename - */ - public String getFilename() { - File file = new File(filepath); - return file.getName(); - } - - /** - * Set the filepath. - * - * @param filepath The filepath. - */ - public void setFilepath(String filepath) { - this.filepath = filepath; - } - - /** - * Get the destination collection. - * - * @return The collection. - */ - public String getDestination() { - return destination; - } - - /** - * Set the destination collection. - * - * @param destination The destination. - */ - public void setDestination(String destination) { - this.destination = destination; - } - - /** - * Get the filetype. - * @return The filetype. - */ - public String getFiletype() { - return filetype; - } - - /** - * Set the filetype. - * - * @param filetype The filetype. - */ - public void setFiletype(String filetype) { - this.filetype = filetype; - } - - /** - * Get the onBehalfOf value. - * - * @return The value. - */ - public String getOnBehalfOf() { - return onBehalfOf; - } - - /** - * Set the onBehalfOf value. - * - * @param onBehalfOf The value. - */ - public void setOnBehalfOf(String onBehalfOf) { - this.onBehalfOf = onBehalfOf; - } - - /** - * Get the MD5 status. - * @return The value. - */ - public boolean isUseMD5() { - return useMD5; - } - - /** - * Set the md5 state. - * - * @param useMD5 True if the message should use an MD5 checksum. - */ - public void setUseMD5(boolean useMD5) { - this.useMD5 = useMD5; - } - - /** - * Get the no-op state. - * - * @return The value. - */ - public boolean isNoOp() { - return noOp; - } - - /** - * Set the no-op state. - * - * @param noOp The no-op. - */ - public void setNoOp(boolean noOp) { - this.noOp = noOp; - } - - /** - * Get the verbose value. - * - * @return The value. - */ - public boolean isVerbose() { - return verbose; - } - - /** - * Set the verbose state. - * - * @param verbose True if the post message should send a - * verbose header. - */ - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - /** - * Get the packaging format. - * - * @return The value. - */ - public String getPackaging() { - return packaging; - } - - /** - * Set the packaging format. - * - * @param packaging The packaging format. - */ - public void setFormatNamespace(String packaging) { - this.packaging = packaging; - } - - /** - * Get the status of the checksum error. - * - * @return True if the client should simulate a checksum error. - */ - public boolean getChecksumError() { - return checksumError; - } - - /** - * Set the state of the checksum error. - * - * @param checksumError True if the item should include a checksum error. - */ - public void setChecksumError(boolean checksumError) { - this.checksumError = checksumError; - } - - /** - * Get the status of the corrupt request flag. - * - * @return True if the client should corrupt the POST header. - */ - public boolean getCorruptRequest() { - return corruptRequest; - } - - /** - * Set the state of the corrupt request flag. - * - * @param corruptRequest True if the item should corrupt the POST header. - */ - public void setCorruptRequest(boolean corruptRequest) { - this.corruptRequest = corruptRequest; - } - - /** - * Set the Slug value. - * - * @param slug The value. - */ - public void setSlug(String slug) { - this.slug = slug; - } - - /** - * Get the Slug value. - * - * @return The Slug. - */ - public String getSlug() { - return this.slug; - } - - /** - * @return the userAgent - */ - public String getUserAgent() { - return userAgent; - } - - /** - * Set the user agent - * - * @param userAgent the userAgent to set - */ - public void setUserAgent(String userAgent) { - this.userAgent = userAgent; - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/PropertiesDialog.java b/dspace-sword/src/main/java/org/purl/sword/client/PropertiesDialog.java deleted file mode 100644 index 6d43cb68ef10..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/PropertiesDialog.java +++ /dev/null @@ -1,240 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -import java.awt.BorderLayout; -import java.util.Enumeration; -import java.util.Properties; -import javax.swing.DefaultCellEditor; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.TableCellEditor; - -/** - * Dialog that is used to edit the collection of properties. - * - * @author Neil Taylor, Suzana Barreto - */ -public class PropertiesDialog { - /** - * The parent frame for the dialog that is displayed. - */ - private JFrame parentFrame = null; - - /** - * Array that lists the labels for the buttons on the panel. - */ - private static Object[] options = {"OK", "Cancel"}; - - /** - * The panel that holds the controls to show. - */ - private JPanel controls = null; - - /** - * The configuration properties - */ - private Properties properties = null; - - /** - * Table that is used to display the list of properties. - */ - private JTable propertiesTable; - - /** - * Create a new instance. - * - * @param parentFrame The parent frame for the dialog. - * @param props The properties lisst to display - */ - public PropertiesDialog(JFrame parentFrame, Properties props) { - this.parentFrame = parentFrame; - properties = props; - controls = createControls(); - } - - /** - * Create the controls that are to be displayed in the system. - * - * @return A panel that contains the controls. - */ - protected final JPanel createControls() { - JPanel panel = new JPanel(new BorderLayout()); - propertiesTable = new JTable(new PropertiesModel()); - ((DefaultCellEditor) propertiesTable.getDefaultEditor(String.class)).setClickCountToStart(1); - JScrollPane scrollpane = new JScrollPane(propertiesTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, - JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - panel.add(scrollpane, BorderLayout.CENTER); - return panel; - } - - - /** - * Show the dialog and return the status code. - * - * @return The status code returned from the dialog. - */ - public int show() { - int result = JOptionPane.showOptionDialog(parentFrame, - controls, - "Edit Properties", - JOptionPane.OK_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE, - null, - options, - null); - - // cancel any edit in the table. If there is a cell editing, the getEditingColumn will - // return a non-negative column number. This can be used to retreive the cell editor. - // The code then gets the default editor and calls the stopCellEditing. If custom - // editors are used, an additional check must be made to get the cell editor - // for a specific cell. - int column = propertiesTable.getEditingColumn(); - - if (column > -1) { - TableCellEditor editor = propertiesTable.getDefaultEditor(propertiesTable.getColumnClass(column)); - if (editor != null) { - editor.stopCellEditing(); - } - } - - return result; - } - - - /** - * A table model that is used to show the properties. The model links directly - * to the underlying properties object. As changes are made in the table, the - * corresponding changes are made in the properties object. The user can only - * edit the value column in the table. - */ - public class PropertiesModel extends AbstractTableModel { - /** - * Column names. - */ - private String columns[] = {"Property Name", "Value"}; - - /** - * Create a new instance of the model. If no properties object exists, - * a default model is created. Note, this will allow the table to - * continue editing, although this value will not be passed back to - * the calling window. - */ - public PropertiesModel() { - super(); - if (properties == null) { - properties = new Properties(); - } - } - - /** - * Get the number of columns. - * - * @return The number of columns. - */ - public int getColumnCount() { - return columns.length; - } - - /** - * Get the number of rows. - * - * @return The number of rows. - */ - public int getRowCount() { - return properties.size(); - } - - /** - * Get the value that is at the specified cell. - * - * @param row The row for the cell. - * @param col The column for the cell. - * @return The data value from the properties. - */ - public Object getValueAt(int row, int col) { - if (col == 0) { - return getKeyValue(row); - } else { - String key = getKeyValue(row); - return properties.get(key); - } - } - - /** - * Retrieve the column name for the specified column. - * - * @param col The column number. - * @return The column name. - */ - public String getColumnName(int col) { - return columns[col]; - } - - /** - * Retrieve the column class. - * - * @param col The column number. - * @return The class for the object found at the column position. - */ - public Class getColumnClass(int col) { - return getValueAt(0, col).getClass(); - } - - /** - * Determine if the cell can be edited. This model will only - * allow the second column to be edited. - * - * @param row The cell row. - * @param col The cell column. - * @return True if the cell can be edited. Otherwise, false. - */ - public boolean isCellEditable(int row, int col) { - if (col == 1) { - return true; - } - return false; - } - - /** - * Set the value for the specified cell. - * - * @param value The value to set. - * @param row The row for the cell. - * @param col The column. - */ - public void setValueAt(Object value, int row, int col) { - String key = getKeyValue(row); - properties.setProperty(key, ((String) value)); - fireTableCellUpdated(row, col); - } - - /** - * Get the Key value for the specified row. - * - * @param row The row. - * @return A string that shows the key value. - */ - public String getKeyValue(int row) { - int count = 0; - Enumeration k = properties.keys(); - while (k.hasMoreElements()) { - String key = (String) k.nextElement(); - if (count == row) { - return key; - } - count++; - } - return null; - } - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/SWORDClient.java b/dspace-sword/src/main/java/org/purl/sword/client/SWORDClient.java deleted file mode 100644 index 0df7fd53104a..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/SWORDClient.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -import org.purl.sword.base.DepositResponse; -import org.purl.sword.base.ServiceDocument; - -/** - * Interface for any SWORD client implementation. - */ -public interface SWORDClient { - /** - * Set the server that is to be contacted on the next access. - * - * @param server The name of the server, e.g. www.aber.ac.uk - * @param port The port number, e.g. 80. - */ - public void setServer(String server, int port); - - /** - * Set the user credentials that are to be used for subsequent accesses. - * - * @param username The username. - * @param password The password. - */ - public void setCredentials(String username, String password); - - /** - * Clear the credentials settings on the client. - */ - public void clearCredentials(); - - /** - * Set the proxy that is to be used for subsequent accesses. - * - * @param host The host name, e.g. cache.host.com. - * @param port The port, e.g. 8080. - */ - public void setProxy(String host, int port); - - /** - * Get the status result returned from the most recent network test. - * - * @return The status code and message. - */ - public Status getStatus(); - - /** - * Get a service document, specified in the URL. - * - * @param url The URL to connect to. - * @return A ServiceDocument that contains the Service details that were - * obained from the specified URL. - * @throws SWORDClientException If there is an error accessing the - * URL. - */ - public ServiceDocument getServiceDocument(String url) throws SWORDClientException; - - /** - * Get a service document, specified in the URL. The document is accessed on - * behalf of the specified user. - * - * @param url The URL to connect to. - * @param onBehalfOf The username for the onBehalfOf access. - * @return A ServiceDocument that contains the Service details that were - * obtained from the specified URL. - * @throws SWORDClientException If there is an error accessing the URL. - */ - public ServiceDocument getServiceDocument(String url, String onBehalfOf) throws SWORDClientException; - - /** - * Post a file to the specified destination URL. - * - * @param message The message that defines the requirements for the operation. - * @return A DespoitResponse if the response is successful. If there was an error, - * null should be returned. - * @throws SWORDClientException If there is an error accessing the URL. - */ - public DepositResponse postFile(PostMessage message) throws SWORDClientException; -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/SWORDClientException.java b/dspace-sword/src/main/java/org/purl/sword/client/SWORDClientException.java deleted file mode 100644 index 1355b9d4ab61..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/SWORDClientException.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -/** - * Represents an exception thrown by the SWORD Client. - * - * @author Neil Taylor - */ -public class SWORDClientException extends Exception { - /** - * Create a new exception, without a message. - */ - public SWORDClientException() { - super(); - } - - /** - * Create a new exception with the specified message. - * - * @param message The message. - */ - public SWORDClientException(String message) { - super(message); - } - - /** - * Create a new exception with the specified message and set - * the exception that generated this error. - * - * @param message The message. - * @param cause The original exception. - */ - public SWORDClientException(String message, Exception cause) { - super(message, cause); - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/SWORDComboBox.java b/dspace-sword/src/main/java/org/purl/sword/client/SWORDComboBox.java deleted file mode 100644 index 42fcc082ff58..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/SWORDComboBox.java +++ /dev/null @@ -1,129 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ - -/** - * Copyright (c) 2007, Aberystwyth University - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - Neither the name of the Centre for Advanced Software and - * Intelligent Systems (CASIS) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -package org.purl.sword.client; - -import javax.swing.JComboBox; - -/** - * An extension of the JComboBox class. This adds a method that - * can update the list of items with the item. The update will only - * work on combo boxes that are set to editable. - * - * @author Neil Taylor - */ -public class SWORDComboBox extends JComboBox { - /** - * Create an instance of the SWORD Combo box. - */ - public SWORDComboBox() { - super(); - setEditable(true); - } - - /** - * Update the list for the Combo box with the currently selected - * item. This will only add an item to the list if: i) the control - * is editable, ii) the selected item is not empty and iii) the - * item is not already in the list. - */ - public void updateList() { - Object s = getSelectedItem(); - - if (!isEditable() || s == null || ((String) s).trim().length() == 0) { - // don't update with an empty item or if the combo box is not editable. - return; - } - - insertItem(s); - } - - /** - * Insert an item into the combo box. This will only be added - * if the item is not already present in the combo box. - * - * @param newItem The item to insert. - */ - public void insertItem(Object newItem) { - int count = getItemCount(); - - boolean found = false; - - for (int i = 0; i < count && !found; i++) { - Object item = getItemAt(i); - if (item != null && item.equals(newItem)) { - found = true; - } - } - - if (!found) { - addItem(newItem); - } - } - - /** - * Insert multiple items into the combo box. - * - * @param items The array of items. - */ - public void insertItems(String[] items) { - for (String item : items) { - insertItem(item); - } - } - - /** - * Get the text of the currently selected item in the combo box. - * @return The text. null is returned if no item - * is selected. - */ - public String getText() { - Object o = getSelectedItem(); - if (o != null) { - return o.toString().trim(); - } - - return null; - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/SWORDFormPanel.java b/dspace-sword/src/main/java/org/purl/sword/client/SWORDFormPanel.java deleted file mode 100644 index 81de59ae68c2..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/SWORDFormPanel.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import javax.swing.JPanel; - -/** - * Utility class. Creates a two column form. The left column is used to show - * the label for the row. The right column is used to show the control, e.g. - * text box, combo box or checkbox, for the row. - * - * @author Neil Taylor - */ -public class SWORDFormPanel extends JPanel { - /** - * Constraints used to control the layout on the panel. - */ - private GridBagConstraints labelConstraints; - - /** - * Constraints used to control the layout of the input controls on the panel. - */ - private GridBagConstraints controlConstraints; - - /** - * Index to the next row. - */ - private int rowIndex = 0; - - /** - * Insets for the top row of the label column. - */ - private Insets labelTop = new Insets(10, 10, 0, 0); - - /** - * Insets for the top row of the control column. - */ - private Insets controlTop = new Insets(10, 4, 0, 10); - - /** - * Insets for a general row in the label column. - */ - private Insets labelGeneral = new Insets(3, 10, 0, 0); - - /** - * Insets for a general row in the control column. - */ - private Insets controlGeneral = new Insets(3, 4, 0, 10); - - /** - * Create a new instance of the class. - */ - public SWORDFormPanel() { - super(); - setLayout(new GridBagLayout()); - - labelConstraints = new GridBagConstraints(); - labelConstraints.fill = GridBagConstraints.NONE; - labelConstraints.anchor = GridBagConstraints.LINE_END; - labelConstraints.weightx = 0.1; - - controlConstraints = new GridBagConstraints(); - controlConstraints.fill = GridBagConstraints.HORIZONTAL; - controlConstraints.weightx = 0.9; - } - - /** - * Add the specified component as the first row. It will occupy two - * columns. - * - * @param one The control to add. - */ - public void addFirstRow(Component one) { - addRow(one, null, labelTop, controlTop); - } - - /** - * Add the specified components as the first row in the form. - * - * @param one The label component. - * @param two The control component. - */ - public void addFirstRow(Component one, Component two) { - addRow(one, two, labelTop, controlTop); - } - - /** - * Add a component to the general row. This will be added in the label column. - * - * @param one The component. - */ - public void addRow(Component one) { - addRow(one, null); - } - - /** - * Add a component to the general row. - * - * @param one The component to add to the label column. - * @param two The component to add to the control column. - */ - public void addRow(Component one, Component two) { - addRow(one, two, labelGeneral, controlGeneral); - } - - /** - * Add a row to the table. - * - * @param one The component to display in the label column. - * @param two The component to display in the control column. - * @param labels The insets for the label column. - * @param controls The insets for the controls column. - */ - protected void addRow(Component one, Component two, Insets labels, Insets controls) { - labelConstraints.insets = labels; - labelConstraints.gridx = 0; - labelConstraints.gridy = rowIndex; - if (two == null) { - labelConstraints.gridwidth = 2; - } else { - labelConstraints.gridwidth = 1; - } - - add(one, labelConstraints); - - if (two != null) { - controlConstraints.insets = controls; - controlConstraints.gridx = 1; - controlConstraints.gridy = rowIndex; - add(two, controlConstraints); - } - - rowIndex++; - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/ServiceDialog.java b/dspace-sword/src/main/java/org/purl/sword/client/ServiceDialog.java deleted file mode 100644 index 03489f0d2e77..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/ServiceDialog.java +++ /dev/null @@ -1,227 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ - -/** - * Copyright (c) 2007, Aberystwyth University - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - Neither the name of the Centre for Advanced Software and - * Intelligent Systems (CASIS) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -package org.purl.sword.client; - -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; - -/** - * Dialog that prompts the user to enter the details for a service - * document location. - * - * @author Neil Taylor - */ -public class ServiceDialog { - /** - * The username. - */ - private SWORDComboBox username; - - /** - * The password. - */ - private JPasswordField password; - - /** - * Holds the URL for the collection. - */ - private SWORDComboBox location; - - /** - * The combo box that shows the list of onBehalfOf items. - */ - private SWORDComboBox onBehalfOf; - - /** - * Parent frame for the dialog. - */ - private JFrame parentFrame = null; - - /** - * The panel that holds the controls. - */ - private JPanel controls = null; - - /** - * List of buttons. - */ - private static Object[] options = {"Get Service Document", "Cancel"}; - - /** - * Create a new instance. - * - * @param parentFrame The parent frame. The dialog will be shown over the - * centre of this frame. - */ - public ServiceDialog(JFrame parentFrame) { - this.parentFrame = parentFrame; - controls = createControls(); - } - - /** - * Show the dialog. - * - * @return The close option. This is one of the dialog options from - * JOptionPane. - */ - public int show() { - int result = JOptionPane.showOptionDialog(parentFrame, - controls, - "Get Service Document", - JOptionPane.OK_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE, - null, - options, - options[1]); - - if (result == JOptionPane.OK_OPTION) { - // update the combo boxes with the values - username.updateList(); - location.updateList(); - onBehalfOf.updateList(); - } - - return result; - } - - /** - * Create the controls that are displayed in the dialog. - * - * @return The panel that contains the controls. - */ - protected final JPanel createControls() { - username = new SWORDComboBox(); - username.setEditable(true); - password = new JPasswordField(); - location = new SWORDComboBox(); - location.setEditable(true); - onBehalfOf = new SWORDComboBox(); - onBehalfOf.setEditable(true); - - JLabel userLabel = new JLabel("Username:", JLabel.TRAILING); - JLabel passwordLabel = new JLabel("Password:", JLabel.TRAILING); - JLabel locationLabel = new JLabel("Location:", JLabel.TRAILING); - JLabel onBehalfOfLabel = new JLabel("On Behalf Of:", JLabel.TRAILING); - - SWORDFormPanel panel = new SWORDFormPanel(); - panel.addFirstRow(userLabel, username); - panel.addRow(passwordLabel, password); - panel.addRow(locationLabel, location); - panel.addRow(onBehalfOfLabel, onBehalfOf); - - return panel; - } - - /** - * Get the username from the controls on the dialog. - * - * @return The username. - */ - public String getUsername() { - return username.getText(); - } - - /** - * Get the password from the dialog. - * - * @return The password. - */ - public String getPassword() { - return new String(password.getPassword()); - } - - /** - * The location from the dialog. - * - * @return The location. - */ - public String getLocation() { - return location.getText(); - } - - /** - * The onBehalfOf value from the dialog. - * - * @return The onBehalfOf value. - */ - public String getOnBehalfOf() { - String text = onBehalfOf.getText().trim(); - if (text.length() == 0) { - return null; - } - return text; - } - - /** - * Add the list of user ids to the dialog. - * - * @param users The list of user ids. - */ - public void addUserIds(String[] users) { - username.insertItems(users); - } - - /** - * Add the list of service URLs. - * - * @param services The service URLs. - */ - public void addServiceUrls(String[] services) { - location.insertItems(services); - } - - /** - * Add a list of onBehalfOf names. - * - * @param users The list of onBehalfOf items. - */ - public void addOnBehalfOf(String[] users) { - onBehalfOf.insertItems(users); - } - -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/ServicePanel.java b/dspace-sword/src/main/java/org/purl/sword/client/ServicePanel.java deleted file mode 100644 index bc3031c33354..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/ServicePanel.java +++ /dev/null @@ -1,843 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ - -/** - * Copyright (c) 2007, Aberystwyth University - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - Neither the name of the Centre for Advanced Software and - * Intelligent Systems (CASIS) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -package org.purl.sword.client; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JEditorPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTree; -import javax.swing.ToolTipManager; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; - -import org.purl.sword.atom.Author; -import org.purl.sword.atom.Content; -import org.purl.sword.atom.Contributor; -import org.purl.sword.atom.Generator; -import org.purl.sword.atom.Link; -import org.purl.sword.atom.TextConstruct; -import org.purl.sword.base.Collection; -import org.purl.sword.base.DepositResponse; -import org.purl.sword.base.SWORDEntry; -import org.purl.sword.base.Service; -import org.purl.sword.base.ServiceDocument; -import org.purl.sword.base.SwordAcceptPackaging; -import org.purl.sword.base.Workspace; - -/** - * The main panel for the GUI client. This contains the top-two sub-panels: the - * tree and the text area to show the details of the selected node. - * - * @author Neil Taylor - */ -public class ServicePanel extends JPanel - implements TreeSelectionListener { - /** - * The top level item in the tree that lists services. - */ - DefaultMutableTreeNode top; - - /** - * The tree model used to display the items. - */ - DefaultTreeModel treeModel = null; - - /** - * Tree that holds the list of services. - */ - private JTree services; - - /** - * The panel that shows an HTML table with any details for the selected - * node in the services tree. - */ - private JEditorPane details; - - /** - * A registered listener. This listener will be notified when there is a - * different node selected in the service tree. - */ - private ServiceSelectedListener listener; - - /** - * Create a new instance of the panel. - */ - public ServicePanel() { - super(); - setLayout(new BorderLayout()); - - top = new DefaultMutableTreeNode("Services & Posted Files"); - treeModel = new DefaultTreeModel(top); - - services = new JTree(treeModel); - services.setCellRenderer(new ServicePostTreeRenderer()); - - JScrollPane servicesPane = new JScrollPane(services, - JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, - JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - - details = new JEditorPane("text/html", - "

    Details

    This panel will show the details for the currently " + - "selected item in the tree.

    "); - - JScrollPane detailsPane = new JScrollPane(details, - JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, - JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - - JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, - servicesPane, - detailsPane); - splitPane.setOneTouchExpandable(true); - splitPane.setResizeWeight(0.5); - splitPane.setDividerLocation(200); - - services.addTreeSelectionListener(this); - ToolTipManager.sharedInstance().registerComponent(services); - - add(splitPane, BorderLayout.CENTER); - } - - /** - * Renderer that displays the icons for the tree nodes. - * - * @author Neil Taylor - */ - static class ServicePostTreeRenderer extends DefaultTreeCellRenderer { - Icon workspaceIcon; - Icon serviceIcon; - Icon collectionIcon; - Icon fileIcon; - - /** - * Initialise the renderer. Load the icons. - */ - public ServicePostTreeRenderer() { - ClassLoader loader = this.getClass().getClassLoader(); - workspaceIcon = new ImageIcon(loader.getResource("images/WorkspaceNodeImage.gif")); - serviceIcon = new ImageIcon(loader.getResource("images/ServiceNodeImage.gif")); - collectionIcon = new ImageIcon(loader.getResource("images/CollectionNodeImage.gif")); - fileIcon = new ImageIcon(loader.getResource("images/ServiceNodeImage.gif")); - } - - /** - * Return the cell renderer. This will be the default tree cell renderer - * with a different icon depending upon the type of data in the node. - * - * @param tree The JTree control. - * @param value The value to display. - * @param sel True if the node is selected. - * @param expanded True if the node is expanded. - * @param leaf True if the node is a leaf. - * @param row The row. - * @param hasFocus True if the node has focus. - */ - public Component getTreeCellRendererComponent( - JTree tree, - Object value, - boolean sel, - boolean expanded, - boolean leaf, - int row, - boolean hasFocus) { - - JComponent comp = (JComponent) super.getTreeCellRendererComponent( - tree, value, sel, - expanded, leaf, row, - hasFocus); - - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) value; - - Object o = node.getUserObject(); - if (o instanceof TreeNodeWrapper) { - TreeNodeWrapper wrapper = (TreeNodeWrapper) o; - comp.setToolTipText(wrapper.toString()); - Object data = wrapper.getData(); - if (data instanceof Service) { - setIcon(serviceIcon); - } else if (data instanceof Workspace) { - setIcon(workspaceIcon); - } else if (data instanceof Collection) { - setIcon(collectionIcon); - } else if (data instanceof SWORDEntry) { - setIcon(fileIcon); - } - } else { - comp.setToolTipText(null); - } - return comp; - } - - - } - - /** - * Set the service selected listener. This listener will be notified when - * there is a selection change in the tree. - * - * @param listener The listener. - */ - public void setServiceSelectedListener(ServiceSelectedListener listener) { - this.listener = listener; - } - - /** - * Process the specified service document. Add the details as a new child of the - * root of the tree. - * - * @param url The url used to access the service document. - * @param doc The service document. - */ - public void processServiceDocument(String url, - ServiceDocument doc) { - TreeNodeWrapper wrapper = null; - - Service service = doc.getService(); - wrapper = new TreeNodeWrapper(url, service); - DefaultMutableTreeNode serviceNode = new DefaultMutableTreeNode(wrapper); - treeModel.insertNodeInto(serviceNode, top, top.getChildCount()); - services.scrollPathToVisible(new TreePath(serviceNode.getPath())); - - // process the workspaces - DefaultMutableTreeNode workspaceNode = null; - - Iterator workspaces = service.getWorkspaces(); - for (; workspaces.hasNext(); ) { - Workspace workspace = workspaces.next(); - wrapper = new TreeNodeWrapper(workspace.getTitle(), workspace); - workspaceNode = new DefaultMutableTreeNode(wrapper); - treeModel.insertNodeInto(workspaceNode, serviceNode, serviceNode.getChildCount()); - services.scrollPathToVisible(new TreePath(workspaceNode.getPath())); - - DefaultMutableTreeNode collectionNode = null; - Iterator collections = workspace.collectionIterator(); - for (; collections.hasNext(); ) { - Collection collection = collections.next(); - wrapper = new TreeNodeWrapper(collection.getTitle(), collection); - collectionNode = new DefaultMutableTreeNode(wrapper); - treeModel.insertNodeInto(collectionNode, workspaceNode, workspaceNode.getChildCount()); - services.scrollPathToVisible(new TreePath(collectionNode.getPath())); - } - } // for - } - - /** - * Holds the data for a tree node. It specifies the name that will be displayed - * in the node, and stores associated data. - * - * @author Neil Taylor - */ - static class TreeNodeWrapper { - /** - * The node name. - */ - private String name; - - /** - * The user data. - */ - private Object userObject; - - /** - * Create a new instance. - * - * @param name The name of the node. - * @param data The data in the node. - */ - public TreeNodeWrapper(String name, Object data) { - this.name = name; - this.userObject = data; - } - - /** - * Retrieve the data that is stored in this node. - * - * @return The data. - */ - public Object getData() { - return userObject; - } - - /** - * Get a string description for this node. - */ - public String toString() { - if (name == null || name.trim().equals("")) { - return "Unspecified"; - } - - return name; - } - } - - /** - * Respond to a changed tree selection event. Update the details panel to - * show an appropriate message for the newly selected node. Also, - * alert the selection listener for this panel. The listener will receive - * a path, if a collection has been selected. Otherwise, the listener - * will receive null. - */ - public void valueChanged(TreeSelectionEvent evt) { - // Get all nodes whose selection status has changed - TreePath[] paths = evt.getPaths(); - - for (int i = 0; i < paths.length; i++) { - if (evt.isAddedPath(i)) { - // process new selections - DefaultMutableTreeNode node; - node = (DefaultMutableTreeNode) (paths[i].getLastPathComponent()); - - Object o = node.getUserObject(); - if (o instanceof TreeNodeWrapper) { - try { - TreeNodeWrapper wrapper = (TreeNodeWrapper) o; - Object data = wrapper.getData(); - if (data instanceof Service) { - showService((Service) data); - alertListener(null); - } else if (data instanceof Workspace) { - showWorkspace((Workspace) data); - if (listener != null) { - alertListener(null); - } - } else if (data instanceof Collection) { - Collection c = (Collection) data; - showCollection(c); - alertListener(c.getLocation()); - } else if (data instanceof SWORDEntry) { - showEntry((SWORDEntry) data); - alertListener(null); - } else { - details.setText("unknown"); - alertListener(null); - } - } catch (Exception e) { - details.setText( - "An error occurred. The message was: " + e.getMessage() + ""); - alertListener(null); - e.printStackTrace(); - } - } else { - details.setText("please select one of the other nodes"); - alertListener(null); - } - } - - } - } - - /** - * Notify the listener that there has been a change to the currently selected - * item in the tree. - * - * @param value The value to send to the listener. - */ - private void alertListener(String value) { - if (listener != null) { - listener.selected(value); - } - } - - /** - * Add a new HTML table row to the specified StringBuffer. The label is displayed in - * the left column and the value is displayed in the right column. - * - * @param buffer The destination string buffer. - * @param label The label to add. - * @param value The corresponding value to add. - */ - private void addTableRow(StringBuffer buffer, String label, Object value) { - buffer.append(""); - buffer.append(label); - buffer.append(""); - buffer.append(displayableValue(value)); - buffer.append(""); - } - - /** - * Show the specified service data in the details panel. - * - * @param service The service node to display. - */ - private void showService(Service service) { - StringBuffer buffer = new StringBuffer(); - buffer.append(""); - buffer.append(""); - - buffer.append(""); - buffer.append(""); - addTableRow(buffer, "SWORD Version", service.getVersion()); - addTableRow(buffer, "NoOp Support ", service.isNoOp()); - addTableRow(buffer, "Verbose Support ", service.isVerbose()); - - String maxSize = ""; - - // Commented out the following code as the client code is out of step with the - // Sword 'base' library and wont compile. - Robin Taylor. - //if ( service.maxUploadIsDefined() ) - //{ - // maxSize = "" + service.getMaxUploadSize() + "kB"; - //} - //else - //{ - maxSize = "undefined"; - //} - - addTableRow(buffer, "Max File Upload Size ", maxSize); - - buffer.append("
    Service Summary
    "); - - buffer.append(""); - buffer.append(""); - details.setText(buffer.toString()); - } - - /** - * Display the workspace data in the details panel. - * - * @param workspace The workspace. - */ - private void showWorkspace(Workspace workspace) { - StringBuffer buffer = new StringBuffer(); - buffer.append(""); - buffer.append(""); - - buffer.append(""); - buffer - .append(""); - addTableRow(buffer, "Workspace Title", workspace.getTitle()); - buffer.append("
    Workspace Summary
    "); - - buffer.append(""); - buffer.append(""); - details.setText(buffer.toString()); - } - - /** - * Return the parameter unmodified if set, or the not defined text if null - * @param s - * @return s or ClientConstants.NOT_DEFINED_TEXT - */ - private Object displayableValue(Object s) { - if (null == s) { - return ClientConstants.NOT_DEFINED_TEXT; - } else { - return s; - } - } - - /** - * Add a string within paragraph tags. - * - * @param buffer The buffer to add the message to. - * @param message The message to add. - */ - private void addPara(StringBuffer buffer, String message) { - buffer.append("

    " + message + "

    "); - } - - /** - * Show the specified collection data in the details panel. - * - * @param collection The collection data. - */ - private void showCollection(Collection collection) { - StringBuffer buffer = new StringBuffer(); - buffer.append(""); - buffer.append(""); - - if (collection == null) { - addPara(buffer, "Invalid Collection object. Unable to display details."); - } else { - buffer.append(""); - buffer.append( - ""); - addTableRow(buffer, "Collection location", collection.getLocation()); - addTableRow(buffer, "Collection title", collection.getTitle()); - addTableRow(buffer, "Abstract", collection.getAbstract()); - addTableRow(buffer, "Collection Policy", collection.getCollectionPolicy()); - addTableRow(buffer, "Treatment", collection.getTreatment()); - addTableRow(buffer, "Mediation", collection.getMediation()); - addTableRow(buffer, "Nested Service Document", collection.getService()); - - String[] accepts = collection.getAccepts(); - StringBuilder acceptList = new StringBuilder(); - if (accepts != null && accepts.length == 0) { - acceptList.append("None specified"); - } else { - for (String s : accepts) { - acceptList.append(s).append("
    "); - } - } - addTableRow(buffer, "Accepts", acceptList.toString()); - - List acceptsPackaging = collection.getAcceptPackaging(); - - StringBuilder acceptPackagingList = new StringBuilder(); - for (Iterator i = acceptsPackaging.iterator(); i.hasNext(); ) { - SwordAcceptPackaging accept = (SwordAcceptPackaging) i.next(); - acceptPackagingList.append(accept.getContent()).append(" (").append(accept.getQualityValue()) - .append(")"); - - // add a , separator if there are any more items in the list - if (i.hasNext()) { - acceptPackagingList.append(", "); - } - } - - addTableRow(buffer, "Accepts Packaging", acceptPackagingList.toString()); - - buffer.append("
    Collection Summary
    "); - } - - buffer.append(""); - buffer.append(""); - details.setText(buffer.toString()); - } - - /** - * Display the contents of a Post entry in the display panel. - * - * @param entry The entry to display. - */ - private void showEntry(SWORDEntry entry) { - StringBuffer buffer = new StringBuffer(); - buffer.append(""); - buffer.append(""); - - if (entry == null) { - addPara(buffer, "Invalid Entry object. Unable to display details."); - } else { - buffer.append(""); - buffer - .append(""); - - // process atom:title - String titleString = getTextConstructDetails(entry.getSummary()); - addTableRow(buffer, "Title", titleString); - - // process id - addTableRow(buffer, "ID", entry.getId()); - - // process updated - addTableRow(buffer, "Date Updated", entry.getUpdated()); - - String authorString = getAuthorDetails(entry.getAuthors()); - addTableRow(buffer, "Authors", authorString); - - // process summary - String summaryString = getTextConstructDetails(entry.getSummary()); - addTableRow(buffer, "Summary", summaryString); - - // process content - Content content = entry.getContent(); - String contentString = ""; - if (content == null) { - contentString = "Not defined."; - } else { - contentString += "Source: '" + content.getSource() + "', Type: '" + - content.getType() + "'"; - } - addTableRow(buffer, "Content", contentString); - - // process links - Iterator links = entry.getLinks(); - StringBuffer linkBuffer = new StringBuffer(); - for (; links.hasNext(); ) { - Link link = links.next(); - linkBuffer.append("href: '"); - linkBuffer.append(link.getHref()); - linkBuffer.append("', href lang: '"); - linkBuffer.append(link.getHreflang()); - linkBuffer.append("', rel: '"); - linkBuffer.append(link.getRel()); - linkBuffer.append("')
    "); - } - if (linkBuffer.length() == 0) { - linkBuffer.append("Not defined"); - } - addTableRow(buffer, "Links", linkBuffer.toString()); - - // process contributors - String contributorString = getContributorDetails(entry.getContributors()); - addTableRow(buffer, "Contributors", contributorString); - - // process source - String sourceString = ""; - Generator generator = entry.getGenerator(); - if (generator != null) { - sourceString += "Content: '" + generator.getContent() + "'
    '"; - sourceString += "Version: '" + generator.getVersion() + "'
    '"; - sourceString += "Uri: '" + generator.getUri() + "'"; - } else { - sourceString += "No generator defined."; - } - - addTableRow(buffer, "Generator", sourceString); - - // process treatment - addTableRow(buffer, "Treatment", entry.getTreatment()); - - // process verboseDescription - addTableRow(buffer, "Verbose Description", entry.getVerboseDescription()); - - // process noOp - addTableRow(buffer, "NoOp", entry.isNoOp()); - - // process formatNamespace - addTableRow(buffer, "Packaging", entry.getPackaging()); - - // process userAgent - addTableRow(buffer, "User Agent", entry.getUserAgent()); - - - buffer.append("
    Entry Summary
    "); - } - - buffer.append(""); - buffer.append(""); - details.setText(buffer.toString()); - } - - /** - * Retrieve the details for a TextConstruct object. - * - * @param data The text construct object to display. - * - * @return Either 'Not defined' if the data is null, or - * details of the text content element. - */ - private String getTextConstructDetails(TextConstruct data) { - String summaryStr = ""; - if (data == null) { - summaryStr = "Not defined"; - } else { - summaryStr = "Content: '" + data.getContent() + "', Type: "; - if (data.getType() != null) { - summaryStr += "'" + data.getType().toString() + "'"; - } else { - summaryStr += "undefined."; - } - } - - return summaryStr; - } - - /** - * Get the author details and insert them into a string. - * - * @param authors the list of authors to process. - * - * @return A string containing the list of authors. - */ - private String getAuthorDetails(Iterator authors) { - // process author - StringBuffer authorBuffer = new StringBuffer(); - for (; authors.hasNext(); ) { - Author a = authors.next(); - authorBuffer.append(getAuthorDetails(a)); - } - - if (authorBuffer.length() == 0) { - authorBuffer.append("Not defined"); - } - - return authorBuffer.toString(); - } - - /** - * Get the contributor details and insert them into a string. - * - * @param contributors The contributors. - * - * @return The string that lists the details of the contributors. - */ - private String getContributorDetails(Iterator contributors) { - // process author - StringBuffer authorBuffer = new StringBuffer(); - for (; contributors.hasNext(); ) { - Contributor c = contributors.next(); - authorBuffer.append(getAuthorDetails(c)); - } - - if (authorBuffer.length() == 0) { - authorBuffer.append("Not defined"); - } - - return authorBuffer.toString(); - } - - /** - * Build a string that describes the specified author. - * - * @param author The author. - * - * @return The string description. - */ - private String getAuthorDetails(Author author) { - // process author - StringBuffer authorBuffer = new StringBuffer(); - authorBuffer.append(author.getName()); - authorBuffer.append(" (email: '"); - authorBuffer.append(author.getEmail()); - authorBuffer.append("', uri: '"); - authorBuffer.append(author.getUri()); - authorBuffer.append("')
    "); - - return authorBuffer.toString(); - } - - /** - * Process the deposit response and insert the details into the tree. If the url - * matches one of the collections in the tree, the deposit is added as a child - * node. Otherwise, the node is added as a child of the root. - * - * @param url The url of the collection that the file was posted to. - * - * @param response The details of the deposit. - */ - public void processDepositResponse(String url, - DepositResponse response) { - SWORDEntry entry = response.getEntry(); - Object title = entry.getTitle(); - if (title == null) { - title = "Undefined"; - } else { - title = entry.getTitle().getContent(); - } - - TreeNodeWrapper wrapper = new TreeNodeWrapper(title.toString(), entry); - DefaultMutableTreeNode entryNode = new DefaultMutableTreeNode(wrapper); - - DefaultMutableTreeNode newParentNode = top; - List nodes = getCollectionNodes(); - for (DefaultMutableTreeNode node : nodes) { - Object o = node.getUserObject(); - if (o instanceof TreeNodeWrapper) { - TreeNodeWrapper collectionWrapper = (TreeNodeWrapper) o; - Object data = collectionWrapper.getData(); - if (data instanceof Collection) { - Collection col = (Collection) data; - String location = col.getLocation(); - if (location != null && location.equals(url)) { - newParentNode = node; - break; - } - } - } - } - - treeModel.insertNodeInto(entryNode, newParentNode, newParentNode.getChildCount()); - services.scrollPathToVisible(new TreePath(entryNode.getPath())); - } - - /** - * Get a list of all current collections displayed in the tree. - * - * @return An array of the URLs for the collections. - */ - public String[] getCollectionLocations() { - List nodes = getCollectionNodes(); - String[] locations = new String[nodes.size()]; - - DefaultMutableTreeNode node; - for (int i = 0; i < nodes.size(); i++) { - node = nodes.get(i); - Object o = node.getUserObject(); - if (o instanceof TreeNodeWrapper) { - TreeNodeWrapper collectionWrapper = (TreeNodeWrapper) o; - Object data = collectionWrapper.getData(); - if (data instanceof Collection) { - Collection col = (Collection) data; - String location = col.getLocation(); - if (location != null) { - locations[i] = location; - } - } - } - } - return locations; - } - - /** - * Get a list of nodes that contain collections. - * - * @return A vector of the collection nodes. - */ - private List getCollectionNodes() { - List nodes = new ArrayList(); - - DefaultMutableTreeNode node; - Enumeration treeNodes = top.depthFirstEnumeration(); - - while (treeNodes.hasMoreElements()) { - node = (DefaultMutableTreeNode) treeNodes.nextElement(); - Object o = node.getUserObject(); - if (o instanceof TreeNodeWrapper) { - TreeNodeWrapper wrapper = (TreeNodeWrapper) o; - Object data = wrapper.getData(); - if (data instanceof Collection) { - nodes.add(node); - } - } - } - - return nodes; - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/ServiceSelectedListener.java b/dspace-sword/src/main/java/org/purl/sword/client/ServiceSelectedListener.java deleted file mode 100644 index fa97549fd924..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/ServiceSelectedListener.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -/** - * Listener for any objects that want to be notified when a collection has been selected in the - * ServicePanel. - * - * @author Neil Taylor - */ -public interface ServiceSelectedListener { - /** - * Called to provide an update on whether the selected node is a Collection. - * - * @param collection The location of the collection. null, otherwise. - */ - public void selected(String collection); -} diff --git a/dspace-sword/src/main/java/org/purl/sword/client/Status.java b/dspace-sword/src/main/java/org/purl/sword/client/Status.java deleted file mode 100644 index ff80fa6e52e2..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/Status.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.purl.sword.client; - -/** - * Representation of the status code and message. - * - * @author Neil Taylor - */ -public class Status { - /** - * The status code. - */ - private int code; - - /** - * The status message. - */ - private String message; - - /** - * Create a new status message. - * - * @param code The code. - * @param message The message. - */ - public Status(int code, String message) { - this.code = code; - this.message = message; - } - - /** - * Retrieve the code. - * - * @return The code. - */ - public int getCode() { - return code; - } - - /** - * Get the message. - * - * @return The message. - */ - public String getMessage() { - return message; - } - - /** - * Get a string representation of the status. - */ - public String toString() { - return "Code: " + code + ", Message: '" + message + "'"; - } -} From e356335b56ff9b490fe99a15fcab6a14a3a60b60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 00:03:37 +0000 Subject: [PATCH 478/632] Bump org.checkerframework:checker-qual from 3.49.0 to 3.49.2 Bumps [org.checkerframework:checker-qual](https://github.com/typetools/checker-framework) from 3.49.0 to 3.49.2. - [Release notes](https://github.com/typetools/checker-framework/releases) - [Changelog](https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/typetools/checker-framework/compare/checker-framework-3.49.0...checker-framework-3.49.2) --- updated-dependencies: - dependency-name: org.checkerframework:checker-qual dependency-version: 3.49.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4907e7a12ee6..17992113bc85 100644 --- a/pom.xml +++ b/pom.xml @@ -1350,7 +1350,7 @@ org.checkerframework checker-qual - 3.49.0 + 3.49.2 2.18.2 2.18.2 @@ -140,7 +140,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.13.0 + 3.14.0 ${java.version} @@ -208,7 +208,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.2 + 3.5.3 @@ -235,7 +235,7 @@ maven-failsafe-plugin - 3.5.2 + 3.5.3 @@ -303,7 +303,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.9.1.0 + 4.9.3.0 Max Low @@ -313,7 +313,7 @@ com.github.spotbugs spotbugs - 4.9.1 + 4.9.3 @@ -329,7 +329,7 @@ maven-clean-plugin - 3.4.0 + 3.4.1 @@ -405,7 +405,7 @@ org.jacoco jacoco-maven-plugin - 0.8.12 + 0.8.13 From 6733e56e92b5733913251d863cd2b5488dac2fe5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 16:05:23 +0000 Subject: [PATCH 481/632] Bump the fasterxml group with 4 updates Bumps the fasterxml group with 4 updates: [com.fasterxml.jackson.core:jackson-annotations](https://github.com/FasterXML/jackson), [com.fasterxml.jackson.core:jackson-core](https://github.com/FasterXML/jackson-core), [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) and com.fasterxml.jackson.datatype:jackson-datatype-jsr310. Updates `com.fasterxml.jackson.core:jackson-annotations` from 2.18.2 to 2.18.3 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.18.2 to 2.18.3 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.18.2...jackson-core-2.18.3) Updates `com.fasterxml.jackson.core:jackson-core` from 2.18.2 to 2.18.3 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.18.2...jackson-core-2.18.3) Updates `com.fasterxml.jackson.core:jackson-databind` from 2.18.2 to 2.18.3 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.18.2 to 2.18.3 Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.18.2 to 2.18.3 --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 388dd0cf8393..ad888d1dc339 100644 --- a/pom.xml +++ b/pom.xml @@ -31,8 +31,8 @@ 3.10.8 2.36.0 - 2.18.2 - 2.18.2 + 2.18.3 + 2.18.3 2.1.1 4.0.2 4.0.5 From 754a3450eefaa9d5ee50e4f2741cfdf26bab4ad7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 16:18:07 +0000 Subject: [PATCH 482/632] Bump the spring group with 23 updates Bumps the spring group with 23 updates: | Package | From | To | | --- | --- | --- | | [org.springframework:spring-orm](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-beans](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-aop](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-context-support](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-tx](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-jdbc](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-expression](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework:spring-test](https://github.com/spring-projects/spring-framework) | `6.2.4` | `6.2.5` | | [org.springframework.boot:spring-boot-starter-test](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter-tomcat](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-maven-plugin](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter-cache](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter-web](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter-data-rest](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter-security](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter-aop](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter-actuator](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | | [org.springframework.boot:spring-boot-starter-log4j2](https://github.com/spring-projects/spring-boot) | `3.4.3` | `3.4.4` | Updates `org.springframework:spring-orm` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-core` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-beans` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-aop` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-context` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-context-support` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-tx` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-jdbc` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-web` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-webmvc` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-expression` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-test` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-core` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-beans` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-aop` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-context` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-context-support` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-tx` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-jdbc` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-web` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-webmvc` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-expression` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework:spring-test` from 6.2.4 to 6.2.5 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.4...v6.2.5) Updates `org.springframework.boot:spring-boot-starter-test` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.3 to 3.4.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.3...v3.4.4) --- updated-dependencies: - dependency-name: org.springframework:spring-orm dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 388dd0cf8393..5a3e755c112a 100644 --- a/pom.xml +++ b/pom.xml @@ -19,8 +19,8 @@ 17 - 6.2.4 - 3.4.3 + 6.2.5 + 3.4.4 6.4.4 6.4.8.Final 8.0.1.Final From ffff7cc4d8b63c1b89b605d61594f31bab4b3234 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 9 Apr 2025 13:39:05 +0200 Subject: [PATCH 483/632] remove inclusion of sword-client.cfg (cherry picked from commit 9794df594cc7d155cecc6ae9f86a6fc3811a61db) --- dspace/config/dspace.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index debe4b658fb9..c9ae5d521d90 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -1672,7 +1672,6 @@ include = ${module_dir}/researcher-profile.cfg include = ${module_dir}/spring.cfg include = ${module_dir}/submission-curation.cfg include = ${module_dir}/suggestion.cfg -include = ${module_dir}/sword-client.cfg include = ${module_dir}/sword-server.cfg include = ${module_dir}/swordv2-server.cfg include = ${module_dir}/translator.cfg From a4314e5df6cebd81acc28f1927ee3fb7b68e5235 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 9 Apr 2025 13:40:02 +0200 Subject: [PATCH 484/632] removal of configuration file sword-client.cfg (cherry picked from commit d299d2268507f55b4b6ab2a43d33222da8c082b9) --- dspace/config/modules/sword-client.cfg | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 dspace/config/modules/sword-client.cfg diff --git a/dspace/config/modules/sword-client.cfg b/dspace/config/modules/sword-client.cfg deleted file mode 100644 index 9e8a029ae684..000000000000 --- a/dspace/config/modules/sword-client.cfg +++ /dev/null @@ -1,23 +0,0 @@ -#---------------------------------------------------------------# -#--------------SWORD V.1 CLIENT CONFIGURATIONS------------------# -#---------------------------------------------------------------# -# Configuration properties used solely by the UI-based SWORD # -# Client interface (used to submit DSpace content to another # -# SWORD server). # -#---------------------------------------------------------------# -# TODO: UNSUPPORTED in DSpace 7.0 -# List of remote Sword servers. Used to build the drop-down list of selectable Sword targets. -sword-client.targets = http://localhost:8080/sword/servicedocument, \ - http://client.swordapp.org/client/servicedocument, \ - http://dspace.swordapp.org/sword/servicedocument, \ - http://sword.eprints.org/sword-app/servicedocument, \ - http://sword.intralibrary.com/IntraLibrary-Deposit/service, \ - http://fedora.swordapp.org/sword-fedora/servicedocument - -# List of file types from which the user can select. If a type is not supported by the remote server -# it will not appear in the drop-down list. -sword-client.file-types = application/zip - -# List of package formats from which the user can select. If a format is not supported by the remote server -# it will not appear in the drop-down list. -sword-client.package-formats = http://purl.org/net/sword-types/METSDSpaceSIP From 518fb3b1d89795b4995b32e164e3ac9c9e48350e Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Thu, 20 Feb 2025 18:21:21 +0100 Subject: [PATCH 485/632] 126885: Removed database connection leak on login Also: - Updated EPersonRestAuthenticationProvider to not open an additional DB connection, and reuse the existing one instead - Normalized the behaviour of OidcLoginFilter by not calling the redirectAfterSuccess instead of doing a chain.doFilter(req, res). This way we don't need to reopen a new Context --- .../EPersonRestAuthenticationProvider.java | 64 ++++++++----------- .../app/rest/security/OidcLoginFilter.java | 52 ++++++++++++++- ...JWTTokenRestAuthenticationServiceImpl.java | 3 + 3 files changed, 80 insertions(+), 39 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EPersonRestAuthenticationProvider.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EPersonRestAuthenticationProvider.java index e55734e513de..00c804ad2d64 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EPersonRestAuthenticationProvider.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EPersonRestAuthenticationProvider.java @@ -85,7 +85,7 @@ public Authentication authenticate(Authentication authentication) throws Authent } else { // Otherwise, this is a new login & we need to attempt authentication log.debug("Request to authenticate new login"); - return authenticateNewLogin(authentication); + return authenticateNewLogin(context, authentication); } } @@ -107,56 +107,44 @@ private Authentication authenticateRefreshTokenRequest(Context context) { * If login is successful, returns a NEW Authentication class containing the logged in EPerson and their list of * GrantedAuthority objects. If login fails, a BadCredentialsException is thrown. If no valid login found implicit * or explicit, then null is returned. + * + * @param context The current DSpace context * @param authentication Authentication class to attempt authentication. * @return new Authentication class containing logged-in user information or null */ - private Authentication authenticateNewLogin(Authentication authentication) { - Context newContext = null; + private Authentication authenticateNewLogin(Context context, Authentication authentication) { Authentication output = null; if (authentication != null) { - try { - newContext = new Context(); - String name = authentication.getName(); - String password = Objects.toString(authentication.getCredentials(), null); + String name = authentication.getName(); + String password = Objects.toString(authentication.getCredentials(), null); - int implicitStatus = authenticationService.authenticateImplicit(newContext, null, null, null, request); + int implicitStatus = authenticationService.authenticateImplicit(context, null, null, null, request); - if (implicitStatus == AuthenticationMethod.SUCCESS) { - log.info(LogHelper.getHeader(newContext, "login", "type=implicit")); - output = createAuthentication(newContext); - } else { - int authenticateResult = authenticationService - .authenticate(newContext, name, password, null, request); - if (AuthenticationMethod.SUCCESS == authenticateResult) { + if (implicitStatus == AuthenticationMethod.SUCCESS) { + log.info(LogHelper.getHeader(context, "login", "type=implicit")); + output = createAuthentication(context); + } else { + int authenticateResult = authenticationService.authenticate(context, name, password, null, request); + if (AuthenticationMethod.SUCCESS == authenticateResult) { - log.info(LogHelper - .getHeader(newContext, "login", "type=explicit")); + log.info(LogHelper.getHeader(context, "login", "type=explicit")); - output = createAuthentication(newContext); + output = createAuthentication(context); - for (PostLoggedInAction action : postLoggedInActions) { - try { - action.loggedIn(newContext); - } catch (Exception ex) { - log.error("An error occurs performing post logged in action", ex); - } + for (PostLoggedInAction action : postLoggedInActions) { + try { + action.loggedIn(context); + } catch (Exception ex) { + log.error("An error occurs performing post logged in action", ex); } - - } else { - log.info(LogHelper.getHeader(newContext, "failed_login", "email=" - + name + ", result=" - + authenticateResult)); - throw new BadCredentialsException("Login failed"); - } - } - } finally { - if (newContext != null && newContext.isValid()) { - try { - newContext.complete(); - } catch (SQLException e) { - log.error(e.getMessage() + " occurred while trying to close", e); } + + } else { + log.info(LogHelper.getHeader(context, "failed_login", "email=" + + name + ", result=" + + authenticateResult)); + throw new BadCredentialsException("Login failed"); } } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/OidcLoginFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/OidcLoginFilter.java index c84840e77041..e73a3e8d3ccb 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/OidcLoginFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/OidcLoginFilter.java @@ -10,11 +10,18 @@ import static org.dspace.authenticate.OidcAuthenticationBean.OIDC_AUTH_ATTRIBUTE; import java.io.IOException; +import java.util.ArrayList; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.core.Utils; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -27,6 +34,11 @@ public class OidcLoginFilter extends StatelessLoginFilter { + private static final Logger log = LogManager.getLogger(OidcLoginFilter.class); + + private final ConfigurationService configurationService = DSpaceServicesFactory.getInstance() + .getConfigurationService(); + public OidcLoginFilter(String url, AuthenticationManager authenticationManager, RestAuthenticationService restAuthenticationService) { super(url, authenticationManager, restAuthenticationService); @@ -44,7 +56,45 @@ public Authentication attemptAuthentication(HttpServletRequest req, HttpServletR protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException, ServletException { restAuthenticationService.addAuthenticationDataForUser(req, res, (DSpaceAuthentication) auth, true); - chain.doFilter(req, res); + redirectAfterSuccess(req, res); + } + + /** + * After successful login, redirect to the DSpace URL specified by this OIDC + * request (in the "redirectUrl" request parameter). If that 'redirectUrl' is + * not valid or trusted for this DSpace site, then return a 400 error. + * @param request + * @param response + * @throws IOException + */ + private void redirectAfterSuccess(HttpServletRequest request, HttpServletResponse response) throws IOException { + // Get redirect URL from request parameter + String redirectUrl = request.getParameter("redirectUrl"); + + // If redirectUrl unspecified, default to the configured UI + if (StringUtils.isEmpty(redirectUrl)) { + redirectUrl = configurationService.getProperty("dspace.ui.url"); + } + + // Validate that the redirectURL matches either the server or UI hostname. It + // *cannot* be an arbitrary URL. + String redirectHostName = Utils.getHostName(redirectUrl); + String serverHostName = Utils.getHostName(configurationService.getProperty("dspace.server.url")); + ArrayList allowedHostNames = new ArrayList<>(); + allowedHostNames.add(serverHostName); + String[] allowedUrls = configurationService.getArrayProperty("rest.cors.allowed-origins"); + for (String url : allowedUrls) { + allowedHostNames.add(Utils.getHostName(url)); + } + + if (StringUtils.equalsAnyIgnoreCase(redirectHostName, allowedHostNames.toArray(new String[0]))) { + log.debug("OIDC redirecting to " + redirectUrl); + response.sendRedirect(redirectUrl); + } else { + log.error("Invalid OIDC redirectURL=" + redirectUrl + ". URL doesn't match hostname of server or UI!"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, + "Invalid redirectURL! Must match server or ui hostname."); + } } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTTokenRestAuthenticationServiceImpl.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTTokenRestAuthenticationServiceImpl.java index c28729ff83a8..425ba505b431 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTTokenRestAuthenticationServiceImpl.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTTokenRestAuthenticationServiceImpl.java @@ -84,6 +84,9 @@ public void addAuthenticationDataForUser(HttpServletRequest request, HttpServlet String token = loginJWTTokenHandler.createTokenForEPerson(context, request, authentication.getPreviousLoginDate()); context.commit(); + // Close the Context, because the DSpaceRequestContextFilter is not called for requests that trigger + // the authentication filters (filters that extend AbstractAuthenticationProcessingFilter) + context.close(); // Add newly generated auth token to the response addTokenToResponse(request, response, token, addCookie); From a74ff3d96084ed5d954979235c537085002c557e Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Fri, 4 Apr 2025 17:46:35 +0200 Subject: [PATCH 486/632] #9778 Replace OAI templating with Thymeleaf (cherry picked from commit f2389e6e7b9996181344ab70dd5f2886153001ab) --- dspace-oai/pom.xml | 20 +++-- .../app/configuration/OAIWebConfig.java | 56 +++++++++---- .../src/main/resources/templates/index.html | 78 ++++++++++++++++++ .../main/resources/templates/index.twig.html | 81 ------------------- 4 files changed, 129 insertions(+), 106 deletions(-) create mode 100644 dspace-oai/src/main/resources/templates/index.html delete mode 100644 dspace-oai/src/main/resources/templates/index.twig.html diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index b824b7396e03..eae700663e6e 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -87,18 +87,16 @@ - + - org.jtwig - jtwig-spring-boot-starter - ${jtwig.version} - - - - org.springframework.boot - spring-boot-starter-web - - + org.springframework + spring-webmvc + ${spring.version} + + + org.springframework.boot + spring-boot-starter-thymeleaf + ${spring-boot.version} diff --git a/dspace-oai/src/main/java/org/dspace/app/configuration/OAIWebConfig.java b/dspace-oai/src/main/java/org/dspace/app/configuration/OAIWebConfig.java index dc4efde880d5..565d9f032632 100644 --- a/dspace-oai/src/main/java/org/dspace/app/configuration/OAIWebConfig.java +++ b/dspace-oai/src/main/java/org/dspace/app/configuration/OAIWebConfig.java @@ -11,8 +11,6 @@ import org.dspace.xoai.app.BasicConfiguration; import org.dspace.xoai.services.api.xoai.ItemRepositoryResolver; import org.dspace.xoai.services.impl.xoai.DSpaceItemRepositoryResolver; -import org.jtwig.spring.JtwigViewResolver; -import org.jtwig.spring.boot.config.JtwigViewResolverConfigurer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -20,31 +18,37 @@ import org.springframework.context.annotation.Import; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.thymeleaf.spring6.SpringTemplateEngine; +import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver; +import org.thymeleaf.spring6.view.ThymeleafViewResolver; +import org.thymeleaf.templatemode.TemplateMode; /** - * OAI-PMH webapp configuration. Replaces the old web.xml + * OAI-PMH webapp configuration. Replaces the old web.xml. + * This webapp used JTwig in earlier versions and has been refactored to + * use Thymeleaf instead. *

    * This @Configuration class is automatically discovered by Spring Boot via a @ComponentScan * on the org.dspace.app.configuration package. *

    * * - * @author Tim Donohue + * @author Kim Shepherd */ @Configuration // Import additional configuration and beans from BasicConfiguration @Import(BasicConfiguration.class) // Scan for controllers in this package @ComponentScan("org.dspace.xoai.controller") -public class OAIWebConfig implements WebMvcConfigurer, JtwigViewResolverConfigurer { +public class OAIWebConfig implements WebMvcConfigurer { // Path where OAI is deployed. Defaults to "oai" // NOTE: deployment on this path is handled by org.dspace.xoai.controller.DSpaceOAIDataProvider @Value("${oai.path:oai}") private String oaiPath; - private static final String TWIG_HTML_EXTENSION = ".twig.html"; private static final String VIEWS_LOCATION = "classpath:/templates/"; + private static final String HTML_EXTENSION = ".html"; /** * Ensure all resources under src/main/resources/static/ directory are available @@ -58,18 +62,42 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) { } /** - * Configure the Jtwig template engine for Spring Boot - * Ensures Jtwig looks for templates in proper location with proper extension + * Configure the Thymeleaf template resolver **/ - @Override - public void configure(JtwigViewResolver viewResolver) { - viewResolver.setPrefix(VIEWS_LOCATION); - viewResolver.setSuffix(TWIG_HTML_EXTENSION); + @Bean + public SpringResourceTemplateResolver templateResolver() { + SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); + templateResolver.setPrefix(VIEWS_LOCATION); + templateResolver.setSuffix(HTML_EXTENSION); + templateResolver.setTemplateMode(TemplateMode.HTML); + templateResolver.setCacheable(true); + return templateResolver; + } + + /** + * Configure the Thymeleaf template engine + **/ + @Bean + public SpringTemplateEngine templateEngine() { + SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(templateResolver()); + templateEngine.setEnableSpringELCompiler(true); + return templateEngine; + } + + /** + * Configure the Thymeleaf view resolver + **/ + @Bean + public ThymeleafViewResolver viewResolver() { + ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); + viewResolver.setTemplateEngine(templateEngine()); + viewResolver.setCharacterEncoding("UTF-8"); + return viewResolver; } @Bean public ItemRepositoryResolver xoaiItemRepositoryResolver() { return new DSpaceItemRepositoryResolver(); } -} - +} \ No newline at end of file diff --git a/dspace-oai/src/main/resources/templates/index.html b/dspace-oai/src/main/resources/templates/index.html new file mode 100644 index 000000000000..a0d35d91dea2 --- /dev/null +++ b/dspace-oai/src/main/resources/templates/index.html @@ -0,0 +1,78 @@ + + + + + + DSpace OAI-PMH Data Provider + + + + + + + + + + + +

    + + + + + + + +
    +

    Available Contexts

    + +
    + +
    +
    +

    DSpace OAI-PMH Data Provider

    +

    + + DSpace + +

    +
    + +
    + + diff --git a/dspace-oai/src/main/resources/templates/index.twig.html b/dspace-oai/src/main/resources/templates/index.twig.html deleted file mode 100644 index c473188e35c0..000000000000 --- a/dspace-oai/src/main/resources/templates/index.twig.html +++ /dev/null @@ -1,81 +0,0 @@ -{# - - The contents of this file are subject to the license and copyright - detailed in the LICENSE and NOTICE files at the root of the source - tree and available online at - - http://www.dspace.org/license/ - -#} -{# - - DSpace OAI default index template. To override this template, place a customized version in - the [webapp]/WEB-INF/classes/templates/ folder, and reboot your servlet engine. - -#} - - - - DSpace OAI-PMH Data Provider - - - - - {# NOTE: We use JQuery and Bootstrap via WebJars which are configured in dspace-server-webapp #} - - - - - - -
    - - - - - - - -
    -

    Available Contexts

    -
    - {% for item in contexts %} -
    -

    {{ item.name }} {% if (item.description) %}{{ item.description }}{% endif %}

    -

    -

    -

    -

    -
    - {% endfor %} -
    -
    - -
    -
    -

    DSpace OAI-PMH Data Provider

    -

    - - DSpace - -

    -
    - -
    - - From 7aceda3dd29e17d5e60ab27c83fe8e7781df93b5 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 9 Apr 2025 22:47:15 +0200 Subject: [PATCH 487/632] #9778 Remove jtwig version property from oai pom.xml (cherry picked from commit aa304767cefc41209e91adb91256e426583f0159) --- dspace-oai/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index eae700663e6e..10511740459c 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -16,7 +16,6 @@ ${basedir}/.. 3.4.0 - 5.87.0.RELEASE
    From 6c8adb2d2f1a5285870a666da6c00c52184195c5 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 9 Apr 2025 22:48:08 +0200 Subject: [PATCH 488/632] #9778 Remove jtwig references from LICENSES_THIRD_PARTY (cherry picked from commit c01170071227bb097b2fc454077690100bb26805) --- LICENSES_THIRD_PARTY | 5 ----- 1 file changed, 5 deletions(-) diff --git a/LICENSES_THIRD_PARTY b/LICENSES_THIRD_PARTY index 1d39b851ad61..5049903ffc62 100644 --- a/LICENSES_THIRD_PARTY +++ b/LICENSES_THIRD_PARTY @@ -384,11 +384,6 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/) * JBoss Logging 3 (org.jboss.logging:jboss-logging:3.6.1.Final - http://www.jboss.org) * JDOM (org.jdom:jdom2:2.0.6.1 - http://www.jdom.org) - * jtwig-core (org.jtwig:jtwig-core:5.87.0.RELEASE - http://jtwig.org) - * jtwig-reflection (org.jtwig:jtwig-reflection:5.87.0.RELEASE - http://jtwig.org) - * jtwig-spring (org.jtwig:jtwig-spring:5.87.0.RELEASE - http://jtwig.org) - * jtwig-spring-boot-starter (org.jtwig:jtwig-spring-boot-starter:5.87.0.RELEASE - http://jtwig.org) - * jtwig-web (org.jtwig:jtwig-web:5.87.0.RELEASE - http://jtwig.org) * Proj4J (org.locationtech.proj4j:proj4j:1.1.5 - https://github.com/locationtech/proj4j) * Spatial4J (org.locationtech.spatial4j:spatial4j:0.7 - https://projects.eclipse.org/projects/locationtech.spatial4j) * MockServer Java Client (org.mock-server:mockserver-client-java:5.15.0 - https://www.mock-server.com) From 7cb9eb49a3a431aa121fe0e55f2f47df8d22d8b5 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Thu, 10 Apr 2025 17:01:08 -0400 Subject: [PATCH 489/632] Translate null message parameters to "". Reorganize and add minimal test suite. (cherry picked from commit 66fe8d862ecb462791deb5d6d79649403ed1b5e0) --- .../src/main/java/org/dspace/core/Email.java | 120 ++++++++++++------ .../test/java/org/dspace/core/EmailTest.java | 68 ++++++++++ 2 files changed, 152 insertions(+), 36 deletions(-) create mode 100644 dspace-api/src/test/java/org/dspace/core/EmailTest.java diff --git a/dspace-api/src/main/java/org/dspace/core/Email.java b/dspace-api/src/main/java/org/dspace/core/Email.java index bb434c07cb96..74a48b3d82c9 100644 --- a/dspace-api/src/main/java/org/dspace/core/Email.java +++ b/dspace-api/src/main/java/org/dspace/core/Email.java @@ -55,7 +55,7 @@ import org.dspace.services.factory.DSpaceServicesFactory; /** - * Class representing an e-mail message. The {@link send} method causes the + * Builder representing an e-mail message. The {@link send} method causes the * assembled message to be formatted and sent. *

    * Typical use: @@ -168,6 +168,9 @@ public class Email { */ private String charset; + /** The message being assembled. */ + MimeMessage message; + private static final Logger LOG = LogManager.getLogger(); /** Velocity template settings. */ @@ -188,6 +191,9 @@ public class Email { /** Velocity template for a message body */ private Template template; + /** The message text. */ + private String body; + /** * Create a new email message. */ @@ -254,9 +260,15 @@ public void setReplyTo(String email) { /** * Fill out the next argument in the template. * - * @param arg the value for the next argument + * @param arg the value for the next argument. If {@code null}, + * a zero-length string is substituted. */ public void addArgument(Object arg) { + if (null == arg) { + arg = ""; + LOG.warn("Null argument {} to email template {} replaced with zero-length string", + arguments.size(), contentName); + } arguments.add(arg); } @@ -327,7 +339,27 @@ public void reset() { } /** - * Sends the email. If the template defines a Velocity context property + * Sends the email. If sending is disabled then the assembled message is + * logged instead. + * + * @throws MessagingException if there was a problem sending the mail. + * @throws IOException if IO error + */ + public void send() throws MessagingException, IOException { + build(); + + ConfigurationService config + = DSpaceServicesFactory.getInstance().getConfigurationService(); + boolean disabled = config.getBooleanProperty("mail.server.disabled", false); + if (disabled) { + LOG.info(format(message, body)); + } else { + Transport.send(message); + } + } + + /** + * Build the message. If the template defines a Velocity context property * named among the values of DSpace configuration property * {@code mail.message.headers} then that name and its value will be added * to the message's headers. @@ -336,11 +368,12 @@ public void reset() { * called, the value of any "subject" property will be used as if setSubject * had been called with that value. Thus a template may define its subject, * but the caller may override it. - * - * @throws MessagingException if there was a problem sending the mail. - * @throws IOException if IO error + * + * @throws MessagingException if there is no template, or passed through. + * @throws IOException passed through. */ - public void send() throws MessagingException, IOException { + void build() + throws MessagingException, IOException { if (null == template) { // No template -- no content -- PANIC!!! throw new MessagingException("Email has no body"); @@ -351,7 +384,6 @@ public void send() throws MessagingException, IOException { // Get the mail configuration properties String from = config.getProperty("mail.from.address"); - boolean disabled = config.getBooleanProperty("mail.server.disabled", false); // If no character set specified, attempt to retrieve a default if (charset == null) { @@ -362,7 +394,7 @@ public void send() throws MessagingException, IOException { Session session = DSpaceServicesFactory.getInstance().getEmailService().getSession(); // Create message - MimeMessage message = new MimeMessage(session); + message = new MimeMessage(session); // Set the recipients of the message for (String recipient : recipients) { @@ -385,7 +417,7 @@ public void send() throws MessagingException, IOException { LOG.error("Template not merged: {}", ex.getMessage()); throw new MessagingException("Template not merged", ex); } - String fullMessage = writer.toString(); + body = writer.toString(); // Set some message header fields Date date = new Date(); @@ -412,20 +444,19 @@ public void send() throws MessagingException, IOException { message.setSubject(subject); } - // Add attachments - if (attachments.isEmpty() && moreAttachments.isEmpty()) { - // If a character set has been specified, or a default exists + // Attach the body. + if (attachments.isEmpty() && moreAttachments.isEmpty()) { // Flat body. if (charset != null) { - message.setText(fullMessage, charset); + message.setText(body, charset); } else { - message.setText(fullMessage); + message.setText(body); } - } else { + } else { // Add attachments. Multipart multipart = new MimeMultipart(); // create the first part of the email BodyPart messageBodyPart = new MimeBodyPart(); - messageBodyPart.setText(fullMessage); + messageBodyPart.setText(body); multipart.addBodyPart(messageBodyPart); // Add file attachments @@ -457,30 +488,47 @@ public void send() throws MessagingException, IOException { replyToAddr[0] = new InternetAddress(replyTo); message.setReplyTo(replyToAddr); } + } - if (disabled) { - StringBuilder text = new StringBuilder( - "Message not sent due to mail.server.disabled:\n"); - - Enumeration headers = message.getAllHeaderLines(); - while (headers.hasMoreElements()) { - text.append(headers.nextElement()).append('\n'); - } + /** + * Flatten the email into a string. + * + * @param message the message headers, attachments, etc. + * @param body the message body. + * @return stringified email message. + * @throws MessagingException passed through. + */ + private String format(MimeMessage message, String body) + throws MessagingException { + StringBuilder text = new StringBuilder( + "Message not sent due to mail.server.disabled:\n"); + + Enumeration headers = message.getAllHeaderLines(); + while (headers.hasMoreElements()) { + text.append(headers.nextElement()).append('\n'); + } - if (!attachments.isEmpty()) { - text.append("\nAttachments:\n"); - for (FileAttachment f : attachments) { - text.append(f.name).append('\n'); - } - text.append('\n'); + if (!attachments.isEmpty()) { + text.append("\nAttachments:\n"); + for (FileAttachment f : attachments) { + text.append(f.name).append('\n'); } + text.append('\n'); + } - text.append('\n').append(fullMessage); + text.append('\n').append(body); + return text.toString(); + } - LOG.info(text.toString()); - } else { - Transport.send(message); - } + /** + * Get the formatted message for testing. + * + * @return the message flattened to a String. + * @throws MessagingException passed through. + */ + String getMessage() + throws MessagingException { + return format(message, body); } /** diff --git a/dspace-api/src/test/java/org/dspace/core/EmailTest.java b/dspace-api/src/test/java/org/dspace/core/EmailTest.java new file mode 100644 index 000000000000..61b8dd31e1f0 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/core/EmailTest.java @@ -0,0 +1,68 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.core; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; + +import java.io.IOException; + +import jakarta.mail.MessagingException; +import org.dspace.AbstractDSpaceTest; +import org.dspace.services.ConfigurationService; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for email sender. + * + * @author mwood + */ +public class EmailTest + extends AbstractDSpaceTest { + private ConfigurationService config; + + @Before + public void init_test() { + config = kernelImpl.getConfigurationService(); + } + + @Test + public void testNullParameter() + throws MessagingException, IOException { + // Ensure that no mail goes out + config.setProperty("mail.server.disabled", "true"); + + Email email = new Email(); + email.setContent("null test", + "Testing: parameter value is /${params[0]}/."); + email.addArgument(null); + email.build(); + String message = email.getMessage(); + assertThat("Null message parameter should be transformed to empty", + message, not(containsString("(null)"))); + } + + @Test + public void testNotNullParameter() + throws MessagingException, IOException { + // Ensure that no mail goes out + config.setProperty("mail.server.disabled", "true"); + + Email email = new Email(); + email.setContent("not-null test", + "Testing: parameter value is /${params[0]}/."); + String testParam = "axolotl"; + email.addArgument(testParam); + email.build(); + String message = email.getMessage(); + assertThat("Null message parameter should be transformed to empty", + message, containsString(testParam)); + } +} From 5c034c6c02d046226587947ce1a40d0363c1fdcc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 23:03:29 +0000 Subject: [PATCH 490/632] Bump the apache-commons group with 2 updates Bumps the apache-commons group with 2 updates: commons-io:commons-io and org.apache.commons:commons-text. Updates `commons-io:commons-io` from 2.18.0 to 2.19.0 Updates `org.apache.commons:commons-text` from 1.13.0 to 1.13.1 --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-version: 2.19.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-text dependency-version: 1.13.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 62d6d2d0b55d..f7951285d56b 100644 --- a/pom.xml +++ b/pom.xml @@ -1505,7 +1505,7 @@ commons-io commons-io - 2.18.0 + 2.19.0 org.apache.commons @@ -1537,7 +1537,7 @@ org.apache.commons commons-text - 1.13.0 + 1.13.1 commons-validator From 24ed6f733dcf5211dbb5b9fc2f74fce4ac7db208 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 23:11:20 +0000 Subject: [PATCH 491/632] Bump com.google.code.gson:gson from 2.12.1 to 2.13.0 Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.12.1 to 2.13.0. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.12.1...gson-parent-2.13.0) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-version: 2.13.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 62d6d2d0b55d..4857766c0b9e 100644 --- a/pom.xml +++ b/pom.xml @@ -1358,7 +1358,7 @@ com.google.code.gson gson - 2.12.1 + 2.13.0 2.18.3 2.18.3 From 2cb34b095e99976d4ee745a783c3c9d0ccaa7642 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Apr 2025 22:27:51 +0000 Subject: [PATCH 498/632] Bump the spring group with 13 updates Bumps the spring group with 13 updates: | Package | From | To | | --- | --- | --- | | [org.springframework:spring-orm](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-beans](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-aop](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-context-support](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-tx](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-jdbc](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-expression](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework:spring-test](https://github.com/spring-projects/spring-framework) | `6.2.5` | `6.2.6` | | [org.springframework.security:spring-security-test](https://github.com/spring-projects/spring-security) | `6.4.4` | `6.4.5` | Updates `org.springframework:spring-orm` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-core` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-beans` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-aop` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-context` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-context-support` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-tx` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-jdbc` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-web` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-webmvc` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-expression` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-test` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-core` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-beans` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-aop` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-context` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-context-support` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-tx` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-jdbc` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-web` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-webmvc` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-expression` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework:spring-test` from 6.2.5 to 6.2.6 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.5...v6.2.6) Updates `org.springframework.security:spring-security-test` from 6.4.4 to 6.4.5 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/6.4.4...6.4.5) --- updated-dependencies: - dependency-name: org.springframework:spring-orm dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-version: 6.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-test dependency-version: 6.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5fbfddd7827d..3568c95996a4 100644 --- a/pom.xml +++ b/pom.xml @@ -19,9 +19,9 @@ 17 - 6.2.5 + 6.2.6 3.4.4 - 6.4.4 + 6.4.5 6.4.8.Final 8.0.1.Final 42.7.5 From 7db6f8922d21290053f24863a455554c96411ad0 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 22 Apr 2025 15:55:52 +0200 Subject: [PATCH 499/632] fix log message (cherry picked from commit 4c9c79bf7bd4882be4157d5ae293a81184086c68) --- .../external/service/impl/ExternalDataServiceImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java b/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java index 59cbe4f9d087..b241f5d782db 100644 --- a/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java @@ -108,8 +108,9 @@ public WorkspaceItem createWorkspaceItemFromExternalDataObject(Context context, } log.info(LogHelper.getHeader(context, "create_item_from_externalDataObject", "Created item" + - "with id: " + item.getID() + " from source: " + externalDataObject.getSource() + " with identifier: " + - externalDataObject.getId())); + " with id: " + item.getID() + + " from source: " + externalDataObject.getSource() + + " with identifier: " + externalDataObject.getId())); try { List providers = suggestionService.getSuggestionProviders(); if (providers != null) { From 5313b9673d0cd5b089abef298662d5d1f7d6f7be Mon Sep 17 00:00:00 2001 From: Agustina Martinez Date: Thu, 20 Mar 2025 12:56:11 +0000 Subject: [PATCH 500/632] Update dim.xsl Added template to correctly parse elements under "others" metadata element (cherry picked from commit ac7da6a477cb7bb42b41560a751223efc870dafa) --- .../config/crosswalks/oai/metadataFormats/dim.xsl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dspace/config/crosswalks/oai/metadataFormats/dim.xsl b/dspace/config/crosswalks/oai/metadataFormats/dim.xsl index ea0aad182092..b659fef931a8 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/dim.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/dim.xsl @@ -36,6 +36,18 @@ + + + + + + + + + + + + @@ -62,6 +74,7 @@ + From 35b48592421574d78a84953109565c0ce492f3bb Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 1 Apr 2025 19:49:28 +0200 Subject: [PATCH 501/632] add method getMaxNumOfItemsPerRequest --- .../java/org/dspace/app/util/service/OpenSearchService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java b/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java index 03f41e535c53..08900f8fff9c 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java +++ b/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java @@ -117,4 +117,10 @@ public Document getResultsDoc(Context context, String format, String query, int public DSpaceObject resolveScope(Context context, String scope) throws SQLException; + /** + * Retrieves the maximum number of items that can be included in a single opensearch request. + * + * @return the maximum number of items allowed per request + */ + int getMaxNumOfItemsPerRequest(); } From a01405cd1816725c305c5049ffc9f24a275138c1 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 1 Apr 2025 19:50:48 +0200 Subject: [PATCH 502/632] implement method getMaxNumOfItemsPerRequest --- .../java/org/dspace/app/util/OpenSearchServiceImpl.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java index bff741b5ca42..2075ef7a3816 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java @@ -101,6 +101,14 @@ protected String getBaseSearchUIURL() { configurationService.getProperty("websvc.opensearch.uicontext"); } + /** + * Get base search UI URL (websvc.opensearch.max_num_of_items_per_request) + */ + public int getMaxNumOfItemsPerRequest() { + return configurationService.getIntProperty( + "websvc.opensearch.max_num_of_items_per_request", 100); + } + @Override public String getContentType(String format) { return "html".equals(format) ? "text/html" : From fe614d5fc5827338058aa43f184c495f9dc1439e Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 1 Apr 2025 19:51:28 +0200 Subject: [PATCH 503/632] add configuration key websvc.opensearch.max_num_of_items_per_request --- dspace/config/dspace.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index c9ae5d521d90..2abe436387dd 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -1376,7 +1376,8 @@ websvc.opensearch.tags = IR DSpace # result formats offered - use 1 or more comma-separated from: html,atom,rss # html uses the normal search module websvc.opensearch.formats = html,atom,rss - +# maximum number of item per request +websvc.opensearch.max_num_of_items_per_request = 100 #### Content Inline Disposition Threshold #### # From 6ad43a508d775c470c44f8af9760d72d5f862c8a Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 1 Apr 2025 19:59:48 +0200 Subject: [PATCH 504/632] restrict maximum value of URL parameter rpp --- .../dspace/app/rest/OpenSearchController.java | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java index baf45c14b6eb..85ec441e20c1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java @@ -21,17 +21,13 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ScopeResolver; import org.dspace.app.util.SyndicationFeed; import org.dspace.app.util.factory.UtilServiceFactory; import org.dspace.app.util.service.OpenSearchService; -import org.dspace.authorize.factory.AuthorizeServiceFactory; -import org.dspace.authorize.service.AuthorizeService; -import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.CollectionService; -import org.dspace.content.service.CommunityService; import org.dspace.core.Context; import org.dspace.core.LogHelper; import org.dspace.core.Utils; @@ -50,7 +46,6 @@ import org.dspace.discovery.indexobject.IndexableItem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -67,12 +62,9 @@ public class OpenSearchController { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(); - private static final String errorpath = "/error"; + private List searchIndices = null; - private CommunityService communityService; - private CollectionService collectionService; - private AuthorizeService authorizeService; private OpenSearchService openSearchService; @Autowired @@ -99,22 +91,28 @@ public void search(HttpServletRequest request, @RequestParam(name = "format", required = false) String format, @RequestParam(name = "sort", required = false) String sort, @RequestParam(name = "sort_direction", required = false) String sortDirection, - @RequestParam(name = "scope", required = false) String dsoObject, - Model model) throws IOException, ServletException { + @RequestParam(name = "scope", required = false) String dsoObject) + throws IOException, ServletException { context = ContextUtil.obtainContext(request); - if (start == null) { - start = 0; - } - if (count == null) { - count = -1; - } + if (openSearchService == null) { openSearchService = UtilServiceFactory.getInstance().getOpenSearchService(); } + if (openSearchService.isEnabled()) { init(); + + if (start == null) { + start = 0; + } + + if (count == null) { + count = -1; + } + count = Math.min(count, openSearchService.getMaxNumOfItemsPerRequest()); + // get enough request parameters to decide on action to take - if (format == null || "".equals(format)) { + if (StringUtils.isEmpty(format)) { // default to atom format = "atom"; } @@ -266,9 +264,6 @@ private void init() { searchIndices.add(sFilter.getIndexFieldName()); } } - communityService = ContentServiceFactory.getInstance().getCommunityService(); - collectionService = ContentServiceFactory.getInstance().getCollectionService(); - authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService(); } public void setOpenSearchService(OpenSearchService oSS) { From df91886375a2a5ddeeaae8e83b94168d37282075 Mon Sep 17 00:00:00 2001 From: Jesiel Viana Date: Tue, 22 Apr 2025 22:12:00 -0300 Subject: [PATCH 505/632] fix: import public email from ORCID person (cherry picked from commit 82ca80cd6b5d340f5d3d2e042803c2fc43d8a973) --- .../impl/OrcidV3AuthorDataProvider.java | 22 +- .../impl/OrcidV3AuthorDataProviderTest.java | 231 ++++++++++++++++++ .../provider/impl/orcid-person/person1.xml | 51 ++++ .../provider/impl/orcid-person/person2.xml | 64 +++++ .../provider/impl/orcid-person/person3.xml | 35 +++ .../provider/impl/orcid-person/search.xml | 25 ++ .../provider/orcid-v3-author/person1.xml | 51 ++++ .../provider/orcid-v3-author/person2.xml | 64 +++++ .../provider/orcid-v3-author/person3.xml | 35 +++ .../provider/orcid-v3-author/search.xml | 25 ++ 10 files changed, 596 insertions(+), 7 deletions(-) create mode 100644 dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProviderTest.java create mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person1.xml create mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person2.xml create mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person3.xml create mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/search.xml create mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person1.xml create mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person2.xml create mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person3.xml create mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/search.xml diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java index c7e41171a5bb..dfbd07a83a02 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java @@ -27,6 +27,7 @@ import org.dspace.external.provider.orcid.xml.XMLtoBio; import org.dspace.orcid.model.factory.OrcidFactoryUtils; import org.orcid.jaxb.model.v3.release.common.OrcidIdentifier; +import org.orcid.jaxb.model.v3.release.record.Email; import org.orcid.jaxb.model.v3.release.record.Person; import org.orcid.jaxb.model.v3.release.search.Result; import org.springframework.beans.factory.annotation.Autowired; @@ -114,13 +115,20 @@ protected ExternalDataObject convertToExternalDataObject(Person person) { if (person.getName().getFamilyName() != null) { lastName = person.getName().getFamilyName().getContent(); externalDataObject.addMetadata(new MetadataValueDTO("person", "familyName", null, null, - lastName)); + lastName)); } if (person.getName().getGivenNames() != null) { firstName = person.getName().getGivenNames().getContent(); externalDataObject.addMetadata(new MetadataValueDTO("person", "givenName", null, null, - firstName)); - + firstName)); + } + if (person.getEmails().getEmails() != null && !person.getEmails().getEmails().isEmpty()) { + Email email = person.getEmails().getEmails().get(0); + if (person.getEmails().getEmails().size() > 1) { + email = person.getEmails().getEmails().stream().filter(Email::isPrimary).findFirst().orElse(email); + } + externalDataObject.addMetadata(new MetadataValueDTO("person", "email", null, + null, email.getEmail())); } externalDataObject.setId(person.getName().getPath()); externalDataObject @@ -128,7 +136,7 @@ protected ExternalDataObject convertToExternalDataObject(Person person) { new MetadataValueDTO("person", "identifier", "orcid", null, person.getName().getPath())); externalDataObject .addMetadata(new MetadataValueDTO("dc", "identifier", "uri", null, - orcidUrl + "/" + person.getName().getPath())); + orcidUrl + "/" + person.getName().getPath())); if (!StringUtils.isBlank(lastName) && !StringUtils.isBlank(firstName)) { externalDataObject.setDisplayValue(lastName + ", " + firstName); externalDataObject.setValue(lastName + ", " + firstName); @@ -139,8 +147,8 @@ protected ExternalDataObject convertToExternalDataObject(Person person) { externalDataObject.setDisplayValue(firstName); externalDataObject.setValue(firstName); } - } else if (person.getPath() != null ) { - externalDataObject.setId(StringUtils.substringBetween(person.getPath(),"/","/person")); + } else if (person.getPath() != null) { + externalDataObject.setId(StringUtils.substringBetween(person.getPath(), "/", "/person")); } return externalDataObject; } @@ -204,7 +212,7 @@ public List searchExternalDataObjects(String query, int star for (Result result : results) { OrcidIdentifier orcidIdentifier = result.getOrcidIdentifier(); if (orcidIdentifier != null) { - log.debug("Found OrcidId=" + orcidIdentifier.toString()); + log.debug("Found OrcidId=" + orcidIdentifier.getPath()); String orcid = orcidIdentifier.getPath(); Person bio = getBio(orcid); if (bio != null) { diff --git a/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProviderTest.java b/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProviderTest.java new file mode 100644 index 000000000000..34b3a6838d4e --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProviderTest.java @@ -0,0 +1,231 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.external.provider.impl; + +import org.dspace.AbstractDSpaceTest; +import org.dspace.external.OrcidRestConnector; +import org.dspace.external.model.ExternalDataObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.InputStream; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +/** + * Unit tests for {@link OrcidV3AuthorDataProvider}. + * + * @author Jesiel Viana (jesielviana at proton.me) + * + */ +public class OrcidV3AuthorDataProviderTest extends AbstractDSpaceTest { + + private static final String SEARCH_XML_PATH = "org/dspace/external/provider/orcid-v3-author/search.xml"; + private static final String PERSON1_XML_PATH = "org/dspace/external/provider/orcid-v3-author/person1.xml"; + private static final String PERSON2_XML_PATH = "org/dspace/external/provider/orcid-v3-author/person2.xml"; + private static final String PERSON3_XML_PATH = "org/dspace/external/provider/orcid-v3-author/person3.xml"; + + public static final String ORCID_SEARCH_QUERY = "search?q=0000-0000-0000-0000"; + + private OrcidV3AuthorDataProvider dataProvider; + + @Before + public void setup() throws Exception { + dataProvider = new OrcidV3AuthorDataProvider(); + + OrcidRestConnector mockRestConnector = mock(OrcidRestConnector.class); + + dataProvider.setOrcidRestConnector(mockRestConnector); + dataProvider.setSourceIdentifier("orcid"); + dataProvider.setOrcidUrl("https://orcid.org"); + + dataProvider.setClientId("client-id"); + dataProvider.setClientSecret("client-secret"); + dataProvider.setOAUTHUrl("https://orcid.org/oauth"); + + InputStream searchXmlStream = getClass().getClassLoader().getResourceAsStream(SEARCH_XML_PATH); + InputStream person1XmlStream = getClass().getClassLoader().getResourceAsStream(PERSON1_XML_PATH); + InputStream person2XmlStream = getClass().getClassLoader().getResourceAsStream(PERSON2_XML_PATH); + InputStream person3XmlStream = getClass().getClassLoader().getResourceAsStream(PERSON3_XML_PATH); + + when(mockRestConnector.get("search?q=search%3Fq%3D0000-0000-0000-0000&start=0&rows=10",null )).thenReturn(searchXmlStream); + when(mockRestConnector.get("0000-0000-0000-0001/person",null )).thenReturn(person1XmlStream); + when(mockRestConnector.get("0000-0000-0000-0002/person",null )).thenReturn(person2XmlStream); + when(mockRestConnector.get("0000-0000-0000-0003/person",null )).thenReturn(person3XmlStream); + + } + + @Test + public void testGetExternalDataObjectSizeIsCorrect() { + List optional = dataProvider.searchExternalDataObjects(ORCID_SEARCH_QUERY, 0, 10); + assertThat(optional, hasSize(3)); + } + + @Test + public void testGetExternalDataObjectGetPersonWithAllFieldsPopulated() { + List optional = dataProvider.searchExternalDataObjects(ORCID_SEARCH_QUERY, 0, 10); + + assertThat(optional, hasSize(3)); + + ExternalDataObject externalDataObject1 = optional.get(0); + + // Basic field assertions + assertThat(externalDataObject1.getId(), equalTo("0000-0000-0000-0001")); + assertThat(externalDataObject1.getValue(), equalTo("FamilyName1, GivenNames1")); + assertThat(externalDataObject1.getSource(), equalTo("orcid")); + assertThat(externalDataObject1.getDisplayValue(), equalTo("FamilyName1, GivenNames1")); + + // Metadata assertions + assertThat(externalDataObject1.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("familyName")), + hasProperty("value", equalTo("FamilyName1")) + ) + )); + assertThat(externalDataObject1.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("givenName")), + hasProperty("value", equalTo("GivenNames1")) + ) + )); + assertThat(externalDataObject1.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("email")), + hasProperty("value", equalTo("person1@email.com")) + ) + )); + assertThat(externalDataObject1.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("identifier")), + hasProperty("qualifier", equalTo("orcid")), + hasProperty("value", equalTo("0000-0000-0000-0001")) + ) + )); + assertThat(externalDataObject1.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("dc")), + hasProperty("element", equalTo("identifier")), + hasProperty("qualifier", equalTo("uri")), + hasProperty("value", equalTo("https://orcid.org/0000-0000-0000-0001")) + ) + )); + } + + @Test + public void testGetExternalDataObjectGetPrimaryEmailFromPersonWithTwoEmails() { + List optional = dataProvider.searchExternalDataObjects(ORCID_SEARCH_QUERY, 0, 10); + + assertThat(optional, hasSize(3)); + + ExternalDataObject externalDataObject2 = optional.get(1); // Test person2 (with two emails) + + // Basic field assertions + assertThat(externalDataObject2.getId(), equalTo("0000-0000-0000-0002")); + assertThat(externalDataObject2.getValue(), equalTo("FamilyName2, GivenNames2")); + assertThat(externalDataObject2.getSource(), equalTo("orcid")); + assertThat(externalDataObject2.getDisplayValue(), equalTo("FamilyName2, GivenNames2")); + + // Metadata assertions + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("familyName")), + hasProperty("value", equalTo("FamilyName2")) + ) + )); + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("givenName")), + hasProperty("value", equalTo("GivenNames2")) + ) + )); + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("email")), + hasProperty("value", equalTo("person2primary@email.com")) // Primary email + ) + )); + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("identifier")), + hasProperty("qualifier", equalTo("orcid")), + hasProperty("value", equalTo("0000-0000-0000-0002")) + ) + )); + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("dc")), + hasProperty("element", equalTo("identifier")), + hasProperty("qualifier", equalTo("uri")), + hasProperty("value", equalTo("https://orcid.org/0000-0000-0000-0002")) + ) + )); + } + + + @Test + public void testGetExternalDataObjectGetPersonOnlyWithNameFilled() { + List optional = dataProvider.searchExternalDataObjects(ORCID_SEARCH_QUERY, 0, 10); + + assertThat(optional, hasSize(3)); + + ExternalDataObject externalDataObject2 = optional.get(2); // Test person2 (with two emails) + + // Basic field assertions + assertThat(externalDataObject2.getId(), equalTo("0000-0000-0000-0003")); + assertThat(externalDataObject2.getValue(), equalTo("FamilyName3, GivenNames3")); + assertThat(externalDataObject2.getSource(), equalTo("orcid")); + assertThat(externalDataObject2.getDisplayValue(), equalTo("FamilyName3, GivenNames3")); + + // Metadata assertions + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("familyName")), + hasProperty("value", equalTo("FamilyName3")) + ) + )); + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("givenName")), + hasProperty("value", equalTo("GivenNames3")) + ) + )); + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("person")), + hasProperty("element", equalTo("identifier")), + hasProperty("qualifier", equalTo("orcid")), + hasProperty("value", equalTo("0000-0000-0000-0003")) + ) + )); + assertThat(externalDataObject2.getMetadata(), hasItem( + allOf( + hasProperty("schema", equalTo("dc")), + hasProperty("element", equalTo("identifier")), + hasProperty("qualifier", equalTo("uri")), + hasProperty("value", equalTo("https://orcid.org/0000-0000-0000-0003")) + ) + )); + } +} diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person1.xml b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person1.xml new file mode 100644 index 000000000000..64e4b292b92b --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person1.xml @@ -0,0 +1,51 @@ + + + 2025-04-21T22:28:18.862Z + + 2025-04-11T15:41:21.340Z + 2025-04-11T15:41:21.340Z + GivenNames1 + FamilyName1 + + + + + 2025-04-21T22:28:18.862Z + + 2025-04-21T22:23:14.698Z + 2025-04-21T22:28:18.862Z + + + https://sandbox.orcid.org/0000-0000-0000-0001 + 0000-0000-0000-0001 + sandbox.orcid.org + + GivenNames1 FamilyName1 + + person1@email.com + + + + + + diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person2.xml b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person2.xml new file mode 100644 index 000000000000..c91b0207247d --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person2.xml @@ -0,0 +1,64 @@ + + + 2025-04-21T22:28:18.862Z + + 2025-04-11T15:41:21.340Z + 2025-04-11T15:41:21.340Z + GivenNames2 + FamilyName2 + + + + + 2025-04-21T22:28:18.862Z + + 2025-04-21T22:23:14.698Z + 2025-04-21T22:28:18.862Z + + + https://sandbox.orcid.org/0000-0000-0000-0002 + 0000-0000-0000-0002 + sandbox.orcid.org + + GivenNames2 FamilyName2 + + person2@email.com + + + 2025-04-21T16:42:54.961Z + 2025-04-21T16:48:32.642Z + + + https://sandbox.orcid.org/0000-0000-0000-0001 + 0000-0000-0000-0001 + sandbox.orcid.org + + GivenNames1 FamilyName1 + + person2primary@email.com + + + + + + diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person3.xml b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person3.xml new file mode 100644 index 000000000000..b24ed9d3547a --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person3.xml @@ -0,0 +1,35 @@ + + + + 2024-06-11T20:01:28.538Z + 2024-06-11T20:01:28.538Z + GivenNames3 + FamilyName3 + + + + + + + + diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/search.xml b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/search.xml new file mode 100644 index 000000000000..98ec721be9b8 --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/search.xml @@ -0,0 +1,25 @@ + + + + + https://sandbox.orcid.org/0000-0000-0000-0001 + 0000-0000-0000-0001 + sandbox.orcid.org + + + + + https://sandbox.orcid.org/0000-0000-0000-0002 + 0000-0000-0000-0002 + sandbox.orcid.org + + + + + https://sandbox.orcid.org/0000-0000-0000-0003 + 0000-0000-0000-0003 + sandbox.orcid.org + + + diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person1.xml b/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person1.xml new file mode 100644 index 000000000000..64e4b292b92b --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person1.xml @@ -0,0 +1,51 @@ + + + 2025-04-21T22:28:18.862Z + + 2025-04-11T15:41:21.340Z + 2025-04-11T15:41:21.340Z + GivenNames1 + FamilyName1 + + + + + 2025-04-21T22:28:18.862Z + + 2025-04-21T22:23:14.698Z + 2025-04-21T22:28:18.862Z + + + https://sandbox.orcid.org/0000-0000-0000-0001 + 0000-0000-0000-0001 + sandbox.orcid.org + + GivenNames1 FamilyName1 + + person1@email.com + + + + + + diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person2.xml b/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person2.xml new file mode 100644 index 000000000000..c91b0207247d --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person2.xml @@ -0,0 +1,64 @@ + + + 2025-04-21T22:28:18.862Z + + 2025-04-11T15:41:21.340Z + 2025-04-11T15:41:21.340Z + GivenNames2 + FamilyName2 + + + + + 2025-04-21T22:28:18.862Z + + 2025-04-21T22:23:14.698Z + 2025-04-21T22:28:18.862Z + + + https://sandbox.orcid.org/0000-0000-0000-0002 + 0000-0000-0000-0002 + sandbox.orcid.org + + GivenNames2 FamilyName2 + + person2@email.com + + + 2025-04-21T16:42:54.961Z + 2025-04-21T16:48:32.642Z + + + https://sandbox.orcid.org/0000-0000-0000-0001 + 0000-0000-0000-0001 + sandbox.orcid.org + + GivenNames1 FamilyName1 + + person2primary@email.com + + + + + + diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person3.xml b/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person3.xml new file mode 100644 index 000000000000..b24ed9d3547a --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/person3.xml @@ -0,0 +1,35 @@ + + + + 2024-06-11T20:01:28.538Z + 2024-06-11T20:01:28.538Z + GivenNames3 + FamilyName3 + + + + + + + + diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/search.xml b/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/search.xml new file mode 100644 index 000000000000..98ec721be9b8 --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/external/provider/orcid-v3-author/search.xml @@ -0,0 +1,25 @@ + + + + + https://sandbox.orcid.org/0000-0000-0000-0001 + 0000-0000-0000-0001 + sandbox.orcid.org + + + + + https://sandbox.orcid.org/0000-0000-0000-0002 + 0000-0000-0000-0002 + sandbox.orcid.org + + + + + https://sandbox.orcid.org/0000-0000-0000-0003 + 0000-0000-0000-0003 + sandbox.orcid.org + + + From 0c895d07b6e8d98a2cc809e556bc1d015c2ff185 Mon Sep 17 00:00:00 2001 From: Jesiel Viana Date: Tue, 22 Apr 2025 23:19:56 -0300 Subject: [PATCH 506/632] fix: Checkstyle violations (cherry picked from commit 9a831e53933771228c7e141db3d0217651d5b32c) --- .../impl/OrcidV3AuthorDataProviderTest.java | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProviderTest.java b/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProviderTest.java index 34b3a6838d4e..a68c0519bae5 100644 --- a/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProviderTest.java +++ b/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProviderTest.java @@ -7,22 +7,24 @@ */ package org.dspace.external.provider.impl; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.core.AllOf.allOf; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.InputStream; +import java.util.List; + import org.dspace.AbstractDSpaceTest; import org.dspace.external.OrcidRestConnector; import org.dspace.external.model.ExternalDataObject; -import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.io.InputStream; -import java.util.List; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; /** * Unit tests for {@link OrcidV3AuthorDataProvider}. @@ -60,10 +62,11 @@ public void setup() throws Exception { InputStream person2XmlStream = getClass().getClassLoader().getResourceAsStream(PERSON2_XML_PATH); InputStream person3XmlStream = getClass().getClassLoader().getResourceAsStream(PERSON3_XML_PATH); - when(mockRestConnector.get("search?q=search%3Fq%3D0000-0000-0000-0000&start=0&rows=10",null )).thenReturn(searchXmlStream); - when(mockRestConnector.get("0000-0000-0000-0001/person",null )).thenReturn(person1XmlStream); - when(mockRestConnector.get("0000-0000-0000-0002/person",null )).thenReturn(person2XmlStream); - when(mockRestConnector.get("0000-0000-0000-0003/person",null )).thenReturn(person3XmlStream); + when(mockRestConnector.get("search?q=search%3Fq%3D0000-0000-0000-0000&start=0&rows=10", null)) + .thenReturn(searchXmlStream); + when(mockRestConnector.get("0000-0000-0000-0001/person", null)).thenReturn(person1XmlStream); + when(mockRestConnector.get("0000-0000-0000-0002/person", null)).thenReturn(person2XmlStream); + when(mockRestConnector.get("0000-0000-0000-0003/person", null)).thenReturn(person3XmlStream); } From 103ed21039d18c07ad6a43bb6ca80946a7255fc4 Mon Sep 17 00:00:00 2001 From: Jesiel Viana Date: Tue, 22 Apr 2025 23:44:10 -0300 Subject: [PATCH 507/632] removing duplicated files (cherry picked from commit c6d1121cbe90ee9c12847f283a3d00601acceaa3) --- .../provider/impl/orcid-person/person1.xml | 51 --------------- .../provider/impl/orcid-person/person2.xml | 64 ------------------- .../provider/impl/orcid-person/person3.xml | 35 ---------- .../provider/impl/orcid-person/search.xml | 25 -------- 4 files changed, 175 deletions(-) delete mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person1.xml delete mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person2.xml delete mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person3.xml delete mode 100644 dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/search.xml diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person1.xml b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person1.xml deleted file mode 100644 index 64e4b292b92b..000000000000 --- a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person1.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - 2025-04-21T22:28:18.862Z - - 2025-04-11T15:41:21.340Z - 2025-04-11T15:41:21.340Z - GivenNames1 - FamilyName1 - - - - - 2025-04-21T22:28:18.862Z - - 2025-04-21T22:23:14.698Z - 2025-04-21T22:28:18.862Z - - - https://sandbox.orcid.org/0000-0000-0000-0001 - 0000-0000-0000-0001 - sandbox.orcid.org - - GivenNames1 FamilyName1 - - person1@email.com - - - - - - diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person2.xml b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person2.xml deleted file mode 100644 index c91b0207247d..000000000000 --- a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person2.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - 2025-04-21T22:28:18.862Z - - 2025-04-11T15:41:21.340Z - 2025-04-11T15:41:21.340Z - GivenNames2 - FamilyName2 - - - - - 2025-04-21T22:28:18.862Z - - 2025-04-21T22:23:14.698Z - 2025-04-21T22:28:18.862Z - - - https://sandbox.orcid.org/0000-0000-0000-0002 - 0000-0000-0000-0002 - sandbox.orcid.org - - GivenNames2 FamilyName2 - - person2@email.com - - - 2025-04-21T16:42:54.961Z - 2025-04-21T16:48:32.642Z - - - https://sandbox.orcid.org/0000-0000-0000-0001 - 0000-0000-0000-0001 - sandbox.orcid.org - - GivenNames1 FamilyName1 - - person2primary@email.com - - - - - - diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person3.xml b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person3.xml deleted file mode 100644 index b24ed9d3547a..000000000000 --- a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/person3.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - 2024-06-11T20:01:28.538Z - 2024-06-11T20:01:28.538Z - GivenNames3 - FamilyName3 - - - - - - - - diff --git a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/search.xml b/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/search.xml deleted file mode 100644 index 98ec721be9b8..000000000000 --- a/dspace-api/src/test/resources/org/dspace/external/provider/impl/orcid-person/search.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - https://sandbox.orcid.org/0000-0000-0000-0001 - 0000-0000-0000-0001 - sandbox.orcid.org - - - - - https://sandbox.orcid.org/0000-0000-0000-0002 - 0000-0000-0000-0002 - sandbox.orcid.org - - - - - https://sandbox.orcid.org/0000-0000-0000-0003 - 0000-0000-0000-0003 - sandbox.orcid.org - - - From 7db214597701df1b7ce4135543bb909253a8540c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 23:55:43 +0000 Subject: [PATCH 508/632] Bump the spring group with 12 updates Bumps the spring group with 12 updates: | Package | From | To | | --- | --- | --- | | [org.springframework.boot:spring-boot-starter-test](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-tomcat](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-maven-plugin](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-cache](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-thymeleaf](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-web](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-data-rest](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-security](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-aop](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-actuator](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | | [org.springframework.boot:spring-boot-starter-log4j2](https://github.com/spring-projects/spring-boot) | `3.4.4` | `3.4.5` | Updates `org.springframework.boot:spring-boot-starter-test` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-thymeleaf` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-thymeleaf` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.4 to 3.4.5 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter-test dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-thymeleaf dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-thymeleaf dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 44b0bb628c13..d09af4f235b1 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 17 6.2.6 - 3.4.4 + 3.4.5 6.4.5 6.4.8.Final 8.0.1.Final From 98be99953a9a6914ad5f874d9a056365264bf744 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 23:59:08 +0000 Subject: [PATCH 509/632] Bump the fasterxml group with 4 updates Bumps the fasterxml group with 4 updates: [com.fasterxml.jackson.core:jackson-annotations](https://github.com/FasterXML/jackson), [com.fasterxml.jackson.core:jackson-core](https://github.com/FasterXML/jackson-core), [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) and com.fasterxml.jackson.datatype:jackson-datatype-jsr310. Updates `com.fasterxml.jackson.core:jackson-annotations` from 2.18.3 to 2.19.0 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.18.3 to 2.19.0 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.18.3...jackson-core-2.19.0) Updates `com.fasterxml.jackson.core:jackson-core` from 2.18.3 to 2.19.0 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.18.3...jackson-core-2.19.0) Updates `com.fasterxml.jackson.core:jackson-databind` from 2.18.3 to 2.19.0 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.18.3 to 2.19.0 Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.18.3 to 2.19.0 --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-version: 2.19.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-version: 2.19.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-version: 2.19.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-version: 2.19.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-version: 2.19.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-version: 2.19.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: fasterxml ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 44b0bb628c13..2236cd4c2840 100644 --- a/pom.xml +++ b/pom.xml @@ -31,8 +31,8 @@ 3.10.8 2.38.0 - 2.18.3 - 2.18.3 + 2.19.0 + 2.19.0 2.1.1 4.0.2 4.0.5 From 8b617256a00081710fde7128a243cfbe7b375c19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Apr 2025 00:00:49 +0000 Subject: [PATCH 510/632] Bump org.apache.httpcomponents.client5:httpclient5 from 5.4.3 to 5.4.4 Bumps [org.apache.httpcomponents.client5:httpclient5](https://github.com/apache/httpcomponents-client) from 5.4.3 to 5.4.4. - [Changelog](https://github.com/apache/httpcomponents-client/blob/rel/v5.4.4/RELEASE_NOTES.txt) - [Commits](https://github.com/apache/httpcomponents-client/compare/rel/v5.4.3...rel/v5.4.4) --- updated-dependencies: - dependency-name: org.apache.httpcomponents.client5:httpclient5 dependency-version: 5.4.4 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 4b92e9f40170..153f59e8d5ab 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -590,7 +590,7 @@ org.apache.httpcomponents.client5 httpclient5 - 5.4.3 + 5.4.4 test From ecd55eabb0eb229c5b4cd6ffd94375709dc84d7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Apr 2025 00:01:56 +0000 Subject: [PATCH 511/632] Bump the apache-commons group with 2 updates Bumps the apache-commons group with 2 updates: org.apache.commons:commons-collections4 and org.apache.commons:commons-configuration2. Updates `org.apache.commons:commons-collections4` from 4.4 to 4.5.0 Updates `org.apache.commons:commons-configuration2` from 2.11.0 to 2.12.0 --- updated-dependencies: - dependency-name: org.apache.commons:commons-collections4 dependency-version: 4.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-configuration2 dependency-version: 2.12.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 44b0bb628c13..9d0c43c08abe 100644 --- a/pom.xml +++ b/pom.xml @@ -1483,12 +1483,12 @@ org.apache.commons commons-collections4 - 4.4 + 4.5.0 org.apache.commons commons-configuration2 - 2.11.0 + 2.12.0 org.apache.commons From 845a35319cbc9a41246addf9bf663c5c5acc00cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Apr 2025 00:03:05 +0000 Subject: [PATCH 512/632] Bump com.google.code.gson:gson from 2.13.0 to 2.13.1 Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.13.0 to 2.13.1. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.13.0...gson-parent-2.13.1) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-version: 2.13.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 44b0bb628c13..e0367d0a76e0 100644 --- a/pom.xml +++ b/pom.xml @@ -1358,7 +1358,7 @@ com.google.code.gson gson - 2.13.0 + 2.13.1 9.4.57.v20241219 2.24.3 - 2.0.33 + 2.0.34 1.19.0 2.0.17 2.9.3 From b2eaf663bba7bdf0e1e95a393fe1a27123eeeb3e Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 29 Apr 2025 17:35:19 +0200 Subject: [PATCH 514/632] Make getAllFacetConfigs unique Improve performance and debuggability by refactoring getAllFacetConfigs to getAllUniqueFacetConfigs. Used only by ChoiceAuthorityService to generate hierarchical vocabulary map for the browse menu, etc. (cherry picked from commit 159bd18529b5f0918cc0bc07e2b4fee16e4f2511) --- .../authority/ChoiceAuthorityServiceImpl.java | 2 +- .../DiscoveryConfigurationService.java | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/authority/ChoiceAuthorityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/authority/ChoiceAuthorityServiceImpl.java index f4d1f02710e1..bbe8e4461fe0 100644 --- a/dspace-api/src/main/java/org/dspace/content/authority/ChoiceAuthorityServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/authority/ChoiceAuthorityServiceImpl.java @@ -577,7 +577,7 @@ public DSpaceControlledVocabularyIndex getVocabularyIndex(String nameVocab) { .collect(Collectors.toList())); } DiscoverySearchFilterFacet matchingFacet = null; - for (DiscoverySearchFilterFacet facetConfig : searchConfigurationService.getAllFacetsConfig()) { + for (DiscoverySearchFilterFacet facetConfig : searchConfigurationService.getAllUniqueFacetsConfig()) { boolean coversAllFieldsFromVocab = true; for (String fieldFromVocab: metadataFields) { boolean coversFieldFromVocab = false; diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java index 6cb93e2993f3..9d603941de39 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java @@ -10,8 +10,10 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -197,15 +199,19 @@ public List getIndexAlwaysConfigurations() { } /** - * @return All configurations for {@link org.dspace.discovery.configuration.DiscoverySearchFilterFacet} + * Get the unique set of configured Discovery facets. This is used when inspecting configuration + * to include hierarchical vocabularies in the browse menu. + * + * @return All unique instances of {@link org.dspace.discovery.configuration.DiscoverySearchFilterFacet} + * included in "sidebarFacets" bean, across all Discovery configurations. */ - public List getAllFacetsConfig() { - List configs = new ArrayList<>(); + public List getAllUniqueFacetsConfig() { + Set configs = new LinkedHashSet<>(); for (String key : map.keySet()) { DiscoveryConfiguration config = map.get(key); configs.addAll(config.getSidebarFacets()); } - return configs; + return new ArrayList<>(configs); } public static void main(String[] args) { From 1f2354a3dc1ebbc239bb9f48ad1b322be74742b7 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 23 Apr 2025 18:55:29 +0200 Subject: [PATCH 515/632] Add help opt and javadoc to InitializeEntities (cherry picked from commit 5240a029965807e4757316aa1a965c4102c0d4f4) --- .../dspace/app/util/InitializeEntities.java | 76 +++++++++++++++++-- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java index 0a072a9819eb..8d3964a3e3c7 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java +++ b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java @@ -64,20 +64,36 @@ private InitializeEntities() { */ public static void main(String[] argv) throws SQLException, AuthorizeException, ParseException { InitializeEntities initializeEntities = new InitializeEntities(); + // Set up command-line options and parse arguments CommandLineParser parser = new DefaultParser(); Options options = createCommandLineOptions(); CommandLine line = parser.parse(options,argv); - String fileLocation = getFileLocationFromCommandLine(line); + // First of all, check if the help option was entered or a required argument is missing checkHelpEntered(options, line); + // Get the file location from the command line + String fileLocation = getFileLocationFromCommandLine(line); + // Run the script initializeEntities.run(fileLocation); } + + /** + * Check if the help option was entered or a required argument is missing. If so, print help and exit. + * @param options the defined command-line options + * @param line the parsed command-line arguments + */ private static void checkHelpEntered(Options options, CommandLine line) { - if (line.hasOption("h")) { + if (line.hasOption("h") || !line.hasOption("f")) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("Intialize Entities", options); System.exit(0); } } + + /** + * Get the file path from the command-line argument. Exits with exit code 1 if no file argument was entered. + * @param line the parsed command-line arguments + * @return the file path + */ private static String getFileLocationFromCommandLine(CommandLine line) { String query = line.getOptionValue("f"); if (StringUtils.isEmpty(query)) { @@ -88,13 +104,25 @@ private static String getFileLocationFromCommandLine(CommandLine line) { return query; } + /** + * Create the command-line options + * @return the command-line options + */ protected static Options createCommandLineOptions() { Options options = new Options(); - options.addOption("f", "file", true, "the location for the file containing the xml data"); + options.addOption("f", "file", true, "the path to the file containing the " + + "relationship definitions (e.g. ${dspace.dir}/config/entities/relationship-types.xml)"); + options.addOption("h", "help", false, "print this message"); return options; } + /** + * Run the script for the given file location + * @param fileLocation the file location + * @throws SQLException If something goes wrong initializing context or inserting relationship types + * @throws AuthorizeException If the script user fails to authorize while inserting relationship types + */ private void run(String fileLocation) throws SQLException, AuthorizeException { Context context = new Context(); context.turnOffAuthorisationSystem(); @@ -102,6 +130,12 @@ private void run(String fileLocation) throws SQLException, AuthorizeException { context.complete(); } + /** + * Parse the XML file at fileLocation to create relationship types in the database + * @param context DSpace context + * @param fileLocation the full or relative file path to the relationship types XML + * @throws AuthorizeException If the script user fails to authorize while inserting relationship types + */ private void parseXMLToRelations(Context context, String fileLocation) throws AuthorizeException { try { File fXmlFile = new File(fileLocation); @@ -158,15 +192,15 @@ private void parseXMLToRelations(Context context, String fileLocation) throws Au for (int j = 0; j < leftCardinalityList.getLength(); j++) { Node node = leftCardinalityList.item(j); - leftCardinalityMin = getString(leftCardinalityMin,(Element) node, "min"); - leftCardinalityMax = getString(leftCardinalityMax,(Element) node, "max"); + leftCardinalityMin = getCardinalityMinString(leftCardinalityMin,(Element) node, "min"); + leftCardinalityMax = getCardinalityMinString(leftCardinalityMax,(Element) node, "max"); } for (int j = 0; j < rightCardinalityList.getLength(); j++) { Node node = rightCardinalityList.item(j); - rightCardinalityMin = getString(rightCardinalityMin,(Element) node, "min"); - rightCardinalityMax = getString(rightCardinalityMax,(Element) node, "max"); + rightCardinalityMin = getCardinalityMinString(rightCardinalityMin,(Element) node, "min"); + rightCardinalityMax = getCardinalityMinString(rightCardinalityMax,(Element) node, "max"); } populateRelationshipType(context, leftType, rightType, leftwardType, rightwardType, @@ -182,13 +216,39 @@ private void parseXMLToRelations(Context context, String fileLocation) throws Au } } - private String getString(String leftCardinalityMin,Element node, String minOrMax) { + /** + * Extract the min or max value for the left or right cardinality from the node text content + * @param leftCardinalityMin current left cardinality min + * @param node node to extract the min or max value from + * @param minOrMax element tag name to parse + * @return final left cardinality min + */ + private String getCardinalityMinString(String leftCardinalityMin, Element node, String minOrMax) { if (node.getElementsByTagName(minOrMax).getLength() > 0) { leftCardinalityMin = node.getElementsByTagName(minOrMax).item(0).getTextContent(); } return leftCardinalityMin; } + /** + * Populate the relationship type based on values parsed from the XML relationship types configuration + * + * @param context DSpace context + * @param leftType left relationship type (e.g. "Publication"). + * @param rightType right relationship type (e.g. "Journal"). + * @param leftwardType leftward relationship type (e.g. "isAuthorOfPublication"). + * @param rightwardType rightward relationship type (e.g. "isPublicationOfAuthor"). + * @param leftCardinalityMin left cardinality min + * @param leftCardinalityMax left cardinality max + * @param rightCardinalityMin right cardinality min + * @param rightCardinalityMax right cardinality max + * @param copyToLeft copy metadata values to left if right side is deleted + * @param copyToRight copy metadata values to right if left side is deleted + * @param tilted set a tilted relationship side (left or right) if there are many relationships going one way + * to help performance (e.g. authors with 1000s of publications) + * @throws SQLException if database error occurs while saving the relationship type + * @throws AuthorizeException if authorization error occurs while saving the relationship type + */ private void populateRelationshipType(Context context, String leftType, String rightType, String leftwardType, String rightwardType, String leftCardinalityMin, String leftCardinalityMax, String rightCardinalityMin, String rightCardinalityMax, From 505cb9bbd57693bfcdf80c7ca29d4f8c671687fb Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 23 Apr 2025 19:02:30 +0200 Subject: [PATCH 516/632] Improve help and docs for RegistryLoader And a few other small improvements (cherry picked from commit f1b4e6ef174559f901354176f934b05e3d698d58) --- .../org/dspace/administer/RegistryLoader.java | 132 +++++++++++++----- 1 file changed, 94 insertions(+), 38 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java b/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java index bbf320a0d5e5..d503bfc00b7f 100644 --- a/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java +++ b/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java @@ -21,6 +21,13 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.BitstreamFormat; @@ -41,7 +48,7 @@ *

    * RegistryLoader -bitstream bitstream-formats.xml *

    - * RegistryLoader -dc dc-types.xml + * RegistryLoader -metadata dc-types.xml * * @author Robert Tansley * @version $Revision$ @@ -50,7 +57,7 @@ public class RegistryLoader { /** * log4j category */ - private static Logger log = org.apache.logging.log4j.LogManager.getLogger(RegistryLoader.class); + private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RegistryLoader.class); protected static BitstreamFormatService bitstreamFormatService = ContentServiceFactory.getInstance() .getBitstreamFormatService(); @@ -67,48 +74,97 @@ private RegistryLoader() { } * @throws Exception if error */ public static void main(String[] argv) throws Exception { - String usage = "Usage: " + RegistryLoader.class.getName() - + " (-bitstream | -metadata) registry-file.xml"; - - Context context = null; + // Set up command-line options and parse arguments + CommandLineParser parser = new DefaultParser(); + Options options = createCommandLineOptions(); try { - context = new Context(); + CommandLine line = parser.parse(options, argv); + + // Check if help option was entered or no options provided + if (line.hasOption('h') || line.getOptions().length == 0) { + printHelp(options); + System.exit(0); + } + + Context context = new Context(); // Can't update registries anonymously, so we need to turn off // authorisation context.turnOffAuthorisationSystem(); - // Work out what we're loading - if (argv[0].equalsIgnoreCase("-bitstream")) { - RegistryLoader.loadBitstreamFormats(context, argv[1]); - } else if (argv[0].equalsIgnoreCase("-metadata")) { - // Call MetadataImporter, as it handles Metadata schema updates - MetadataImporter.loadRegistry(argv[1], true); - } else { - System.err.println(usage); + try { + // Work out what we're loading + if (line.hasOption('b')) { + String filename = line.getOptionValue('b'); + if (StringUtils.isEmpty(filename)) { + System.err.println("No file path provided for bitstream format registry"); + printHelp(options); + System.exit(1); + } + RegistryLoader.loadBitstreamFormats(context, filename); + } else if (line.hasOption('m')) { + String filename = line.getOptionValue('m'); + if (StringUtils.isEmpty(filename)) { + System.err.println("No file path provided for metadata registry"); + printHelp(options); + System.exit(1); + } + // Call MetadataImporter, as it handles Metadata schema updates + MetadataImporter.loadRegistry(filename, true); + } else { + System.err.println("No registry type specified"); + printHelp(options); + System.exit(1); + } + + // Commit changes and close Context + context.complete(); + System.exit(0); + } catch (Exception e) { + log.fatal(LogHelper.getHeader(context, "error_loading_registries", ""), e); + System.err.println("Error: \n - " + e.getMessage()); + System.exit(1); + } finally { + // Clean up our context, if it still exists & it was never completed + if (context != null && context.isValid()) { + context.abort(); + } } + } catch (ParseException e) { + System.err.println("Error parsing command-line arguments: " + e.getMessage()); + printHelp(options); + System.exit(1); + } + } - // Commit changes and close Context - context.complete(); + /** + * Create the command-line options + * @return the command-line options + */ + private static Options createCommandLineOptions() { + Options options = new Options(); - System.exit(0); - } catch (ArrayIndexOutOfBoundsException ae) { - System.err.println(usage); + options.addOption("b", "bitstream", true, "load bitstream format registry from specified file"); + options.addOption("m", "metadata", true, "load metadata registry from specified file"); + options.addOption("h", "help", false, "print this help message"); - System.exit(1); - } catch (Exception e) { - log.fatal(LogHelper.getHeader(context, "error_loading_registries", - ""), e); + return options; + } - System.err.println("Error: \n - " + e.getMessage()); - System.exit(1); - } finally { - // Clean up our context, if it still exists & it was never completed - if (context != null && context.isValid()) { - context.abort(); - } - } + /** + * Print the help message + * @param options the command-line options + */ + private static void printHelp(Options options) { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("RegistryLoader", + "Load bitstream format or metadata registries into the database\n", + options, + "\nExamples:\n" + + " RegistryLoader -b bitstream-formats.xml\n" + + " RegistryLoader -m dc-types.xml", + true); } /** @@ -221,7 +277,7 @@ private static Document loadXML(String filename) throws IOException, * contains: *

    * - * <foo><mimetype>application/pdf</mimetype></foo> + * application/pdf * * passing this the foo node and mimetype will * return application/pdf. @@ -262,10 +318,10 @@ private static String getElementData(Node parentElement, String childName) * document contains: *

    * - * <foo> - * <bar>val1</bar> - * <bar>val2</bar> - * </foo> + * + * val1 + * val2 + * * * passing this the foo node and bar will * return val1 and val2. @@ -295,4 +351,4 @@ private static String[] getRepeatedElementData(Node parentElement, return data; } -} +} \ No newline at end of file From b9a7226d554380e9d3e7293ee7f9c037d1a11b74 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 23 Apr 2025 19:22:12 +0200 Subject: [PATCH 517/632] Let Curation CLI accept uuid identifiers (cherry picked from commit 5020689095549054c987c1fe4481a37aa86f3877) --- .../main/java/org/dspace/curate/Curation.java | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/curate/Curation.java b/dspace-api/src/main/java/org/dspace/curate/Curation.java index 625692a866b3..b894dcd85f03 100644 --- a/dspace-api/src/main/java/org/dspace/curate/Curation.java +++ b/dspace-api/src/main/java/org/dspace/curate/Curation.java @@ -24,6 +24,8 @@ import org.apache.commons.cli.ParseException; import org.apache.commons.io.output.NullOutputStream; +import org.dspace.app.util.DSpaceObjectUtilsImpl; +import org.dspace.app.util.service.DSpaceObjectUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.factory.ContentServiceFactory; @@ -35,6 +37,7 @@ import org.dspace.handle.factory.HandleServiceFactory; import org.dspace.handle.service.HandleService; import org.dspace.scripts.DSpaceRunnable; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.utils.DSpace; /** @@ -45,7 +48,9 @@ public class Curation extends DSpaceRunnable { protected EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService(); - + protected DSpaceObjectUtils dspaceObjectUtils = DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName(DSpaceObjectUtilsImpl.class.getName(), DSpaceObjectUtilsImpl.class); + HandleService handleService = HandleServiceFactory.getInstance().getHandleService(); protected Context context; private CurationClientOptions curationClientOptions; @@ -345,9 +350,29 @@ private void initTaskLineOptionsAndCheckIfValid() { if (this.commandLine.hasOption('i')) { this.id = this.commandLine.getOptionValue('i').toLowerCase(); + DSpaceObject dso; if (!this.id.equalsIgnoreCase("all")) { - HandleService handleService = HandleServiceFactory.getInstance().getHandleService(); - DSpaceObject dso; + // First, try to parse the id as a UUID. If that fails, treat it as a handle. + UUID uuid = null; + try { + uuid = UUID.fromString(id); + } catch (Exception e) { + // It's not a UUID, proceed to treat it as a handle. + } + if (uuid != null) { + try { + dso = dspaceObjectUtils.findDSpaceObject(context, uuid); + if (dso != null) { + // We already resolved an object, return early + return; + } + } catch (SQLException e) { + String error = "SQLException trying to find dso with uuid " + uuid; + super.handler.logError(error); + throw new RuntimeException(error, e); + } + } + // If we get here, the id is not a UUID, so we assume it's a handle. try { dso = handleService.resolveToObject(this.context, id); } catch (SQLException e) { From ce11bc9dbdad286b0ef2c690765b63ab1c60b836 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Apr 2025 14:51:19 -0500 Subject: [PATCH 518/632] Potential fix for code scanning alert no. 30: Resolving XML external entity in user-controlled data Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> (cherry picked from commit a0ce50b2a497dcb1711f48ad35cda14eeabf686f) --- .../pubmed/service/PubmedImportMetadataSourceServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java index a6cfa625bbcf..13201b8fcde3 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java @@ -234,6 +234,8 @@ private String getSingleElementValue(String src, String elementName) { try { SAXBuilder saxBuilder = new SAXBuilder(); + saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false); Document document = saxBuilder.build(new StringReader(src)); Element root = document.getRootElement(); From d09b12280588279cf28dc13d3da7557de06c39d0 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Apr 2025 16:57:31 -0500 Subject: [PATCH 519/632] Cannot disable DTDs with PubMed, so instead disallow external entities & entity expansion (cherry picked from commit f9614c41a6ceaa54756f780164fec40a3b185483) --- .../pubmed/service/PubmedImportMetadataSourceServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java index 13201b8fcde3..000ef19eaec5 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java @@ -234,8 +234,10 @@ private String getSingleElementValue(String src, String elementName) { try { SAXBuilder saxBuilder = new SAXBuilder(); - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + // Disallow external entities & entity expansion to protect against XXE attacks + // (NOTE: We receive errors if we disable all DTDs for PubMed, so this is the best we can do) saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false); + saxBuilder.setFeature("http://xml.org/sax/features/external-parameter-entities", false); Document document = saxBuilder.build(new StringReader(src)); Element root = document.getRootElement(); From 822a27d830cdeddd99ae8be74e4e8d0620023fd0 Mon Sep 17 00:00:00 2001 From: Agustina Martinez Date: Tue, 15 Apr 2025 08:59:45 +0100 Subject: [PATCH 520/632] Update ItemUtils.java Do not include start-date info if embargo is expired (cherry picked from commit c167e5c10a92954bcb6e479a8a6cfab345cacaaf) --- dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java index 20dcabcb20c8..498d2f54210a 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java @@ -39,6 +39,7 @@ import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.Utils; +import org.dspace.eperson.Group; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.xoai.data.DSpaceItem; @@ -194,7 +195,8 @@ private static void addResourcePolicyInformation(Context context, Bitstream bits resourcePolicyEl.getField().add(createValue("group", groupName)); resourcePolicyEl.getField().add(createValue("user", user)); resourcePolicyEl.getField().add(createValue("action", action)); - if (startDate != null) { + // Only add start-date if group is different to anonymous, or there is an active embargo + if (startDate != null && (!groupName.equals(Group.ANONYMOUS) || startDate.isAfter(LocalDate.now()))) { resourcePolicyEl.getField().add(createValue("start-date", formatter.format(startDate))); } if (endDate != null) { From edf43a41c1612373c65cf64a9f6d0bf897a818ce Mon Sep 17 00:00:00 2001 From: Agustina Martinez Date: Wed, 30 Apr 2025 09:55:21 +0100 Subject: [PATCH 521/632] Remove unnecessary check of group (cherry picked from commit 6831aa11c17bb1a1a4c1382296b8471a5acdd6b8) --- dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java index 498d2f54210a..6eda37e62fbe 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java @@ -39,7 +39,6 @@ import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.Utils; -import org.dspace.eperson.Group; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.xoai.data.DSpaceItem; @@ -196,7 +195,7 @@ private static void addResourcePolicyInformation(Context context, Bitstream bits resourcePolicyEl.getField().add(createValue("user", user)); resourcePolicyEl.getField().add(createValue("action", action)); // Only add start-date if group is different to anonymous, or there is an active embargo - if (startDate != null && (!groupName.equals(Group.ANONYMOUS) || startDate.isAfter(LocalDate.now()))) { + if (startDate != null && startDate.isAfter(LocalDate.now())) { resourcePolicyEl.getField().add(createValue("start-date", formatter.format(startDate))); } if (endDate != null) { From b74c4b958ffc730a757989e3765a6c52c7000735 Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Tue, 29 Apr 2025 11:57:38 +0200 Subject: [PATCH 522/632] [DURACOM-357] fix Collection Admin cannot see withdrawn item metadata (cherry picked from commit 5e2bb4fb9270a22a28a39ebcbcbac3f2781f097d) --- .../app/rest/converter/ItemConverter.java | 6 +- .../dspace/app/rest/ItemRestRepositoryIT.java | 62 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java index fc64b66e8a16..38f829be3476 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java @@ -8,7 +8,6 @@ package org.dspace.app.rest.converter; import java.sql.SQLException; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -76,8 +75,9 @@ public MetadataValueList getPermissionFilteredMetadata(Context context, Item obj List returnList = new LinkedList<>(); try { if (obj.isWithdrawn() && (Objects.isNull(context) || - Objects.isNull(context.getCurrentUser()) || !authorizeService.isAdmin(context))) { - return new MetadataValueList(new ArrayList()); + Objects.isNull(context.getCurrentUser()) || + !(authorizeService.isAdmin(context) || authorizeService.isCollectionAdmin(context)))) { + return new MetadataValueList(List.of()); } if (context != null && (authorizeService.isAdmin(context) || itemService.canEdit(context, obj))) { return new MetadataValueList(fullList); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java index bde12228e84f..f54fdc38b60e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java @@ -422,6 +422,68 @@ public void findOneTest() throws Exception { .andExpect(jsonPath("$", publicItem1Matcher)); } + @Test + public void findOneWithdrawnAsCollectionAdminTest() throws Exception { + context.turnOffAuthorisationSystem(); + + // Create collection admin account + EPerson collectionAdmin = EPersonBuilder.createEPerson(context) + .withEmail("collection-admin@dspace.com") + .withPassword("test") + .withCanLogin(true) + .build(); + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + + // Create collection + Collection adminCollection = CollectionBuilder.createCollection(context, child1) + .withName("Collection Admin col") + .withAdminGroup(collectionAdmin) + .build(); + Collection noAdminCollection = + CollectionBuilder.createCollection(context, child1).withName("Collection non Admin") + .build(); + + // both items are withdrawn + Item administeredItem = ItemBuilder.createItem(context, adminCollection) + .withTitle("Public item 1") + .withIssueDate("2017-10-17") + .withAuthor("Smith, Donald").withAuthor("Doe, John") + .withSubject("ExtraEntry") + .withdrawn() + .build(); + + Item nonAdministeredItem = ItemBuilder.createItem(context, noAdminCollection) + .withTitle("Public item 2") + .withIssueDate("2016-02-13") + .withAuthor("Smith, Maria").withAuthor("Doe, Jane") + .withSubject("TestingForMore").withSubject("ExtraEntry") + .withdrawn() + .build(); + + context.restoreAuthSystemState(); + + String collectionAdmintoken = getAuthToken(collectionAdmin.getEmail(), "test"); + + // Metadata are retrieved since user is administering the item's collection + getClient(collectionAdmintoken).perform(get("/api/core/items/" + administeredItem.getID()) + .param("projection", "full")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.metadata").isNotEmpty()); + + // No metadata is retrieved since user is not administering the item's collection + getClient().perform(get("/api/core/items/" + nonAdministeredItem.getID()) + .param("projection", "full")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.metadata").isEmpty()); + + + } + @Test public void findOneFullProjectionTest() throws Exception { context.turnOffAuthorisationSystem(); From 371d4708915959263c655fd2a92dbd6a5daa15f1 Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Wed, 30 Apr 2025 08:31:01 +0200 Subject: [PATCH 523/632] [DURACOM-357] improved check for authorization on objects in ItemConverter (cherry picked from commit a70dede20b9310ec85ec6f441be16c0437c796cf) --- .../main/java/org/dspace/app/rest/converter/ItemConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java index 38f829be3476..0c5a36d5fb5a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java @@ -76,7 +76,7 @@ public MetadataValueList getPermissionFilteredMetadata(Context context, Item obj try { if (obj.isWithdrawn() && (Objects.isNull(context) || Objects.isNull(context.getCurrentUser()) || - !(authorizeService.isAdmin(context) || authorizeService.isCollectionAdmin(context)))) { + !(authorizeService.isAdmin(context) || authorizeService.isAdmin(context, obj)))) { return new MetadataValueList(List.of()); } if (context != null && (authorizeService.isAdmin(context) || itemService.canEdit(context, obj))) { From 1b09620a01baa9e20da10c9fbf8cad8104bb8577 Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Wed, 30 Apr 2025 08:56:31 +0200 Subject: [PATCH 524/632] [DURACOM-357] improved admin check (cherry picked from commit bb3935a0473a13fd1804dd6c88cc49a9196809bb) --- .../main/java/org/dspace/app/rest/converter/ItemConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java index 0c5a36d5fb5a..abcd707118c8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java @@ -76,7 +76,7 @@ public MetadataValueList getPermissionFilteredMetadata(Context context, Item obj try { if (obj.isWithdrawn() && (Objects.isNull(context) || Objects.isNull(context.getCurrentUser()) || - !(authorizeService.isAdmin(context) || authorizeService.isAdmin(context, obj)))) { + !authorizeService.isAdmin(context, obj))) { return new MetadataValueList(List.of()); } if (context != null && (authorizeService.isAdmin(context) || itemService.canEdit(context, obj))) { From e5bb4069b45213d3c453db82b1ffbdb5df9d7cd5 Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Wed, 30 Apr 2025 11:33:40 +0200 Subject: [PATCH 525/632] [DURACOM-357] improved javadoc (cherry picked from commit f1cb3c3ad144444f9ee9baf699a359f19680f38c) --- .../main/java/org/dspace/app/rest/converter/ItemConverter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java index abcd707118c8..a1e9442f7466 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java @@ -63,6 +63,9 @@ public ItemRest convert(Item obj, Projection projection) { /** * Retrieves the metadata list filtered according to the hidden metadata configuration * When the context is null, it will return the metadatalist as for an anonymous user + * When the context is not null, it will return the full metadata list if the user + * is allowed to edit the item or if the user is an admin. Otherwise, it will + * return the metadata list filtered according to the hidden metadata configuration * Overrides the parent method to include virtual metadata * @param context The context * @param obj The object of which the filtered metadata will be retrieved From ee225cb0d34e305258fe161db47af1cb288d1e8a Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 30 Apr 2025 15:42:22 +0200 Subject: [PATCH 526/632] Fix #10608 8.x backport by backporting Date references --- dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java index 6eda37e62fbe..40a193ea2905 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java @@ -195,7 +195,7 @@ private static void addResourcePolicyInformation(Context context, Bitstream bits resourcePolicyEl.getField().add(createValue("user", user)); resourcePolicyEl.getField().add(createValue("action", action)); // Only add start-date if group is different to anonymous, or there is an active embargo - if (startDate != null && startDate.isAfter(LocalDate.now())) { + if (startDate != null && startDate.after(new Date())) { resourcePolicyEl.getField().add(createValue("start-date", formatter.format(startDate))); } if (endDate != null) { From 2772b1c9b06d5ac7c3a194dbff7c179fde246522 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 1 May 2025 10:52:39 -0500 Subject: [PATCH 527/632] Replace MethodNotFoundException with more appropriate UnsupportedOperationException --- .../MultipleParallelImportMetadataSourceServiceImpl.java | 3 +-- .../external/ads/ADSImportMetadataSourceServiceImpl.java | 3 +-- .../service/ArXivImportMetadataSourceServiceImpl.java | 3 +-- .../cinii/CiniiImportMetadataSourceServiceImpl.java | 3 +-- .../crossref/CrossRefImportMetadataSourceServiceImpl.java | 3 +-- .../datacite/DataCiteImportMetadataSourceServiceImpl.java | 3 +-- .../service/OpenAireImportMetadataSourceServiceImpl.java | 5 ++--- .../PubmedEuropeMetadataSourceServiceImpl.java | 3 +-- .../ror/service/RorImportMetadataSourceServiceImpl.java | 5 ++--- .../service/ScieloImportMetadataSourceServiceImpl.java | 7 +++---- .../service/ScopusImportMetadataSourceServiceImpl.java | 3 +-- .../vufind/VuFindImportMetadataSourceServiceImpl.java | 3 +-- .../wos/service/WOSImportMetadataSourceServiceImpl.java | 7 +++---- .../dspace/app/rest/ADSImportMetadataSourceServiceIT.java | 3 +-- .../app/rest/CrossRefImportMetadataSourceServiceIT.java | 3 +-- .../app/rest/DataCiteImportMetadataSourceServiceIT.java | 3 +-- .../app/rest/ScieloImportMetadataSourceServiceIT.java | 5 ++--- .../app/rest/VuFindImportMetadataSourceServiceIT.java | 3 +-- 18 files changed, 25 insertions(+), 43 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/MultipleParallelImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/MultipleParallelImportMetadataSourceServiceImpl.java index 1bb7e9269596..1ab5319d4066 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/MultipleParallelImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/MultipleParallelImportMetadataSourceServiceImpl.java @@ -17,7 +17,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; -import jakarta.el.MethodNotFoundException; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -144,7 +143,7 @@ public Collection getRecords(Query query) throws MetadataSourceExc @Override public ImportRecord getRecord(Query query) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for multiple external data sources"); + throw new UnsupportedOperationException("This method is not implemented for multiple external data sources"); } @Override diff --git a/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSImportMetadataSourceServiceImpl.java index 4c72c46732b7..ca3f48da6114 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSImportMetadataSourceServiceImpl.java @@ -21,7 +21,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.el.MethodNotFoundException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.URIBuilder; @@ -99,7 +98,7 @@ public Collection findMatchingRecords(Query query) throws Metadata @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for CrossRef"); + throw new UnsupportedOperationException("This method is not implemented for CrossRef"); } @Override diff --git a/dspace-api/src/main/java/org/dspace/importer/external/arxiv/service/ArXivImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/arxiv/service/ArXivImportMetadataSourceServiceImpl.java index a1df4a7f40c1..660e0c9754bd 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/arxiv/service/ArXivImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/arxiv/service/ArXivImportMetadataSourceServiceImpl.java @@ -15,7 +15,6 @@ import java.util.List; import java.util.concurrent.Callable; -import jakarta.el.MethodNotFoundException; import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.Invocation; @@ -162,7 +161,7 @@ public String getImportSource() { @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { // FIXME: we need this method? - throw new MethodNotFoundException("This method is not implemented for ArXiv"); + throw new UnsupportedOperationException("This method is not implemented for ArXiv"); } /** diff --git a/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java index 66572f9a3d16..82a4b2d77968 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java @@ -20,7 +20,6 @@ import java.util.Objects; import java.util.concurrent.Callable; -import jakarta.el.MethodNotFoundException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpException; @@ -113,7 +112,7 @@ public Collection findMatchingRecords(Query query) throws Metadata @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for Cinii"); + throw new UnsupportedOperationException("This method is not implemented for Cinii"); } public String getUrl() { diff --git a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefImportMetadataSourceServiceImpl.java index 37e613d9c5ff..88aeec8d9498 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefImportMetadataSourceServiceImpl.java @@ -20,7 +20,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.el.MethodNotFoundException; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.URIBuilder; @@ -112,7 +111,7 @@ public Collection findMatchingRecords(Query query) throws Metadata @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for CrossRef"); + throw new UnsupportedOperationException("This method is not implemented for CrossRef"); } public String getID(String id) { diff --git a/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteImportMetadataSourceServiceImpl.java index ad6e260bd0d5..34405cc3eec4 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteImportMetadataSourceServiceImpl.java @@ -17,7 +17,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.el.MethodNotFoundException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -188,7 +187,7 @@ public Collection findMatchingRecords(Query query) throws Metadata @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for DataCite"); + throw new UnsupportedOperationException("This method is not implemented for DataCite"); } public String getID(String query) { diff --git a/dspace-api/src/main/java/org/dspace/importer/external/openaire/service/OpenAireImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/openaire/service/OpenAireImportMetadataSourceServiceImpl.java index 0e7bc5e532e8..7fb5f27354f7 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/openaire/service/OpenAireImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/openaire/service/OpenAireImportMetadataSourceServiceImpl.java @@ -15,7 +15,6 @@ import java.util.List; import java.util.concurrent.Callable; -import jakarta.el.MethodNotFoundException; import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.Invocation; @@ -135,12 +134,12 @@ public Collection getRecords(Query query) throws MetadataSourceExc @Override public Collection findMatchingRecords(Query query) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for OpenAIRE"); + throw new UnsupportedOperationException("This method is not implemented for OpenAIRE"); } @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for OpenAIRE"); + throw new UnsupportedOperationException("This method is not implemented for OpenAIRE"); } /** diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeMetadataSourceServiceImpl.java index 5aae8ca8cf50..7cd297eb2815 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeMetadataSourceServiceImpl.java @@ -18,7 +18,6 @@ import java.util.Objects; import java.util.concurrent.Callable; -import jakarta.el.MethodNotFoundException; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpException; import org.apache.http.client.ClientProtocolException; @@ -153,7 +152,7 @@ public Collection findMatchingRecords(Query query) throws Metadata @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for PubMed Europe"); + throw new UnsupportedOperationException("This method is not implemented for PubMed Europe"); } @Override diff --git a/dspace-api/src/main/java/org/dspace/importer/external/ror/service/RorImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/ror/service/RorImportMetadataSourceServiceImpl.java index aa11ac0bb710..8298b6d6f011 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/ror/service/RorImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/ror/service/RorImportMetadataSourceServiceImpl.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.el.MethodNotFoundException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.URIBuilder; @@ -91,12 +90,12 @@ public ImportRecord getRecord(Query query) throws MetadataSourceException { @Override public Collection findMatchingRecords(Query query) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for ROR"); + throw new UnsupportedOperationException("This method is not implemented for ROR"); } @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for ROR"); + throw new UnsupportedOperationException("This method is not implemented for ROR"); } @Override diff --git a/dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloImportMetadataSourceServiceImpl.java index ce0c20435ecf..cb988a5e55fb 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloImportMetadataSourceServiceImpl.java @@ -21,7 +21,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import jakarta.el.MethodNotFoundException; import jakarta.ws.rs.BadRequestException; import org.apache.commons.collections4.CollectionUtils; import org.apache.http.client.utils.URIBuilder; @@ -99,17 +98,17 @@ public int getRecordsCount(String query) throws MetadataSourceException { @Override public int getRecordsCount(Query query) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for Scielo"); + throw new UnsupportedOperationException("This method is not implemented for Scielo"); } @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for Scielo"); + throw new UnsupportedOperationException("This method is not implemented for Scielo"); } @Override public Collection findMatchingRecords(Query query) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for Scielo"); + throw new UnsupportedOperationException("This method is not implemented for Scielo"); } /** diff --git a/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusImportMetadataSourceServiceImpl.java index 39b2be7ad5f8..a3f74694becf 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusImportMetadataSourceServiceImpl.java @@ -23,7 +23,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import jakarta.el.MethodNotFoundException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -152,7 +151,7 @@ public ImportRecord getRecord(Query query) throws MetadataSourceException { @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for Scopus"); + throw new UnsupportedOperationException("This method is not implemented for Scopus"); } @Override diff --git a/dspace-api/src/main/java/org/dspace/importer/external/vufind/VuFindImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/vufind/VuFindImportMetadataSourceServiceImpl.java index 8933569a060f..7eb3743d207b 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/vufind/VuFindImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/vufind/VuFindImportMetadataSourceServiceImpl.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.el.MethodNotFoundException; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.URIBuilder; import org.apache.logging.log4j.LogManager; @@ -104,7 +103,7 @@ public Collection findMatchingRecords(Query query) throws Metadata @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for VuFind"); + throw new UnsupportedOperationException("This method is not implemented for VuFind"); } @Override diff --git a/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java index c7b5aaa49e27..c33a2f890123 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java @@ -22,7 +22,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import jakarta.el.MethodNotFoundException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; @@ -109,17 +108,17 @@ public int getRecordsCount(String query) throws MetadataSourceException { @Override public int getRecordsCount(Query query) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for WOS"); + throw new UnsupportedOperationException("This method is not implemented for WOS"); } @Override public Collection findMatchingRecords(Item item) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for WOS"); + throw new UnsupportedOperationException("This method is not implemented for WOS"); } @Override public Collection findMatchingRecords(Query query) throws MetadataSourceException { - throw new MethodNotFoundException("This method is not implemented for WOS"); + throw new UnsupportedOperationException("This method is not implemented for WOS"); } /** diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ADSImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ADSImportMetadataSourceServiceIT.java index 892e83c79da0..4150ca580e49 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ADSImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ADSImportMetadataSourceServiceIT.java @@ -18,7 +18,6 @@ import java.util.Collection; import java.util.List; -import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; @@ -117,7 +116,7 @@ public void adsImportMetadataGetRecordsCountByQueryTest() throws Exception { } } - @Test(expected = MethodNotFoundException.class) + @Test(expected = UnsupportedOperationException.class) public void adsImportMetadataFindMatchingRecordsTest() throws Exception { context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java index f68bfe48db1b..27b5e6933ba7 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CrossRefImportMetadataSourceServiceIT.java @@ -18,7 +18,6 @@ import java.util.Collection; import java.util.List; -import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; @@ -135,7 +134,7 @@ public void crossRefImportMetadataGetRecordByIdTest() throws Exception { } } - @Test(expected = MethodNotFoundException.class) + @Test(expected = UnsupportedOperationException.class) public void crossRefImportMetadataFindMatchingRecordsTest() throws Exception { context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DataCiteImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DataCiteImportMetadataSourceServiceIT.java index 35b4810d9292..a8cd59a1afc4 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DataCiteImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DataCiteImportMetadataSourceServiceIT.java @@ -16,7 +16,6 @@ import java.util.Collection; import java.util.List; -import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; @@ -90,7 +89,7 @@ public void dataCiteImportMetadataGetRecordsCountTest() throws Exception { } } - @Test(expected = MethodNotFoundException.class) + @Test(expected = UnsupportedOperationException.class) public void dataCiteImportMetadataFindMatchingRecordsTest() throws Exception { context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScieloImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScieloImportMetadataSourceServiceIT.java index c12eff1f176e..af23ff4d14a4 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScieloImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScieloImportMetadataSourceServiceIT.java @@ -18,7 +18,6 @@ import java.util.Collection; import java.util.List; -import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; @@ -92,7 +91,7 @@ public void scieloImportMetadataGetRecordsCountTest() throws Exception { } } - @Test(expected = MethodNotFoundException.class) + @Test(expected = UnsupportedOperationException.class) public void scieloImportMetadataFindMatchingRecordsTest() throws Exception { context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context) @@ -111,7 +110,7 @@ public void scieloImportMetadataFindMatchingRecordsTest() throws Exception { scieloServiceImpl.findMatchingRecords(testItem); } - @Test(expected = MethodNotFoundException.class) + @Test(expected = UnsupportedOperationException.class) public void scieloImportMetadataGetRecordsCountByQueryTest() throws Exception { Query q = new Query(); q.addParameter("query", "test query"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/VuFindImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/VuFindImportMetadataSourceServiceIT.java index 76512272444d..89b67bbb4aa2 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/VuFindImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/VuFindImportMetadataSourceServiceIT.java @@ -18,7 +18,6 @@ import java.util.Collection; import java.util.List; -import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; @@ -119,7 +118,7 @@ public void vuFindImportMetadataGetRecordByIdTest() throws Exception { } } - @Test(expected = MethodNotFoundException.class) + @Test(expected = UnsupportedOperationException.class) public void vuFindImportMetadataFindMatchingRecordsTest() throws Exception { context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context) From 31220966f7523428b29aa5c31acf7c7b84766da5 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 1 May 2025 10:53:14 -0500 Subject: [PATCH 528/632] Remove jakarta.el dependency --- dspace-api/pom.xml | 4 ---- pom.xml | 5 ----- 2 files changed, 9 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 91c69fe2154c..8851a5e5256a 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -500,10 +500,6 @@ jakarta.annotation jakarta.annotation-api - - jakarta.el - jakarta.el-api - jaxen jaxen diff --git a/pom.xml b/pom.xml index 779fc9648ec6..2dd4c2d2adb4 100644 --- a/pom.xml +++ b/pom.xml @@ -1573,11 +1573,6 @@ jakarta.servlet-api 6.1.0 - - jakarta.el - jakarta.el-api - 5.0.1 - From 59d637e62384c7d1d2bdb6ab6f1c676e36a9236f Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 19 Nov 2024 12:13:37 +0100 Subject: [PATCH 529/632] 119612: configurable limit on exporting items since it can take up a bunch of resources (cherry picked from commit b634e1e38070e65128c49d702affa3b19842ebb6) --- .../app/bulkedit/MetadataExportSearch.java | 2 +- .../MetadataDSpaceCsvExportServiceImpl.java | 43 +++++++++++++++++-- .../MetadataDSpaceCsvExportService.java | 6 ++- .../MetadataDSpaceCsvExportServiceImplIT.java | 8 +++- dspace/config/dspace.cfg | 9 ++++ 5 files changed, 59 insertions(+), 9 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java index 027ad116a7e2..e4bbe335d63e 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java @@ -143,7 +143,7 @@ public void internalRun() throws Exception { Iterator itemIterator = searchService.iteratorSearch(context, dso, discoverQuery); handler.logDebug("creating dspacecsv"); - DSpaceCSV dSpaceCSV = metadataDSpaceCsvExportService.export(context, itemIterator, true); + DSpaceCSV dSpaceCSV = metadataDSpaceCsvExportService.export(context, itemIterator, true, handler); handler.logDebug("writing to file " + getFileNameOrExportFile()); handler.writeFilestream(context, getFileNameOrExportFile(), dSpaceCSV.getInputStream(), EXPORT_CSV); context.restoreAuthSystemState(); diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java index 8bc34d3f5ed1..7e313b79511e 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java @@ -15,14 +15,17 @@ import java.util.Set; import java.util.UUID; +import org.apache.commons.collections.IteratorUtils; import org.dspace.app.bulkedit.DSpaceCSV; import org.dspace.app.util.service.DSpaceObjectUtils; import org.dspace.content.service.ItemService; import org.dspace.content.service.MetadataDSpaceCsvExportService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.eperson.service.GroupService; import org.dspace.handle.factory.HandleServiceFactory; import org.dspace.scripts.handler.DSpaceRunnableHandler; +import org.dspace.services.ConfigurationService; import org.springframework.beans.factory.annotation.Autowired; /** @@ -36,6 +39,12 @@ public class MetadataDSpaceCsvExportServiceImpl implements MetadataDSpaceCsvExpo @Autowired private DSpaceObjectUtils dSpaceObjectUtils; + @Autowired + private ConfigurationService configurationService; + + @Autowired + private GroupService groupService; + @Override public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean exportAllMetadata, String identifier, DSpaceRunnableHandler handler) throws Exception { @@ -74,17 +83,19 @@ public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean e } } - DSpaceCSV csv = this.export(context, toExport, exportAllMetadata); + DSpaceCSV csv = this.export(context, toExport, exportAllMetadata, handler); return csv; } @Override - public DSpaceCSV export(Context context, Iterator toExport, boolean exportAll) throws Exception { + public DSpaceCSV export(Context context, Iterator toExport, + boolean exportAll, DSpaceRunnableHandler handler) throws Exception { Context.Mode originalMode = context.getCurrentMode(); context.setMode(Context.Mode.READ_ONLY); // Process each item DSpaceCSV csv = new DSpaceCSV(exportAll); + toExport = setItemsToExportWithLimit(context, toExport, handler); while (toExport.hasNext()) { Item item = toExport.next(); csv.addItem(item); @@ -97,8 +108,32 @@ public DSpaceCSV export(Context context, Iterator toExport, boolean export } @Override - public DSpaceCSV export(Context context, Community community, boolean exportAll) throws Exception { - return export(context, buildFromCommunity(context, community), exportAll); + public DSpaceCSV export(Context context, Community community, + boolean exportAll, DSpaceRunnableHandler handler) throws Exception { + return export(context, buildFromCommunity(context, community), exportAll, handler); + } + + private Iterator setItemsToExportWithLimit(Context context, Iterator toExport, + DSpaceRunnableHandler handler) throws SQLException { + int itemExportLimit = configurationService.getIntProperty( + "metadataexport.max.items", 500); + String[] ignoreLimitGroups = configurationService.getArrayProperty( + "metadataexport.admin.groups"); + + for (String group : ignoreLimitGroups) { + if (groupService.isMember(context, context.getCurrentUser(), group)) { + itemExportLimit = Integer.MAX_VALUE; + break; + } + } + + List items = IteratorUtils.toList(toExport); + if (items.size() > itemExportLimit) { + handler.logWarning("The amount of items to export is higher than the limit of " + itemExportLimit + + " items. Only the first " + itemExportLimit + " items will be exported."); + items = items.subList(0, itemExportLimit); + } + return items.iterator(); } /** diff --git a/dspace-api/src/main/java/org/dspace/content/service/MetadataDSpaceCsvExportService.java b/dspace-api/src/main/java/org/dspace/content/service/MetadataDSpaceCsvExportService.java index d3fc2e823669..052754a16331 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/MetadataDSpaceCsvExportService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/MetadataDSpaceCsvExportService.java @@ -44,7 +44,8 @@ public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean e * @return A DSpaceCSV object containing the exported information * @throws Exception If something goes wrong */ - public DSpaceCSV export(Context context, Iterator toExport, boolean exportAll) throws Exception; + public DSpaceCSV export(Context context, Iterator toExport, + boolean exportAll, DSpaceRunnableHandler handler) throws Exception; /** * This method will export all the Items within the given Community to a DSpaceCSV @@ -54,6 +55,7 @@ public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean e * @return A DSpaceCSV object containing the exported information * @throws Exception If something goes wrong */ - public DSpaceCSV export(Context context, Community community, boolean exportAll) throws Exception; + public DSpaceCSV export(Context context, Community community, + boolean exportAll, DSpaceRunnableHandler handler) throws Exception; } \ No newline at end of file diff --git a/dspace-api/src/test/java/org/dspace/content/MetadataDSpaceCsvExportServiceImplIT.java b/dspace-api/src/test/java/org/dspace/content/MetadataDSpaceCsvExportServiceImplIT.java index c2d4f56ca61a..5a3412646482 100644 --- a/dspace-api/src/test/java/org/dspace/content/MetadataDSpaceCsvExportServiceImplIT.java +++ b/dspace-api/src/test/java/org/dspace/content/MetadataDSpaceCsvExportServiceImplIT.java @@ -16,6 +16,7 @@ import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.app.bulkedit.DSpaceCSV; import org.dspace.app.bulkedit.DSpaceCSVLine; +import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; @@ -31,6 +32,9 @@ */ public class MetadataDSpaceCsvExportServiceImplIT extends AbstractIntegrationTestWithDatabase { + + TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); + /** * Test of handleExport method, of class MetadataDSpaceCsvExportServiceImpl. * @throws java.lang.Exception passed through. @@ -66,7 +70,7 @@ public void testExport_3args_1() boolean exportAll = false; MetadataDSpaceCsvExportServiceImpl instance = new MetadataDSpaceCsvExportServiceImpl(); DSpaceCSV expResult = null; - DSpaceCSV result = instance.export(context, toExport, exportAll); + DSpaceCSV result = instance.export(context, toExport, exportAll, testDSpaceRunnableHandler); assertEquals(expResult, result); // TODO review the generated test code and remove the default call to fail. fail("The test case is a prototype."); @@ -105,7 +109,7 @@ public void testMappedItem() .getServiceManager() .getServiceByName(MetadataDSpaceCsvExportServiceImpl.class.getCanonicalName(), MetadataDSpaceCsvExportService.class); - DSpaceCSV result = instance.export(context, parentCommunity, false); + DSpaceCSV result = instance.export(context, parentCommunity, false, testDSpaceRunnableHandler); // Examine the result. List csvLines = result.getCSVLines(); diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 2abe436387dd..76a0c84c757f 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -901,6 +901,15 @@ org.dspace.app.itemexport.life.span.hours = 48 # cumulative sizes are more than this entry the export is not kicked off org.dspace.app.itemexport.max.size = 200 +### Bulkedit Metadata export settings +# The maximum amount of items that can be exported using the "metadata-export" script / process +# Recommend to keep this at a feasible number, as exporting large amounts of items can be resource intensive +metadataexport.max.items = 1 + +# A list of groups that are allowed to use the metadata-export script without any restrictions +#metadataexport.admin.groups = Administrator + + ### Batch Item import settings ### # The directory where the results of imports will be placed (mapfile, upload file) org.dspace.app.batchitemimport.work.dir = ${dspace.dir}/imports From e9deba8c55da9c442e42ceaaa10fd4354071ea42 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 20 Nov 2024 17:09:38 +0100 Subject: [PATCH 530/632] 119612: property should be commented by default and have a normal limit (cherry picked from commit a8b98bb7b78c9220e159c587a55def1bff3cb023) --- dspace/config/dspace.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 76a0c84c757f..d07868af33a6 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -902,9 +902,10 @@ org.dspace.app.itemexport.life.span.hours = 48 org.dspace.app.itemexport.max.size = 200 ### Bulkedit Metadata export settings -# The maximum amount of items that can be exported using the "metadata-export" script / process +# The maximum amount of items that can be exported using the "metadata-export" / "metadata-export-search" script # Recommend to keep this at a feasible number, as exporting large amounts of items can be resource intensive -metadataexport.max.items = 1 +# If not set, this will default to 500 items +# metadataexport.max.items = 500 # A list of groups that are allowed to use the metadata-export script without any restrictions #metadataexport.admin.groups = Administrator From 1e93108103a6ec26513a0d24eaf184ef6a1f5e0d Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 20 Jan 2025 15:46:26 +0100 Subject: [PATCH 531/632] 119612: Remove group configuration and expose property to angular (cherry picked from commit c73c739deb007c657641f198414da886c2953807) --- .../content/MetadataDSpaceCsvExportServiceImpl.java | 13 ------------- dspace/config/dspace.cfg | 3 --- dspace/config/modules/rest.cfg | 1 + 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java index 7e313b79511e..3dd396589344 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java @@ -22,7 +22,6 @@ import org.dspace.content.service.MetadataDSpaceCsvExportService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.eperson.service.GroupService; import org.dspace.handle.factory.HandleServiceFactory; import org.dspace.scripts.handler.DSpaceRunnableHandler; import org.dspace.services.ConfigurationService; @@ -42,9 +41,6 @@ public class MetadataDSpaceCsvExportServiceImpl implements MetadataDSpaceCsvExpo @Autowired private ConfigurationService configurationService; - @Autowired - private GroupService groupService; - @Override public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean exportAllMetadata, String identifier, DSpaceRunnableHandler handler) throws Exception { @@ -117,15 +113,6 @@ private Iterator setItemsToExportWithLimit(Context context, Iterator DSpaceRunnableHandler handler) throws SQLException { int itemExportLimit = configurationService.getIntProperty( "metadataexport.max.items", 500); - String[] ignoreLimitGroups = configurationService.getArrayProperty( - "metadataexport.admin.groups"); - - for (String group : ignoreLimitGroups) { - if (groupService.isMember(context, context.getCurrentUser(), group)) { - itemExportLimit = Integer.MAX_VALUE; - break; - } - } List items = IteratorUtils.toList(toExport); if (items.size() > itemExportLimit) { diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index d07868af33a6..e546f1386304 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -907,9 +907,6 @@ org.dspace.app.itemexport.max.size = 200 # If not set, this will default to 500 items # metadataexport.max.items = 500 -# A list of groups that are allowed to use the metadata-export script without any restrictions -#metadataexport.admin.groups = Administrator - ### Batch Item import settings ### # The directory where the results of imports will be placed (mapfile, upload file) diff --git a/dspace/config/modules/rest.cfg b/dspace/config/modules/rest.cfg index 3bb620510e59..6dd1ab89fbe0 100644 --- a/dspace/config/modules/rest.cfg +++ b/dspace/config/modules/rest.cfg @@ -59,3 +59,4 @@ rest.properties.exposed = ldn.notify.inbox rest.properties.exposed = handle.canonical.prefix rest.properties.exposed = contentreport.enable rest.properties.exposed = duplicate.enable +rest.properties.exposed = metadataexport.max.items From 8ad376b368d065f7fb8cbf8c041836d0dbba3762 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 3 Feb 2025 10:09:47 +0100 Subject: [PATCH 532/632] 124504: Move configuration to be included in the bulkedit module and apply the configured limit earlier, never obtaining a larger list than actually required (cherry picked from commit b63ffd2eb4a869d17d2caca2d726d7702b05d564) --- .../app/bulkedit/MetadataExportSearch.java | 2 + .../MetadataDSpaceCsvExportServiceImpl.java | 42 +++++++++---------- .../MetadataDSpaceCsvExportService.java | 4 +- dspace/config/dspace.cfg | 7 ---- dspace/config/modules/bulkedit.cfg | 5 +++ dspace/config/modules/rest.cfg | 2 +- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java index e4bbe335d63e..04c3a75dedd6 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java @@ -139,6 +139,8 @@ public void internalRun() throws Exception { DiscoverQuery discoverQuery = queryBuilder.buildQuery(context, dso, discoveryConfiguration, query, queryBuilderSearchFilters, "Item", 10, Long.getLong("0"), null, SortOption.DESCENDING); + // add configured limit + discoverQuery.setMaxResults(metadataDSpaceCsvExportService.getCsvExportLimit()); handler.logDebug("creating iterator"); Iterator itemIterator = searchService.iteratorSearch(context, dso, discoverQuery); diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java index 3dd396589344..33e87a43fcd4 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java @@ -15,7 +15,6 @@ import java.util.Set; import java.util.UUID; -import org.apache.commons.collections.IteratorUtils; import org.dspace.app.bulkedit.DSpaceCSV; import org.dspace.app.util.service.DSpaceObjectUtils; import org.dspace.content.service.ItemService; @@ -41,6 +40,8 @@ public class MetadataDSpaceCsvExportServiceImpl implements MetadataDSpaceCsvExpo @Autowired private ConfigurationService configurationService; + private int csxExportLimit = -1; + @Override public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean exportAllMetadata, String identifier, DSpaceRunnableHandler handler) throws Exception { @@ -48,7 +49,7 @@ public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean e if (exportAllItems) { handler.logInfo("Exporting whole repository WARNING: May take some time!"); - toExport = itemService.findAll(context); + toExport = itemService.findAll(context, getCsvExportLimit(), 0); } else { DSpaceObject dso = HandleServiceFactory.getInstance().getHandleService() .resolveToObject(context, identifier); @@ -68,7 +69,7 @@ public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean e } else if (dso.getType() == Constants.COLLECTION) { handler.logInfo("Exporting collection '" + dso.getName() + "' (" + identifier + ")"); Collection collection = (Collection) dso; - toExport = itemService.findByCollection(context, collection); + toExport = itemService.findByCollection(context, collection, getCsvExportLimit(), 0); } else if (dso.getType() == Constants.COMMUNITY) { handler.logInfo("Exporting community '" + dso.getName() + "' (" + identifier + ")"); toExport = buildFromCommunity(context, (Community) dso); @@ -91,7 +92,6 @@ public DSpaceCSV export(Context context, Iterator toExport, // Process each item DSpaceCSV csv = new DSpaceCSV(exportAll); - toExport = setItemsToExportWithLimit(context, toExport, handler); while (toExport.hasNext()) { Item item = toExport.next(); csv.addItem(item); @@ -109,20 +109,6 @@ public DSpaceCSV export(Context context, Community community, return export(context, buildFromCommunity(context, community), exportAll, handler); } - private Iterator setItemsToExportWithLimit(Context context, Iterator toExport, - DSpaceRunnableHandler handler) throws SQLException { - int itemExportLimit = configurationService.getIntProperty( - "metadataexport.max.items", 500); - - List items = IteratorUtils.toList(toExport); - if (items.size() > itemExportLimit) { - handler.logWarning("The amount of items to export is higher than the limit of " + itemExportLimit - + " items. Only the first " + itemExportLimit + " items will be exported."); - items = items.subList(0, itemExportLimit); - } - return items.iterator(); - } - /** * Build a Java Collection of item IDs that are in a Community (including * its sub-Communities and Collections) @@ -135,25 +121,37 @@ private Iterator setItemsToExportWithLimit(Context context, Iterator private Iterator buildFromCommunity(Context context, Community community) throws SQLException { Set result = new HashSet<>(); + int itemsAdded = 0; // Add all the collections List collections = community.getCollections(); for (Collection collection : collections) { - Iterator items = itemService.findByCollection(context, collection); - while (items.hasNext()) { + // Never obtain more items than the configured limit + Iterator items = itemService.findByCollection(context, collection, getCsvExportLimit(), 0); + while (itemsAdded <= getCsvExportLimit() && items.hasNext()) { result.add(items.next()); + itemsAdded++; } } - // Add all the sub-communities + // Add all the sub-communities List communities = community.getSubcommunities(); for (Community subCommunity : communities) { Iterator items = buildFromCommunity(context, subCommunity); - while (items.hasNext()) { + while (itemsAdded <= getCsvExportLimit() && items.hasNext()) { result.add(items.next()); + itemsAdded++; } } return result.iterator(); } + + @Override + public int getCsvExportLimit() { + if (csxExportLimit == -1) { + csxExportLimit = configurationService.getIntProperty("bulkedit.export.max.items", 500); + } + return csxExportLimit; + } } diff --git a/dspace-api/src/main/java/org/dspace/content/service/MetadataDSpaceCsvExportService.java b/dspace-api/src/main/java/org/dspace/content/service/MetadataDSpaceCsvExportService.java index 052754a16331..a951e8cf7763 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/MetadataDSpaceCsvExportService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/MetadataDSpaceCsvExportService.java @@ -58,4 +58,6 @@ public DSpaceCSV export(Context context, Iterator toExport, public DSpaceCSV export(Context context, Community community, boolean exportAll, DSpaceRunnableHandler handler) throws Exception; -} \ No newline at end of file + int getCsvExportLimit(); + +} diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index e546f1386304..2abe436387dd 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -901,13 +901,6 @@ org.dspace.app.itemexport.life.span.hours = 48 # cumulative sizes are more than this entry the export is not kicked off org.dspace.app.itemexport.max.size = 200 -### Bulkedit Metadata export settings -# The maximum amount of items that can be exported using the "metadata-export" / "metadata-export-search" script -# Recommend to keep this at a feasible number, as exporting large amounts of items can be resource intensive -# If not set, this will default to 500 items -# metadataexport.max.items = 500 - - ### Batch Item import settings ### # The directory where the results of imports will be placed (mapfile, upload file) org.dspace.app.batchitemimport.work.dir = ${dspace.dir}/imports diff --git a/dspace/config/modules/bulkedit.cfg b/dspace/config/modules/bulkedit.cfg index 6174af53a0f3..e326e007f884 100644 --- a/dspace/config/modules/bulkedit.cfg +++ b/dspace/config/modules/bulkedit.cfg @@ -40,3 +40,8 @@ bulkedit.allow-bulk-deletion = dspace.agreements.end-user # By default this is set to 100 bulkedit.change.commit.count = 100 +### Bulkedit Metadata export settings +# The maximum amount of items that can be exported using the "metadata-export" / "metadata-export-search" script +# Recommend to keep this at a feasible number, as exporting large amounts of items can be resource intensive +# If not set, this will default to 500 items +# bulkedit.export.max.items = 500 diff --git a/dspace/config/modules/rest.cfg b/dspace/config/modules/rest.cfg index 6dd1ab89fbe0..4c179d5d8900 100644 --- a/dspace/config/modules/rest.cfg +++ b/dspace/config/modules/rest.cfg @@ -59,4 +59,4 @@ rest.properties.exposed = ldn.notify.inbox rest.properties.exposed = handle.canonical.prefix rest.properties.exposed = contentreport.enable rest.properties.exposed = duplicate.enable -rest.properties.exposed = metadataexport.max.items +rest.properties.exposed = bulkedit.export.max.items From 54e40db4006518172c66f28873213f851087c58f Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 2 Apr 2025 11:09:45 +0200 Subject: [PATCH 533/632] 119612: Fix limit not applying on export (cherry picked from commit bcf48821d94d30cee10c3c2c94b33c52b0bccdb0) --- .../dspace/app/bulkedit/MetadataExportSearch.java | 2 -- .../content/MetadataDSpaceCsvExportServiceImpl.java | 13 ++++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java index 04c3a75dedd6..e4bbe335d63e 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java @@ -139,8 +139,6 @@ public void internalRun() throws Exception { DiscoverQuery discoverQuery = queryBuilder.buildQuery(context, dso, discoveryConfiguration, query, queryBuilderSearchFilters, "Item", 10, Long.getLong("0"), null, SortOption.DESCENDING); - // add configured limit - discoverQuery.setMaxResults(metadataDSpaceCsvExportService.getCsvExportLimit()); handler.logDebug("creating iterator"); Iterator itemIterator = searchService.iteratorSearch(context, dso, discoverQuery); diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java index 33e87a43fcd4..757c5d0cd529 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataDSpaceCsvExportServiceImpl.java @@ -90,9 +90,11 @@ public DSpaceCSV export(Context context, Iterator toExport, Context.Mode originalMode = context.getCurrentMode(); context.setMode(Context.Mode.READ_ONLY); - // Process each item + // Process each item until we reach the limit + int itemExportLimit = getCsvExportLimit(); DSpaceCSV csv = new DSpaceCSV(exportAll); - while (toExport.hasNext()) { + + for (int itemsAdded = 0; toExport.hasNext() && itemsAdded < itemExportLimit; itemsAdded++) { Item item = toExport.next(); csv.addItem(item); context.uncacheEntity(item); @@ -121,16 +123,14 @@ public DSpaceCSV export(Context context, Community community, private Iterator buildFromCommunity(Context context, Community community) throws SQLException { Set result = new HashSet<>(); - int itemsAdded = 0; // Add all the collections List collections = community.getCollections(); for (Collection collection : collections) { // Never obtain more items than the configured limit Iterator items = itemService.findByCollection(context, collection, getCsvExportLimit(), 0); - while (itemsAdded <= getCsvExportLimit() && items.hasNext()) { + while (result.size() < getCsvExportLimit() && items.hasNext()) { result.add(items.next()); - itemsAdded++; } } @@ -138,9 +138,8 @@ private Iterator buildFromCommunity(Context context, Community community) List communities = community.getSubcommunities(); for (Community subCommunity : communities) { Iterator items = buildFromCommunity(context, subCommunity); - while (itemsAdded <= getCsvExportLimit() && items.hasNext()) { + while (result.size() < getCsvExportLimit() && items.hasNext()) { result.add(items.next()); - itemsAdded++; } } From 5bcd3ce8c60a11d625c9c0328767a5d581dfcc28 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Fri, 2 May 2025 11:13:29 +0200 Subject: [PATCH 534/632] pull primary bitstream out of innerloop (cherry picked from commit 81e2314ec65977a91ec1dea66313209051d7f715) --- .../java/org/dspace/app/rest/submit/step/UploadStep.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java index e0a9cb17e01c..877e64756df5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java @@ -55,13 +55,13 @@ public DataUpload getData(SubmissionService submissionService, InProgressSubmiss DataUpload result = new DataUpload(); List bundles = itemService.getBundles(obj.getItem(), Constants.CONTENT_BUNDLE_NAME); for (Bundle bundle : bundles) { + Bitstream primaryBitstream = bundle.getPrimaryBitstream(); + if (Objects.nonNull(primaryBitstream)) { + result.setPrimary(primaryBitstream.getID()); + } for (Bitstream source : bundle.getBitstreams()) { - Bitstream primaryBitstream = bundle.getPrimaryBitstream(); UploadBitstreamRest b = submissionService.buildUploadBitstream(configurationService, source); result.getFiles().add(b); - if (Objects.nonNull(primaryBitstream)) { - result.setPrimary(primaryBitstream.getID()); - } } } return result; From c6e5bbed624405a805e0f355626a2d5de0382268 Mon Sep 17 00:00:00 2001 From: Adamo Date: Fri, 2 May 2025 12:42:47 +0200 Subject: [PATCH 535/632] [DURACOM-355] Update to avoid NPE during WOS live import when no api key is found (cherry picked from commit 70f1c83bf0a7b32c10eaf22c5cc990c6b10e5784) --- .../WOSImportMetadataSourceServiceImpl.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java index c33a2f890123..9bffa2a84a19 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java @@ -56,7 +56,7 @@ public class WOSImportMetadataSourceServiceImpl extends AbstractImportMetadataSo private static final String AI_PATTERN = "^AI=(.*)"; private static final Pattern ISI_PATTERN = Pattern.compile("^\\d{15}$"); - private int timeout = 1000; + private final int timeout = 1000; private String url; private String urlSearch; @@ -126,7 +126,7 @@ public Collection findMatchingRecords(Query query) throws Metadata */ private class SearchNBByQueryCallable implements Callable { - private String query; + private final String query; private SearchNBByQueryCallable(String queryString) { this.query = queryString; @@ -155,7 +155,8 @@ public Integer call() throws Exception { Element tot = xpath.evaluateFirst(root); return Integer.valueOf(tot.getValue()); } - return null; + log.warn("API key is missing: cannot execute count request."); + return 0; } } @@ -166,7 +167,7 @@ public Integer call() throws Exception { */ private class FindByIdCallable implements Callable> { - private String doi; + private final String doi; private FindByIdCallable(String doi) { this.doi = URLEncoder.encode(doi, StandardCharsets.UTF_8); @@ -185,6 +186,8 @@ public List call() throws Exception { for (Element record : elements) { results.add(transformSourceRecords(record)); } + } else { + log.warn("API key is missing: cannot execute live import request."); } return results; } @@ -202,7 +205,7 @@ public List call() throws Exception { */ private class SearchByQueryCallable implements Callable> { - private Query query; + private final Query query; private SearchByQueryCallable(String queryString, Integer maxResult, Integer start) { query = new Query(); @@ -232,6 +235,8 @@ public List call() throws Exception { for (Element el : omElements) { results.add(transformSourceRecords(el)); } + } else { + log.warn("API key is missing: cannot execute live import request."); } return results; } @@ -270,9 +275,7 @@ private String checkQuery(String query) { } else if (isIsi(query)) { return "UT=(" + query + ")"; } - StringBuilder queryBuilder = new StringBuilder("TS=("); - queryBuilder.append(query).append(")"); - return queryBuilder.toString(); + return "TS=(" + query + ")"; } private boolean isIsi(String query) { From be55a2ae7a3f6acd453ab827521b3eb55610d985 Mon Sep 17 00:00:00 2001 From: Adamo Date: Fri, 2 May 2025 18:08:15 +0200 Subject: [PATCH 536/632] [DURACOM-311] Ensure stable pagination in bulk access control by adding explicit sort (cherry picked from commit ced9e9b9f731162c43d5823a9d2fd05e74ab233a) --- .../bulkaccesscontrol/BulkAccessControl.java | 2 +- .../BulkAccessControlIT.java | 84 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 7bef232f0450..30f68efaf3cb 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -416,7 +416,7 @@ private DiscoverQuery buildDiscoveryQuery(String query, int start, int limit) { discoverQuery.setQuery(query); discoverQuery.setStart(start); discoverQuery.setMaxResults(limit); - + discoverQuery.setSortField("search.resourceid", DiscoverQuery.SORT_ORDER.asc); return discoverQuery; } diff --git a/dspace-api/src/test/java/org/dspace/app/bulkaccesscontrol/BulkAccessControlIT.java b/dspace-api/src/test/java/org/dspace/app/bulkaccesscontrol/BulkAccessControlIT.java index 73f02e40494c..106b176ee5b4 100644 --- a/dspace-api/src/test/java/org/dspace/app/bulkaccesscontrol/BulkAccessControlIT.java +++ b/dspace-api/src/test/java/org/dspace/app/bulkaccesscontrol/BulkAccessControlIT.java @@ -32,8 +32,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -1831,6 +1833,88 @@ public void performBulkAccessWithHelpParamTest() throws Exception { assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty()); } + + @Test + public void bulkAccessControlShouldProcessEachItemOnceWithPagination() throws Exception { + context.turnOffAuthorisationSystem(); + + Community community = CommunityBuilder.createCommunity(context) + .withName("Test Community") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("Test Collection") + .build(); + + List createdItemIDs = new ArrayList<>(); + + for (int i = 0; i < 25; i++) { + Item item = ItemBuilder.createItem(context, collection).build(); + + Bundle bundle = BundleBuilder.createBundle(context, item) + .withName("ORIGINAL") + .build(); + + BitstreamBuilder.createBitstream(context, bundle, + IOUtils.toInputStream("Bitstream content " + i, + CharEncoding.UTF_8)) + .withName("bitstream_" + i) + .build(); + + createdItemIDs.add(item.getID()); + } + + context.restoreAuthSystemState(); + + // JSON without constraints: apply to ALL items + String json = """ + { "item": { + "mode": "add", + "accessConditions": [ + { + "name": "openaccess" + } + ] + }} + """; + + buildJsonFile(json); + + String[] args = { + "bulk-access-control", + "-u", community.getID().toString(), + "-f", tempFilePath, + "-e", admin.getEmail() + }; + + TestDSpaceRunnableHandler testHandler = new TestDSpaceRunnableHandler(); + ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testHandler, kernelImpl); + + assertThat(testHandler.getErrorMessages(), empty()); + assertThat(testHandler.getWarningMessages(), empty()); + + // Collect item IDs from the info messages + List infoMessages = testHandler.getInfoMessages(); + List updatedItemIDs = infoMessages.stream() + .map(msg -> { + int startIdx = msg.indexOf("Item {") + 6; + int endIdx = msg.indexOf("}", startIdx); + return UUID.fromString(msg.substring(startIdx, endIdx)); + }) + .toList(); + + Set uniqueUpdatedItemIDs = new HashSet<>(updatedItemIDs); + + // Check if any item was processed multiple times + assertThat("Some items were processed more than once!", + uniqueUpdatedItemIDs.size(), is(updatedItemIDs.size())); + + // Check all items were updated once + assertThat("Not all created items were updated!", + createdItemIDs, containsInAnyOrder(uniqueUpdatedItemIDs.toArray())); + } + + private List findItems(String query) throws SearchServiceException { DiscoverQuery discoverQuery = new DiscoverQuery(); From ab0a4531ca157a1b52aedc04c765e250e0d17d63 Mon Sep 17 00:00:00 2001 From: Adamo Date: Thu, 1 May 2025 18:52:26 +0200 Subject: [PATCH 537/632] [DURACOM-356] Updated Sherpa mapping to use creativeworkseries.issn instead of dc.identifier.issn (cherry picked from commit 480bad24440b615d2d10686e37bdbd4c5df97776) --- .../provider/impl/SHERPAv2JournalISSNDataProvider.java | 3 +-- dspace/config/spring/api/sherpa.xml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/SHERPAv2JournalISSNDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/SHERPAv2JournalISSNDataProvider.java index 9e61b9ac2ac0..860334847ccb 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/SHERPAv2JournalISSNDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/SHERPAv2JournalISSNDataProvider.java @@ -106,8 +106,7 @@ private ExternalDataObject constructExternalDataObjectFromSherpaJournal(SHERPAJo String issn = sherpaJournal.getIssns().get(0); externalDataObject.setId(issn); externalDataObject.addMetadata(new MetadataValueDTO( - "dc", "identifier", "issn", null, issn)); - + "creativeworkseries", "issn", null, null, issn)); } log.debug("New external data object. Title=" + externalDataObject.getValue() + ". ID=" diff --git a/dspace/config/spring/api/sherpa.xml b/dspace/config/spring/api/sherpa.xml index 0414f3f8e4b4..da42880218ca 100644 --- a/dspace/config/spring/api/sherpa.xml +++ b/dspace/config/spring/api/sherpa.xml @@ -17,7 +17,7 @@ - dc.identifier.issn + creativeworkseries.issn From 29fc51c02aed49920ef87eeb62df3b0a5a37272d Mon Sep 17 00:00:00 2001 From: Adamo Date: Fri, 2 May 2025 19:23:37 +0200 Subject: [PATCH 538/632] [DURACOM-356] Fixed tests (cherry picked from commit fc8a434234e96c74386a958bd1a816d07c9921ad) --- .../org/dspace/app/sherpa/SHERPADataProviderTest.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/app/sherpa/SHERPADataProviderTest.java b/dspace-api/src/test/java/org/dspace/app/sherpa/SHERPADataProviderTest.java index cbea55ea0787..b19b35895bb9 100644 --- a/dspace-api/src/test/java/org/dspace/app/sherpa/SHERPADataProviderTest.java +++ b/dspace-api/src/test/java/org/dspace/app/sherpa/SHERPADataProviderTest.java @@ -87,9 +87,8 @@ public void testGetJournalISSNExternalObject() { if (metadataValue.getSchema().equalsIgnoreCase("dc") && metadataValue.getElement().equalsIgnoreCase("title")) { title = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("dc") - && metadataValue.getElement().equalsIgnoreCase("identifier") - && metadataValue.getQualifier().equalsIgnoreCase("issn")) { + } else if (metadataValue.getSchema().equalsIgnoreCase("creativeworkseries") + && metadataValue.getElement().equalsIgnoreCase("issn")) { identifier = metadataValue.getValue(); } } @@ -136,9 +135,8 @@ public void testSearchJournalISSNExternalObjects() { if (metadataValue.getSchema().equalsIgnoreCase("dc") && metadataValue.getElement().equalsIgnoreCase("title")) { title = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("dc") - && metadataValue.getElement().equalsIgnoreCase("identifier") - && metadataValue.getQualifier().equalsIgnoreCase("issn")) { + } else if (metadataValue.getSchema().equalsIgnoreCase("creativeworkseries") + && metadataValue.getElement().equalsIgnoreCase("issn")) { identifier = metadataValue.getValue(); } } From 20e3f2e03039f365cfb5cb85a0ffc4cdfb13a229 Mon Sep 17 00:00:00 2001 From: Adamo Date: Mon, 5 May 2025 12:46:52 +0200 Subject: [PATCH 539/632] [DURACOM-356] Updated Sherpa Journal mapping to use creativeworkseries.issn instead of dc.identifier.issn (cherry picked from commit 979476b3f35c5c60aa13a8fd4233b7286666b94e) --- .../external/provider/impl/SHERPAv2JournalDataProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/SHERPAv2JournalDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/SHERPAv2JournalDataProvider.java index a4276c83ed70..f0ce6a979a1f 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/SHERPAv2JournalDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/SHERPAv2JournalDataProvider.java @@ -97,7 +97,7 @@ private ExternalDataObject constructExternalDataObjectFromSherpaJournal(SHERPAJo if (CollectionUtils.isNotEmpty(sherpaJournal.getIssns())) { String issn = sherpaJournal.getIssns().get(0); externalDataObject.addMetadata(new MetadataValueDTO( - "dc", "identifier", "issn", null, issn)); + "creativeworkseries", "issn", null, null, issn)); } From 27d3d75ca5f8b9fdb12531215e02d2496acffb18 Mon Sep 17 00:00:00 2001 From: Adamo Date: Mon, 5 May 2025 12:49:16 +0200 Subject: [PATCH 540/632] [DURACOM-356] Updated tests to use metadata constants (cherry picked from commit 94c5f5d6f7d085be572e3e62837b1f8eac5191d8) --- .../app/sherpa/SHERPADataProviderTest.java | 105 +++++++++--------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/app/sherpa/SHERPADataProviderTest.java b/dspace-api/src/test/java/org/dspace/app/sherpa/SHERPADataProviderTest.java index b19b35895bb9..f37d9469d12d 100644 --- a/dspace-api/src/test/java/org/dspace/app/sherpa/SHERPADataProviderTest.java +++ b/dspace-api/src/test/java/org/dspace/app/sherpa/SHERPADataProviderTest.java @@ -38,6 +38,12 @@ public class SHERPADataProviderTest extends AbstractDSpaceTest { ExternalDataProvider sherpaPublisherProvider; ExternalDataProvider sherpaJournalIssnProvider; + private static final MetadataFieldRef TITLE_FIELD = new MetadataFieldRef("dc", "title", null); + private static final MetadataFieldRef ISSN_FIELD = new MetadataFieldRef("creativeworkseries", "issn", null); + private static final MetadataFieldRef SHERPA_PUBLISHER_FIELD = + new MetadataFieldRef("dc", "identifier", "sherpaPublisher"); + private static final MetadataFieldRef OTHER_FIELD = new MetadataFieldRef("dc", "identifier", "other"); + @BeforeClass public static void setUpClass() { } @@ -84,11 +90,9 @@ public void testGetJournalISSNExternalObject() { String title = null; String identifier = null; for (MetadataValueDTO metadataValue : dataObject.getMetadata()) { - if (metadataValue.getSchema().equalsIgnoreCase("dc") && - metadataValue.getElement().equalsIgnoreCase("title")) { + if (TITLE_FIELD.matches(metadataValue)) { title = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("creativeworkseries") - && metadataValue.getElement().equalsIgnoreCase("issn")) { + } else if (ISSN_FIELD.matches(metadataValue)) { identifier = metadataValue.getValue(); } } @@ -132,11 +136,9 @@ public void testSearchJournalISSNExternalObjects() { String title = null; String identifier = null; for (MetadataValueDTO metadataValue : dataObject.getMetadata()) { - if (metadataValue.getSchema().equalsIgnoreCase("dc") && - metadataValue.getElement().equalsIgnoreCase("title")) { + if (TITLE_FIELD.matches(metadataValue)) { title = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("creativeworkseries") - && metadataValue.getElement().equalsIgnoreCase("issn")) { + } else if (ISSN_FIELD.matches(metadataValue)) { identifier = metadataValue.getValue(); } } @@ -172,12 +174,9 @@ public void testGetJournalExternalObject() { String title = null; String identifier = null; for (MetadataValueDTO metadataValue : dataObject.getMetadata()) { - if (metadataValue.getSchema().equalsIgnoreCase("dc") && - metadataValue.getElement().equalsIgnoreCase("title")) { + if (TITLE_FIELD.matches(metadataValue)) { title = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("dc") - && metadataValue.getElement().equalsIgnoreCase("identifier") - && metadataValue.getQualifier().equalsIgnoreCase("issn")) { + } else if (ISSN_FIELD.matches(metadataValue)) { identifier = metadataValue.getValue(); } } @@ -222,12 +221,9 @@ public void testSearchJournalObjects() { String title = null; String identifier = null; for (MetadataValueDTO metadataValue : dataObject.getMetadata()) { - if (metadataValue.getSchema().equalsIgnoreCase("dc") && - metadataValue.getElement().equalsIgnoreCase("title")) { + if (TITLE_FIELD.matches(metadataValue)) { title = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("dc") - && metadataValue.getElement().equalsIgnoreCase("identifier") - && metadataValue.getQualifier().equalsIgnoreCase("issn")) { + } else if (ISSN_FIELD.matches(metadataValue)) { identifier = metadataValue.getValue(); } } @@ -268,16 +264,11 @@ public void testGetPublisherExternalObject() { String identifier = null; String url = null; for (MetadataValueDTO metadataValue : dataObject.getMetadata()) { - if (metadataValue.getSchema().equalsIgnoreCase("dc") && - metadataValue.getElement().equalsIgnoreCase("title")) { + if (TITLE_FIELD.matches(metadataValue)) { title = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("dc") - && metadataValue.getElement().equalsIgnoreCase("identifier") - && metadataValue.getQualifier().equalsIgnoreCase("sherpaPublisher")) { + } else if (SHERPA_PUBLISHER_FIELD.matches(metadataValue)) { identifier = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("dc") - && metadataValue.getElement().equalsIgnoreCase("identifier") - && metadataValue.getQualifier().equalsIgnoreCase("other")) { + } else if (OTHER_FIELD.matches(metadataValue)) { url = metadataValue.getValue(); } } @@ -328,16 +319,11 @@ public void testSearchPublisherExternalObjects() { String identifier = null; String url = null; for (MetadataValueDTO metadataValue : dataObject.getMetadata()) { - if (metadataValue.getSchema().equalsIgnoreCase("dc") && - metadataValue.getElement().equalsIgnoreCase("title")) { + if (TITLE_FIELD.matches(metadataValue)) { title = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("dc") - && metadataValue.getElement().equalsIgnoreCase("identifier") - && metadataValue.getQualifier().equalsIgnoreCase("sherpaPublisher")) { + } else if (SHERPA_PUBLISHER_FIELD.matches(metadataValue)) { identifier = metadataValue.getValue(); - } else if (metadataValue.getSchema().equalsIgnoreCase("dc") - && metadataValue.getElement().equalsIgnoreCase("identifier") - && metadataValue.getQualifier().equalsIgnoreCase("other")) { + } else if (OTHER_FIELD.matches(metadataValue)) { url = metadataValue.getValue(); } } @@ -378,12 +364,9 @@ public void testComparePublisherExternalObjects() { exemplarDataObject.setId(validIdentifier); exemplarDataObject.setValue(validName); exemplarDataObject.setDisplayValue(validName); - exemplarDataObject.addMetadata(new MetadataValueDTO("dc", "title", null, null, - validName)); - exemplarDataObject.addMetadata(new MetadataValueDTO("dc", "identifier", "sherpaPublisher", null, - validIdentifier)); - exemplarDataObject.addMetadata(new MetadataValueDTO("dc", "identifier", "other", null, - validUrl)); + exemplarDataObject.addMetadata(TITLE_FIELD.toMetadata(validName)); + exemplarDataObject.addMetadata(SHERPA_PUBLISHER_FIELD.toMetadata(validIdentifier)); + exemplarDataObject.addMetadata(OTHER_FIELD.toMetadata(validUrl)); // Exemplar object 2 has a different order of metadata values // (we still expect it to be 'equal' when comparing since there is no concept of place for DTOs) @@ -392,12 +375,9 @@ public void testComparePublisherExternalObjects() { exemplarDataObject2.setId(validIdentifier); exemplarDataObject2.setValue(validName); exemplarDataObject2.setDisplayValue(validName); - exemplarDataObject2.addMetadata(new MetadataValueDTO("dc", "identifier", "other", null, - validUrl)); - exemplarDataObject2.addMetadata(new MetadataValueDTO("dc", "title", null, null, - validName)); - exemplarDataObject2.addMetadata(new MetadataValueDTO("dc", "identifier", "sherpaPublisher", null, - validIdentifier)); + exemplarDataObject2.addMetadata(OTHER_FIELD.toMetadata(validUrl)); + exemplarDataObject2.addMetadata(TITLE_FIELD.toMetadata(validName)); + exemplarDataObject2.addMetadata(SHERPA_PUBLISHER_FIELD.toMetadata(validIdentifier)); // Nonequal object should NOT evaluate as equal to our data ExternalDataObject nonEqualObject = new ExternalDataObject(); @@ -405,12 +385,9 @@ public void testComparePublisherExternalObjects() { nonEqualObject.setId(validIdentifier); nonEqualObject.setValue(validName); nonEqualObject.setDisplayValue(validName); - nonEqualObject.addMetadata(new MetadataValueDTO("dc", "title", null, null, - "Private Library of Science")); - nonEqualObject.addMetadata(new MetadataValueDTO("dc", "identifier", "sherpaPublisher", null, - validIdentifier)); - nonEqualObject.addMetadata(new MetadataValueDTO("dc", "identifier", "other", null, - validUrl)); + nonEqualObject.addMetadata(TITLE_FIELD.toMetadata("Private Library of Science")); + nonEqualObject.addMetadata(SHERPA_PUBLISHER_FIELD.toMetadata(validIdentifier)); + nonEqualObject.addMetadata(OTHER_FIELD.toMetadata(validUrl)); // Retrieve the dataobject(s) from the data provider @@ -435,4 +412,28 @@ public void testComparePublisherExternalObjects() { // Assert NON-equality to the 3rd object assertNotEquals(nonEqualObject, dataObject); } + + private static class MetadataFieldRef { + public final String schema; + public final String element; + public final String qualifier; + + public MetadataFieldRef(String schema, String element, String qualifier) { + this.schema = schema; + this.element = element; + this.qualifier = qualifier; + } + + public boolean matches(MetadataValueDTO value) { + return schema.equalsIgnoreCase(value.getSchema()) && + element.equalsIgnoreCase(value.getElement()) && + (qualifier == null ? value.getQualifier() == null + : qualifier.equalsIgnoreCase(value.getQualifier())); + } + + public MetadataValueDTO toMetadata(String value) { + return new MetadataValueDTO(schema, element, qualifier, null, value); + } + } + } \ No newline at end of file From 9990000e4fdf54cf6418f47d2fb7aeff81177ddd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 23:26:55 +0000 Subject: [PATCH 541/632] Bump com.opencsv:opencsv from 5.10 to 5.11 Bumps com.opencsv:opencsv from 5.10 to 5.11. --- updated-dependencies: - dependency-name: com.opencsv:opencsv dependency-version: '5.11' dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 8851a5e5256a..ab795aa3a9c1 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -772,7 +772,7 @@ com.opencsv opencsv - 5.10 + 5.11 From 2bb2d0be2ccc80cb6abf95b1f76e3893b2e7b0a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 23:44:09 +0000 Subject: [PATCH 542/632] Bump org.checkerframework:checker-qual from 3.49.2 to 3.49.3 Bumps [org.checkerframework:checker-qual](https://github.com/typetools/checker-framework) from 3.49.2 to 3.49.3. - [Release notes](https://github.com/typetools/checker-framework/releases) - [Changelog](https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/typetools/checker-framework/compare/checker-framework-3.49.2...checker-framework-3.49.3) --- updated-dependencies: - dependency-name: org.checkerframework:checker-qual dependency-version: 3.49.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2dd4c2d2adb4..20610aaaaeef 100644 --- a/pom.xml +++ b/pom.xml @@ -1350,7 +1350,7 @@ org.checkerframework checker-qual - 3.49.2 + 3.49.3 1.80 8.0.1 From e09f03e6bb2861339f293aab466feeb838fa76bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 23:45:25 +0000 Subject: [PATCH 544/632] Bump com.amazonaws:aws-java-sdk-s3 from 1.12.782 to 1.12.783 Bumps [com.amazonaws:aws-java-sdk-s3](https://github.com/aws/aws-sdk-java) from 1.12.782 to 1.12.783. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.782...1.12.783) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-s3 dependency-version: 1.12.783 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 8851a5e5256a..2722b9744c26 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -731,7 +731,7 @@ com.amazonaws aws-java-sdk-s3 - 1.12.782 + 1.12.783 From e5a36f2e0f61756275b3e930ca2c733b957a6b81 Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Thu, 17 Apr 2025 17:55:05 +0200 Subject: [PATCH 547/632] [DURACOM-109] Continued configuring proxy for other classes --- .../app/client/DSpaceHttpClientFactory.java | 2 +- .../packager/AbstractMETSIngester.java | 12 ++++--- .../ctask/general/BasicLinkChecker.java | 18 ++++++---- .../client/GoogleAnalyticsClientImpl.java | 4 +-- .../dspace/iiif/IIIFApiQueryServiceImpl.java | 15 ++++---- .../service/LiveImportClientImpl.java | 35 ++++--------------- .../CCLicenseConnectorServiceImpl.java | 18 ++-------- .../impl/QAEventActionServiceImpl.java | 4 +-- .../statistics/SolrLoggerServiceImpl.java | 4 +-- dspace/config/dspace.cfg | 2 ++ 10 files changed, 43 insertions(+), 71 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/client/DSpaceHttpClientFactory.java b/dspace-api/src/main/java/org/dspace/app/client/DSpaceHttpClientFactory.java index 999f13c1b387..59c8172f722c 100644 --- a/dspace-api/src/main/java/org/dspace/app/client/DSpaceHttpClientFactory.java +++ b/dspace-api/src/main/java/org/dspace/app/client/DSpaceHttpClientFactory.java @@ -93,7 +93,7 @@ public CloseableHttpClient buildWithoutProxy() { public CloseableHttpClient buildWithoutAutomaticRetries(int maxConnTotal) { HttpClientBuilder clientBuilder = HttpClientBuilder.create() .disableAutomaticRetries() - .setMaxConnTotal(5); + .setMaxConnTotal(maxConnTotal); return build(clientBuilder, true); } diff --git a/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java b/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java index 0ed0abe21825..c43d8e797b07 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java @@ -11,8 +11,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; import java.sql.SQLException; import java.util.Iterator; import java.util.List; @@ -21,7 +19,11 @@ import java.util.zip.ZipFile; import org.apache.commons.collections4.CollectionUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.Logger; +import org.dspace.app.client.DSpaceHttpClientFactory; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.BitstreamFormat; @@ -1312,11 +1314,11 @@ protected static InputStream getFileInputStream(File pkgFile, // we will assume all external files are available via URLs. try { // attempt to open a connection to given URL - URL fileURL = new URL(path); - URLConnection connection = fileURL.openConnection(); + CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); + CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(path)); // open stream to access file contents - return connection.getInputStream(); + return httpResponse.getEntity().getContent(); } catch (IOException io) { log .error("Unable to retrieve external file from URL '" diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java index a302159ea9a4..fd6d69c98f04 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java @@ -9,11 +9,15 @@ import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URL; import java.util.ArrayList; import java.util.List; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.Logger; +import org.dspace.app.client.DSpaceHttpClientFactory; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataValue; @@ -136,15 +140,15 @@ protected boolean checkURL(String url, StringBuilder results) { */ protected int getResponseStatus(String url, int redirects) { try { - URL theURL = new URL(url); - HttpURLConnection connection = (HttpURLConnection) theURL.openConnection(); - connection.setInstanceFollowRedirects(true); - int statusCode = connection.getResponseCode(); + RequestConfig config = RequestConfig.custom().setRedirectsEnabled(true).build(); + CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().buildWithRequestConfig(config); + CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(url)); + int statusCode = httpResponse.getStatusLine().getStatusCode(); int maxRedirect = configurationService.getIntProperty("curate.checklinks.max-redirect", 0); if ((statusCode == HttpURLConnection.HTTP_MOVED_TEMP || statusCode == HttpURLConnection.HTTP_MOVED_PERM || statusCode == HttpURLConnection.HTTP_SEE_OTHER)) { - connection.disconnect(); - String newUrl = connection.getHeaderField("Location"); + httpClient.close(); + String newUrl = httpResponse.getFirstHeader("Location").getValue(); if (newUrl != null && (maxRedirect >= redirects || maxRedirect == -1)) { redirects++; return getResponseStatus(newUrl, redirects); diff --git a/dspace-api/src/main/java/org/dspace/google/client/GoogleAnalyticsClientImpl.java b/dspace-api/src/main/java/org/dspace/google/client/GoogleAnalyticsClientImpl.java index 915bd25b065f..bfecb1fb0861 100644 --- a/dspace-api/src/main/java/org/dspace/google/client/GoogleAnalyticsClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/google/client/GoogleAnalyticsClientImpl.java @@ -18,9 +18,9 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.client.DSpaceHttpClientFactory; import org.dspace.google.GoogleAnalyticsEvent; /** @@ -42,7 +42,7 @@ public class GoogleAnalyticsClientImpl implements GoogleAnalyticsClient { public GoogleAnalyticsClientImpl(String keyPrefix, GoogleAnalyticsClientRequestBuilder requestBuilder) { this.keyPrefix = keyPrefix; this.requestBuilder = requestBuilder; - this.httpclient = HttpClients.createDefault(); + this.httpclient = DSpaceHttpClientFactory.getInstance().build(); } @Override diff --git a/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java b/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java index 7c6336ed3c7f..87bd7770648e 100644 --- a/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java @@ -12,12 +12,14 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.Logger; +import org.dspace.app.client.DSpaceHttpClientFactory; import org.dspace.content.Bitstream; import org.dspace.iiif.util.IIIFSharedUtils; @@ -35,14 +37,11 @@ public class IIIFApiQueryServiceImpl implements IIIFApiQueryService { public int[] getImageDimensions(Bitstream bitstream) { int[] arr = new int[2]; String path = IIIFSharedUtils.getInfoJsonPath(bitstream); - URL url; BufferedReader in = null; try { - url = new URL(path); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("GET"); - in = new BufferedReader( - new InputStreamReader(con.getInputStream())); + CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); + CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(path)); + in = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent())); String inputLine; StringBuilder response = new StringBuilder(); while ((inputLine = in.readLine()) != null) { diff --git a/dspace-api/src/main/java/org/dspace/importer/external/liveimportclient/service/LiveImportClientImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/liveimportclient/service/LiveImportClientImpl.java index 1a8a7a7861ed..2cb8236842a3 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/liveimportclient/service/LiveImportClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/liveimportclient/service/LiveImportClientImpl.java @@ -17,19 +17,16 @@ import org.apache.commons.collections.MapUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.config.RequestConfig.Builder; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.client.DSpaceHttpClientFactory; import org.dspace.services.ConfigurationService; import org.springframework.beans.factory.annotation.Autowired; @@ -53,16 +50,12 @@ public class LiveImportClientImpl implements LiveImportClient { @Override public String executeHttpGetRequest(int timeout, String URL, Map> params) { HttpGet method = null; + RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(timeout).build(); try (CloseableHttpClient httpClient = Optional.ofNullable(this.httpClient) - .orElseGet(HttpClients::createDefault)) { - - Builder requestConfigBuilder = RequestConfig.custom(); - requestConfigBuilder.setConnectionRequestTimeout(timeout); - RequestConfig defaultRequestConfig = requestConfigBuilder.build(); - + .orElse(DSpaceHttpClientFactory.getInstance().buildWithRequestConfig(config))) { String uri = buildUrl(URL, params.get(URI_PARAMETERS)); method = new HttpGet(uri); - method.setConfig(defaultRequestConfig); + method.setConfig(config); Map headerParams = params.get(HEADER_PARAMETERS); if (MapUtils.isNotEmpty(headerParams)) { @@ -71,7 +64,6 @@ public String executeHttpGetRequest(int timeout, String URL, Map> params, String entry) { HttpPost method = null; + RequestConfig config = RequestConfig.custom().build(); try (CloseableHttpClient httpClient = Optional.ofNullable(this.httpClient) - .orElseGet(HttpClients::createDefault)) { - - Builder requestConfigBuilder = RequestConfig.custom(); - RequestConfig defaultRequestConfig = requestConfigBuilder.build(); + .orElse(DSpaceHttpClientFactory.getInstance().buildWithRequestConfig(config))) { String uri = buildUrl(URL, params.get(URI_PARAMETERS)); method = new HttpPost(uri); - method.setConfig(defaultRequestConfig); if (StringUtils.isNotBlank(entry)) { method.setEntity(new StringEntity(entry)); } setHeaderParams(method, params); - configureProxy(method, defaultRequestConfig); if (log.isDebugEnabled()) { log.debug("Performing POST request to \"" + uri + "\"..." ); } @@ -129,17 +117,6 @@ public String executeHttpPostRequest(String URL, Map return StringUtils.EMPTY; } - private void configureProxy(HttpRequestBase method, RequestConfig defaultRequestConfig) { - String proxyHost = configurationService.getProperty("http.proxy.host"); - String proxyPort = configurationService.getProperty("http.proxy.port"); - if (StringUtils.isNotBlank(proxyHost) && StringUtils.isNotBlank(proxyPort)) { - RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig) - .setProxy(new HttpHost(proxyHost, Integer.parseInt(proxyPort), "http")) - .build(); - method.setConfig(requestConfig); - } - } - /** * Allows to set the header parameters to the HTTP Post method * diff --git a/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java b/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java index 524ff04facec..e9fe49e9b4f6 100644 --- a/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java @@ -10,9 +10,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; import java.text.MessageFormat; import java.util.Collections; import java.util.HashMap; @@ -328,23 +325,14 @@ private String createAnswerString(final Map parameterMap) { @Override public Document retrieveLicenseRDFDoc(String licenseURI) throws IOException { String ccLicenseUrl = configurationService.getProperty("cc.api.rooturl"); - String issueUrl = ccLicenseUrl + "/details?license-uri=" + licenseURI; - - URL request_url; - try { - request_url = new URL(issueUrl); - } catch (MalformedURLException e) { - return null; - } - URLConnection connection = request_url.openConnection(); - connection.setDoOutput(true); try { + CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); + CloseableHttpResponse httpResponse = httpClient.execute(new HttpPost(issueUrl)); // parsing document from input stream - InputStream stream = connection.getInputStream(); + InputStream stream = httpResponse.getEntity().getContent(); Document doc = parser.build(stream); return doc; - } catch (Exception e) { log.error("Error while retrieving the license document for URI: " + licenseURI, e); } diff --git a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java index 30875a5105b0..38e7295582eb 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java @@ -22,9 +22,9 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.client.DSpaceHttpClientFactory; import org.dspace.content.Item; import org.dspace.content.QAEvent; import org.dspace.content.service.ItemService; @@ -123,7 +123,7 @@ private void makeAcknowledgement(String eventId, String source, String status) { node.put("eventId", eventId); node.put("status", status); StringEntity requestEntity = new StringEntity(node.toString(), ContentType.APPLICATION_JSON); - CloseableHttpClient httpclient = HttpClients.createDefault(); + CloseableHttpClient httpclient = DSpaceHttpClientFactory.getInstance().buildWithoutProxy(); HttpPost postMethod = new HttpPost(ackwnoledgeCallback); postMethod.setEntity(requestEntity); try { diff --git a/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java b/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java index fb327ed6db15..9e5ba3256c0b 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java @@ -1223,7 +1223,7 @@ public void shardSolrIndex() throws IOException, SolrServerException { + "." + i + ".csv"); - try (CloseableHttpClient hc = DSpaceHttpClientFactory.getInstance().build()) { + try (CloseableHttpClient hc = DSpaceHttpClientFactory.getInstance().buildWithoutProxy()) { HttpResponse response = hc.execute(get); csvInputstream = response.getEntity().getContent(); //Write the csv ouput to a file ! @@ -1365,7 +1365,7 @@ public void reindexBitstreamHits(boolean removeDeletedBitstreams) throws Excepti HttpGet get = new HttpGet(solrRequestUrl); List rows; - try (CloseableHttpClient hc = DSpaceHttpClientFactory.getInstance().build()) { + try (CloseableHttpClient hc = DSpaceHttpClientFactory.getInstance().buildWithoutProxy()) { HttpResponse response = hc.execute(get); InputStream csvOutput = response.getEntity().getContent(); Reader csvReader = new InputStreamReader(csvOutput); diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 2abe436387dd..7151fc6dc56b 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -411,6 +411,8 @@ http.proxy.host = # port number of proxy server http.proxy.port = +http.proxy.hosts-to-ignore = 127.0.0.1, localhost + # If enabled, the logging and the Solr statistics system will look for an X-Forwarded-For header. # If it finds it, it will use this for the user IP address. # NOTE: This is required to be enabled if you plan to use the Angular UI, as the server-side rendering provided in From 0f77db9785033570d5ade41f4fbf8834538dc185 Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Fri, 18 Apr 2025 10:24:35 +0200 Subject: [PATCH 548/632] [DURACOM-109] Minor fix --- .../external/liveimportclient/service/LiveImportClientImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/liveimportclient/service/LiveImportClientImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/liveimportclient/service/LiveImportClientImpl.java index 2cb8236842a3..84475b62c07b 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/liveimportclient/service/LiveImportClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/liveimportclient/service/LiveImportClientImpl.java @@ -55,7 +55,6 @@ public String executeHttpGetRequest(int timeout, String URL, Map headerParams = params.get(HEADER_PARAMETERS); if (MapUtils.isNotEmpty(headerParams)) { From f78c327e5835cc70960bbfb019a4cda972b6d7c5 Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Fri, 18 Apr 2025 15:00:38 +0200 Subject: [PATCH 549/632] [DURACOM-109] Fixed http connection leaks --- .../org/dspace/app/sherpa/SHERPAService.java | 21 +--- .../dspace/app/util/WebAppServiceImpl.java | 4 +- .../oidc/impl/OidcClientImpl.java | 29 +++-- .../packager/AbstractMETSIngester.java | 3 +- .../ctask/general/BasicLinkChecker.java | 5 +- .../dspace/external/OrcidRestConnector.java | 10 +- .../dspace/iiif/IIIFApiQueryServiceImpl.java | 3 +- .../CCLicenseConnectorServiceImpl.java | 3 +- .../dspace/orcid/client/OrcidClientImpl.java | 103 ++++++++---------- 9 files changed, 73 insertions(+), 108 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java index 4f0e99921a95..6f26d0cc2d27 100644 --- a/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java @@ -17,9 +17,9 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URIBuilder; import org.apache.http.impl.client.CloseableHttpClient; @@ -45,8 +45,6 @@ */ public class SHERPAService { - private CloseableHttpClient client = null; - private int maxNumberOfTries; private long sleepBetweenTimeouts; private int timeout = 5000; @@ -59,15 +57,6 @@ public class SHERPAService { @Autowired ConfigurationService configurationService; - /** - * Create a new HTTP builder with sensible defaults in constructor - */ - public SHERPAService() { - // httpclient 4.3+ doesn't appear to have any sensible defaults any more. Setting conservative defaults as - // not to hammer the SHERPA service too much. - client = DSpaceHttpClientFactory.getInstance().buildWithoutAutomaticRetries(5); - } - /** * Complete initialization of the Bean. */ @@ -128,14 +117,14 @@ public SHERPAPublisherResponse performPublisherRequest(String type, String field timeout, sleepBetweenTimeouts)); - try { + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { Thread.sleep(sleepBetweenTimeouts); // Construct a default HTTP method (first result) method = constructHttpGet(type, field, predicate, value, start, limit); // Execute the method - HttpResponse response = client.execute(method); + CloseableHttpResponse response = client.execute(method); int statusCode = response.getStatusLine().getStatusCode(); log.debug(response.getStatusLine().getStatusCode() + ": " @@ -231,14 +220,14 @@ public SHERPAResponse performRequest(String type, String field, String predicate timeout, sleepBetweenTimeouts)); - try { + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { Thread.sleep(sleepBetweenTimeouts); // Construct a default HTTP method (first result) method = constructHttpGet(type, field, predicate, value, start, limit); // Execute the method - HttpResponse response = client.execute(method); + CloseableHttpResponse response = client.execute(method); int statusCode = response.getStatusLine().getStatusCode(); log.debug(response.getStatusLine().getStatusCode() + ": " diff --git a/dspace-api/src/main/java/org/dspace/app/util/WebAppServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/util/WebAppServiceImpl.java index 064a9fdc3e9b..fa23903ba431 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/WebAppServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/util/WebAppServiceImpl.java @@ -13,8 +13,8 @@ import java.util.Date; import java.util.List; -import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpHead; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.Logger; @@ -78,7 +78,7 @@ public List getApps() { method = new HttpHead(app.getUrl()); int status; try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { - HttpResponse response = client.execute(method); + CloseableHttpResponse response = client.execute(method); status = response.getStatusLine().getStatusCode(); } if (status != HttpStatus.SC_OK) { diff --git a/dspace-api/src/main/java/org/dspace/authenticate/oidc/impl/OidcClientImpl.java b/dspace-api/src/main/java/org/dspace/authenticate/oidc/impl/OidcClientImpl.java index f28244268ff1..3e3d4b905b94 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/oidc/impl/OidcClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/oidc/impl/OidcClientImpl.java @@ -22,10 +22,11 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.message.BasicNameValuePair; import org.dspace.app.client.DSpaceHttpClientFactory; import org.dspace.authenticate.oidc.OidcClient; @@ -83,21 +84,17 @@ public Map getUserInfo(String accessToken) throws OidcClientExce } private T executeAndParseJson(HttpUriRequest httpUriRequest, Class clazz) { - - HttpClient client = DSpaceHttpClientFactory.getInstance().build(); - - return executeAndReturns(() -> { - - HttpResponse response = client.execute(httpUriRequest); - - if (isNotSuccessfull(response)) { - throw new OidcClientException(getStatusCode(response), formatErrorMessage(response)); - } - - return objectMapper.readValue(getContent(response), clazz); - - }); - + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { + return executeAndReturns(() -> { + CloseableHttpResponse response = client.execute(httpUriRequest); + if (isNotSuccessfull(response)) { + throw new OidcClientException(getStatusCode(response), formatErrorMessage(response)); + } + return objectMapper.readValue(getContent(response), clazz); + }); + } catch (IOException e) { + throw new RuntimeException(e); + } } private T executeAndReturns(ThrowingSupplier supplier) { diff --git a/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java b/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java index c43d8e797b07..835b9f0e9b6f 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java @@ -1312,9 +1312,8 @@ protected static InputStream getFileInputStream(File pkgFile, if (params.getBooleanProperty("manifestOnly", false)) { // NOTE: since we are only dealing with a METS manifest, // we will assume all external files are available via URLs. - try { + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { // attempt to open a connection to given URL - CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(path)); // open stream to access file contents diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java index fd6d69c98f04..189f77733886 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java @@ -139,9 +139,8 @@ protected boolean checkURL(String url, StringBuilder results) { * @return The HTTP response code (e.g. 200 / 301 / 404 / 500) */ protected int getResponseStatus(String url, int redirects) { - try { - RequestConfig config = RequestConfig.custom().setRedirectsEnabled(true).build(); - CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().buildWithRequestConfig(config); + RequestConfig config = RequestConfig.custom().setRedirectsEnabled(true).build(); + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().buildWithRequestConfig(config)) { CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(url)); int statusCode = httpResponse.getStatusLine().getStatusCode(); int maxRedirect = configurationService.getIntProperty("curate.checklinks.max-redirect", 0); diff --git a/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java b/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java index 3ccbd257e285..f2c6246f4d06 100644 --- a/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java +++ b/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java @@ -12,9 +12,9 @@ import java.util.Scanner; import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.client.DSpaceHttpClientFactory; @@ -39,7 +39,7 @@ public OrcidRestConnector(String url) { } public InputStream get(String path, String accessToken) { - HttpResponse getResponse = null; + CloseableHttpResponse getResponse = null; InputStream result = null; path = trimSlashes(path); @@ -49,10 +49,8 @@ public InputStream get(String path, String accessToken) { httpGet.addHeader("Content-Type", "application/vnd.orcid+xml"); httpGet.addHeader("Authorization","Bearer " + accessToken); } - try { - HttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { getResponse = httpClient.execute(httpGet); - //do not close this httpClient result = getResponse.getEntity().getContent(); } catch (Exception e) { getGotError(e, fullPath); diff --git a/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java b/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java index 87bd7770648e..ccb2c170d949 100644 --- a/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java @@ -38,8 +38,7 @@ public int[] getImageDimensions(Bitstream bitstream) { int[] arr = new int[2]; String path = IIIFSharedUtils.getInfoJsonPath(bitstream); BufferedReader in = null; - try { - CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(path)); in = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent())); String inputLine; diff --git a/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java b/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java index e9fe49e9b4f6..1d777a2e13c8 100644 --- a/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java @@ -326,8 +326,7 @@ private String createAnswerString(final Map parameterMap) { public Document retrieveLicenseRDFDoc(String licenseURI) throws IOException { String ccLicenseUrl = configurationService.getProperty("cc.api.rooturl"); String issueUrl = ccLicenseUrl + "/details?license-uri=" + licenseURI; - try { - CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { CloseableHttpResponse httpResponse = httpClient.execute(new HttpPost(issueUrl)); // parsing document from input stream InputStream stream = httpResponse.getEntity().getContent(); diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java index 62e4c1d61c1b..da1de465251d 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java @@ -35,11 +35,12 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.message.BasicNameValuePair; import org.dspace.app.client.DSpaceHttpClientFactory; import org.dspace.orcid.OrcidToken; @@ -76,12 +77,9 @@ public class OrcidClientImpl implements OrcidClient { private final ObjectMapper objectMapper; - private final DSpaceHttpClientFactory httpClientFactory; - - public OrcidClientImpl(OrcidConfiguration orcidConfiguration, DSpaceHttpClientFactory httpClientFactory) { + public OrcidClientImpl(OrcidConfiguration orcidConfiguration) { this.orcidConfiguration = orcidConfiguration; this.objectMapper = new ObjectMapper(); - this.httpClientFactory = httpClientFactory; } private static Map, String> initializePathsMap() { @@ -257,10 +255,8 @@ private HttpUriRequest buildDeleteUriRequest(String accessToken, String relative } private void executeSuccessful(HttpUriRequest httpUriRequest) { - try { - HttpClient client = httpClientFactory.build(); - HttpResponse response = client.execute(httpUriRequest); - + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { + CloseableHttpResponse response = client.execute(httpUriRequest); if (isNotSuccessfull(response)) { throw new OrcidClientException( getStatusCode(response), @@ -275,21 +271,17 @@ private void executeSuccessful(HttpUriRequest httpUriRequest) { } private T executeAndParseJson(HttpUriRequest httpUriRequest, Class clazz) { - - HttpClient client = httpClientFactory.build(); - - return executeAndReturns(() -> { - - HttpResponse response = client.execute(httpUriRequest); - - if (isNotSuccessfull(response)) { - throw new OrcidClientException(getStatusCode(response), formatErrorMessage(response)); - } - - return objectMapper.readValue(response.getEntity().getContent(), clazz); - - }); - + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { + return executeAndReturns(() -> { + CloseableHttpResponse response = client.execute(httpUriRequest); + if (isNotSuccessfull(response)) { + throw new OrcidClientException(getStatusCode(response), formatErrorMessage(response)); + } + return objectMapper.readValue(response.getEntity().getContent(), clazz); + }); + } catch (IOException e) { + throw new RuntimeException(e); + } } /** @@ -304,44 +296,37 @@ private T executeAndParseJson(HttpUriRequest httpUriRequest, Class clazz) * @throws OrcidClientException if the incoming response is not successfull */ private T executeAndUnmarshall(HttpUriRequest httpUriRequest, boolean handleNotFoundAsNull, Class clazz) { - - HttpClient client = httpClientFactory.build(); - - return executeAndReturns(() -> { - - HttpResponse response = client.execute(httpUriRequest); - - if (handleNotFoundAsNull && isNotFound(response)) { - return null; - } - - if (isNotSuccessfull(response)) { - throw new OrcidClientException(getStatusCode(response), formatErrorMessage(response)); - } - - return unmarshall(response.getEntity(), clazz); - - }); + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { + return executeAndReturns(() -> { + CloseableHttpResponse response = client.execute(httpUriRequest); + if (handleNotFoundAsNull && isNotFound(response)) { + return null; + } + if (isNotSuccessfull(response)) { + throw new OrcidClientException(getStatusCode(response), formatErrorMessage(response)); + } + return unmarshall(response.getEntity(), clazz); + }); + } catch (IOException e) { + throw new RuntimeException(e); + } } private OrcidResponse execute(HttpUriRequest httpUriRequest, boolean handleNotFoundAsNull) { - HttpClient client = httpClientFactory.build(); - - return executeAndReturns(() -> { - - HttpResponse response = client.execute(httpUriRequest); - - if (handleNotFoundAsNull && isNotFound(response)) { - return new OrcidResponse(getStatusCode(response), null, getContent(response)); - } - - if (isNotSuccessfull(response)) { - throw new OrcidClientException(getStatusCode(response), formatErrorMessage(response)); - } - - return new OrcidResponse(getStatusCode(response), getPutCode(response), getContent(response)); - - }); + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { + return executeAndReturns(() -> { + CloseableHttpResponse response = client.execute(httpUriRequest); + if (handleNotFoundAsNull && isNotFound(response)) { + return new OrcidResponse(getStatusCode(response), null, getContent(response)); + } + if (isNotSuccessfull(response)) { + throw new OrcidClientException(getStatusCode(response), formatErrorMessage(response)); + } + return new OrcidResponse(getStatusCode(response), getPutCode(response), getContent(response)); + }); + } catch (IOException e) { + throw new RuntimeException(e); + } } private T executeAndReturns(ThrowingSupplier supplier) { From f4b41b701a9586b3168208bade2f54cdec17a27b Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Fri, 18 Apr 2025 15:12:55 +0200 Subject: [PATCH 550/632] [DURACOM-109] Minor fix --- .../java/org/dspace/service/impl/HttpConnectionPoolService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/service/impl/HttpConnectionPoolService.java b/dspace-api/src/main/java/org/dspace/service/impl/HttpConnectionPoolService.java index b7c99a08cecc..f0484a0576f2 100644 --- a/dspace-api/src/main/java/org/dspace/service/impl/HttpConnectionPoolService.java +++ b/dspace-api/src/main/java/org/dspace/service/impl/HttpConnectionPoolService.java @@ -112,7 +112,7 @@ protected void init() { * @return the client. */ public CloseableHttpClient getClient() { - CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().builder(false).create() + CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().builder(true).create() .setKeepAliveStrategy(keepAliveStrategy) .setConnectionManager(connManager) .build(); From 62bde6589f28688ef382d389e194ecc61b1b0082 Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Wed, 23 Apr 2025 12:31:11 +0200 Subject: [PATCH 551/632] [DURACOM-109] Continued fixing http connection leaks --- .../app/ldn/action/SendLDNMessageAction.java | 29 +++---- .../packager/AbstractMETSIngester.java | 8 +- .../ctask/general/BasicLinkChecker.java | 24 +++--- .../ctask/general/MetadataWebService.java | 85 +++++++++---------- .../ctask/general/MicrosoftTranslator.java | 26 +++--- .../dspace/eperson/CaptchaServiceImpl.java | 19 ++--- .../impl/QAEventActionServiceImpl.java | 7 +- .../export/service/OpenUrlServiceImpl.java | 16 ++-- .../service/OpenUrlServiceImplTest.java | 10 +-- 9 files changed, 106 insertions(+), 118 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/action/SendLDNMessageAction.java b/dspace-api/src/main/java/org/dspace/app/ldn/action/SendLDNMessageAction.java index cbcfd4386b3a..c5a60144e63c 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/action/SendLDNMessageAction.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/action/SendLDNMessageAction.java @@ -34,17 +34,13 @@ public class SendLDNMessageAction implements LDNAction { private static final Logger log = LogManager.getLogger(SendLDNMessageAction.class); - private CloseableHttpClient client = null; + private CloseableHttpClient client; public SendLDNMessageAction() { - client = DSpaceHttpClientFactory.getInstance().buildWithoutAutomaticRetries(5); } public SendLDNMessageAction(CloseableHttpClient client) { - this(); - if (client != null) { - this.client = client; - } + this.client = client; } @Override @@ -62,9 +58,10 @@ public LDNActionStatus execute(Context context, Notification notification, Item // NOTE: Github believes there is a "Potential server-side request forgery due to a user-provided value" // This is a false positive because the LDN Service URL is configured by the user from DSpace. // See the frontend configuration at [dspace.ui.url]/admin/ldn/services - try ( - CloseableHttpResponse response = client.execute(httpPost); - ) { + if (client == null) { + client = DSpaceHttpClientFactory.getInstance().buildWithoutAutomaticRetries(5); + } + try (CloseableHttpResponse response = client.execute(httpPost)) { if (isSuccessful(response.getStatusLine().getStatusCode())) { result = LDNActionStatus.CONTINUE; } else if (isRedirect(response.getStatusLine().getStatusCode())) { @@ -73,6 +70,7 @@ public LDNActionStatus execute(Context context, Notification notification, Item } catch (Exception e) { log.error(e); } + client.close(); return result; } @@ -87,9 +85,9 @@ private boolean isRedirect(int statusCode) { statusCode == HttpStatus.SC_TEMPORARY_REDIRECT; } - private LDNActionStatus handleRedirect(CloseableHttpResponse oldresponse, + private LDNActionStatus handleRedirect(CloseableHttpResponse oldResponse, HttpPost request) throws HttpException { - Header[] urls = oldresponse.getHeaders(HttpHeaders.LOCATION); + Header[] urls = oldResponse.getHeaders(HttpHeaders.LOCATION); String url = urls.length > 0 && urls[0] != null ? urls[0].getValue() : null; if (url == null) { throw new HttpException("Error following redirect, unable to reach" @@ -98,17 +96,14 @@ private LDNActionStatus handleRedirect(CloseableHttpResponse oldresponse, LDNActionStatus result = LDNActionStatus.ABORT; try { request.setURI(new URI(url)); - try ( - CloseableHttpResponse response = client.execute(request); - ) { + try (CloseableHttpResponse response = client.execute(request)) { if (isSuccessful(response.getStatusLine().getStatusCode())) { - return LDNActionStatus.CONTINUE; + result = LDNActionStatus.CONTINUE; } } } catch (Exception e) { log.error("Error following redirect:", e); } - - return LDNActionStatus.ABORT; + return result; } } \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java b/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java index 835b9f0e9b6f..77236be9d525 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java @@ -1314,10 +1314,10 @@ protected static InputStream getFileInputStream(File pkgFile, // we will assume all external files are available via URLs. try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { // attempt to open a connection to given URL - CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(path)); - - // open stream to access file contents - return httpResponse.getEntity().getContent(); + try (CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(path))) { + // open stream to access file contents + return httpResponse.getEntity().getContent(); + } } catch (IOException io) { log .error("Unable to retrieve external file from URL '" diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java index 189f77733886..a6621fcb2b41 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java @@ -141,21 +141,19 @@ protected boolean checkURL(String url, StringBuilder results) { protected int getResponseStatus(String url, int redirects) { RequestConfig config = RequestConfig.custom().setRedirectsEnabled(true).build(); try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().buildWithRequestConfig(config)) { - CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(url)); - int statusCode = httpResponse.getStatusLine().getStatusCode(); - int maxRedirect = configurationService.getIntProperty("curate.checklinks.max-redirect", 0); - if ((statusCode == HttpURLConnection.HTTP_MOVED_TEMP || statusCode == HttpURLConnection.HTTP_MOVED_PERM || - statusCode == HttpURLConnection.HTTP_SEE_OTHER)) { - httpClient.close(); - String newUrl = httpResponse.getFirstHeader("Location").getValue(); - if (newUrl != null && (maxRedirect >= redirects || maxRedirect == -1)) { - redirects++; - return getResponseStatus(newUrl, redirects); + try (CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(url))) { + int statusCode = httpResponse.getStatusLine().getStatusCode(); + int maxRedirect = configurationService.getIntProperty("curate.checklinks.max-redirect", 0); + if ((statusCode == HttpURLConnection.HTTP_MOVED_TEMP || statusCode == HttpURLConnection.HTTP_MOVED_PERM || + statusCode == HttpURLConnection.HTTP_SEE_OTHER)) { + String newUrl = httpResponse.getFirstHeader("Location").getValue(); + if (newUrl != null && (maxRedirect >= redirects || maxRedirect == -1)) { + redirects++; + return getResponseStatus(newUrl, redirects); + } } - + return statusCode; } - return statusCode; - } catch (IOException ioe) { // Must be a bad URL log.debug("Bad link: " + ioe.getMessage()); diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java index da7588be6c6f..7f61cad412e2 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java @@ -30,8 +30,8 @@ import javax.xml.xpath.XPathFactory; import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.LogManager; @@ -255,53 +255,50 @@ public int perform(DSpaceObject dso) throws IOException { } protected int callService(String value, Item item, StringBuilder resultSb) throws IOException { - String callUrl = urlTemplate.replaceAll("\\{" + templateParam + "\\}", value); - CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build(); - HttpGet req = new HttpGet(callUrl); - for (Map.Entry entry : headers.entrySet()) { - req.addHeader(entry.getKey(), entry.getValue()); - } - HttpResponse resp = client.execute(req); - int status = Curator.CURATE_ERROR; - int statusCode = resp.getStatusLine().getStatusCode(); - if (statusCode == HttpStatus.SC_OK) { - HttpEntity entity = resp.getEntity(); - if (entity != null) { - // boiler-plate handling taken from Apache 4.1 javadoc - InputStream instream = entity.getContent(); - try { - // This next line triggers a false-positive XXE warning from LGTM, even though we disallow DTD - // parsing during initialization of docBuilder in init() - Document doc = docBuilder.parse(instream); // lgtm [java/xxe] - status = processResponse(doc, item, resultSb); - } catch (SAXException saxE) { - log.error("caught exception: " + saxE); - resultSb.append(" unable to read response document"); - } catch (RuntimeException ex) { - // In case of an unexpected exception you may want to abort - // the HTTP request in order to shut down the underlying - // connection and release it back to the connection manager. - req.abort(); - log.error("caught exception: " + ex); - throw ex; - } finally { - // Closing the input stream will trigger connection release - instream.close(); + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { + HttpGet req = new HttpGet(callUrl); + for (Map.Entry entry : headers.entrySet()) { + req.addHeader(entry.getKey(), entry.getValue()); + } + try (CloseableHttpResponse resp = client.execute(req)) { + int status = Curator.CURATE_ERROR; + int statusCode = resp.getStatusLine().getStatusCode(); + if (statusCode == HttpStatus.SC_OK) { + HttpEntity entity = resp.getEntity(); + if (entity != null) { + // boiler-plate handling taken from Apache 4.1 javadoc + InputStream instream = entity.getContent(); + try { + // This next line triggers a false-positive XXE warning from LGTM, even though we disallow DTD + // parsing during initialization of docBuilder in init() + Document doc = docBuilder.parse(instream); // lgtm [java/xxe] + status = processResponse(doc, item, resultSb); + } catch (SAXException saxE) { + log.error("caught exception: " + saxE); + resultSb.append(" unable to read response document"); + } catch (RuntimeException ex) { + // In case of an unexpected exception you may want to abort + // the HTTP request in order to shut down the underlying + // connection and release it back to the connection manager. + req.abort(); + log.error("caught exception: " + ex); + throw ex; + } finally { + // Closing the input stream will trigger connection release + instream.close(); + } + } else { + log.error(" obtained no valid service response"); + resultSb.append("no service response"); + } + } else { + log.error("service returned non-OK status: " + statusCode); + resultSb.append("no service response"); } - // When HttpClient instance is no longer needed, - // shut down the connection manager to ensure - // immediate deallocation of all system resources - client.close(); - } else { - log.error(" obtained no valid service response"); - resultSb.append("no service response"); + return status; } - } else { - log.error("service returned non-OK status: " + statusCode); - resultSb.append("no service response"); } - return status; } protected int processResponse(Document doc, Item item, StringBuilder resultSb) throws IOException { diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/MicrosoftTranslator.java b/dspace-api/src/main/java/org/dspace/ctask/general/MicrosoftTranslator.java index 0d682d9406f4..af9c2de0c8b1 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/MicrosoftTranslator.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/MicrosoftTranslator.java @@ -12,7 +12,7 @@ import java.nio.charset.StandardCharsets; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.LogManager; @@ -62,20 +62,18 @@ protected String translateText(String from, String to, String text) throws IOExc try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { HttpGet hm = new HttpGet(url); - HttpResponse httpResponse = client.execute(hm); - log.debug("Response code from API call is " + httpResponse); - - if (httpResponse.getStatusLine().getStatusCode() == 200) { - String response = IOUtils.toString(httpResponse.getEntity().getContent(), - StandardCharsets.ISO_8859_1); - response = response - .replaceAll("", ""); - response = response.replaceAll("", ""); - translatedText = response; + try (CloseableHttpResponse httpResponse = client.execute(hm)) { + log.debug("Response code from API call is " + httpResponse); + if (httpResponse.getStatusLine().getStatusCode() == 200) { + String response = IOUtils.toString(httpResponse.getEntity().getContent(), + StandardCharsets.ISO_8859_1); + response = response + .replaceAll("", ""); + response = response.replaceAll("", ""); + translatedText = response; + } } } - return translatedText; } -} - +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/eperson/CaptchaServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/CaptchaServiceImpl.java index 8300061cbe4e..15f92247d6cc 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/CaptchaServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/CaptchaServiceImpl.java @@ -17,11 +17,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.PostConstruct; -import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -82,18 +82,17 @@ public void processResponse(String response, String action) throws InvalidReCapt throw new RuntimeException(e.getMessage(), e); } - HttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); - HttpResponse httpResponse; - GoogleCaptchaResponse googleResponse; - final ObjectMapper objectMapper = new ObjectMapper(); - try { - httpResponse = httpClient.execute(httpPost); - googleResponse = objectMapper.readValue(httpResponse.getEntity().getContent(), GoogleCaptchaResponse.class); + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { + final ObjectMapper objectMapper = new ObjectMapper(); + try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { + GoogleCaptchaResponse googleResponse = objectMapper.readValue(httpResponse.getEntity().getContent(), + GoogleCaptchaResponse.class); + validateGoogleResponse(googleResponse, action); + } } catch (IOException e) { log.error(e.getMessage(), e); throw new RuntimeException("Error during verify google recaptcha site", e); } - validateGoogleResponse(googleResponse, action); } private boolean responseSanityCheck(String response) { diff --git a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java index 38e7295582eb..3faee3a4f9f7 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java @@ -123,10 +123,9 @@ private void makeAcknowledgement(String eventId, String source, String status) { node.put("eventId", eventId); node.put("status", status); StringEntity requestEntity = new StringEntity(node.toString(), ContentType.APPLICATION_JSON); - CloseableHttpClient httpclient = DSpaceHttpClientFactory.getInstance().buildWithoutProxy(); - HttpPost postMethod = new HttpPost(ackwnoledgeCallback); - postMethod.setEntity(requestEntity); - try { + try (CloseableHttpClient httpclient = DSpaceHttpClientFactory.getInstance().buildWithoutProxy()) { + HttpPost postMethod = new HttpPost(ackwnoledgeCallback); + postMethod.setEntity(requestEntity); httpclient.execute(postMethod); } catch (IOException e) { log.error(e.getMessage(), e); diff --git a/dspace-api/src/main/java/org/dspace/statistics/export/service/OpenUrlServiceImpl.java b/dspace-api/src/main/java/org/dspace/statistics/export/service/OpenUrlServiceImpl.java index d8f4aa6b7e7b..64014fcbc07c 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/export/service/OpenUrlServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/statistics/export/service/OpenUrlServiceImpl.java @@ -14,10 +14,10 @@ import java.util.List; import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.client.DSpaceHttpClientFactory; @@ -68,13 +68,15 @@ public void processUrl(Context c, String urlStr) throws SQLException { * @throws IOException */ protected int getResponseCodeFromUrl(final String urlStr) throws IOException { - HttpGet httpGet = new HttpGet(urlStr); - HttpClient httpClient = getHttpClient(getHttpClientRequestConfig()); - HttpResponse httpResponse = httpClient.execute(httpGet); - return httpResponse.getStatusLine().getStatusCode(); + try (CloseableHttpClient httpClient = getHttpClient(getHttpClientRequestConfig())) { + HttpGet httpGet = new HttpGet(urlStr); + try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { + return httpResponse.getStatusLine().getStatusCode(); + } + } } - protected HttpClient getHttpClient(RequestConfig requestConfig) { + protected CloseableHttpClient getHttpClient(RequestConfig requestConfig) { return DSpaceHttpClientFactory.getInstance().buildWithRequestConfig(requestConfig); } diff --git a/dspace-api/src/test/java/org/dspace/statistics/export/service/OpenUrlServiceImplTest.java b/dspace-api/src/test/java/org/dspace/statistics/export/service/OpenUrlServiceImplTest.java index d214050e6b5a..718ef701e136 100644 --- a/dspace-api/src/test/java/org/dspace/statistics/export/service/OpenUrlServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/statistics/export/service/OpenUrlServiceImplTest.java @@ -27,9 +27,9 @@ import java.util.Date; import java.util.List; -import org.apache.http.HttpResponse; import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.impl.client.CloseableHttpClient; import org.dspace.core.Context; import org.dspace.statistics.export.OpenURLTracker; import org.junit.Before; @@ -55,7 +55,7 @@ public class OpenUrlServiceImplTest { private FailedOpenURLTrackerService failedOpenURLTrackerService; @Mock - private HttpClient httpClient; + private CloseableHttpClient httpClient; @Before public void setUp() throws Exception { @@ -74,11 +74,11 @@ public void setUp() throws Exception { * @param statusCode the http status code to use in the mock. * @return a mocked http response. */ - protected HttpResponse createMockHttpResponse(int statusCode) { + protected CloseableHttpResponse createMockHttpResponse(int statusCode) { StatusLine statusLine = mock(StatusLine.class); when(statusLine.getStatusCode()).thenReturn(statusCode); - HttpResponse httpResponse = mock(HttpResponse.class); + CloseableHttpResponse httpResponse = mock(CloseableHttpResponse.class); when(httpResponse.getStatusLine()).thenReturn(statusLine); return httpResponse; From 460b2d1653e2da6a64ccf05c2fdc51961533005d Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Wed, 23 Apr 2025 15:34:52 +0200 Subject: [PATCH 552/632] [DURACOM-109] Linter error fix --- .../ctask/general/BasicLinkChecker.java | 21 +++++++++---------- .../ctask/general/MetadataWebService.java | 4 ++-- .../impl/QAEventActionServiceImpl.java | 14 ++++++------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java index a6621fcb2b41..020331842703 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java @@ -141,19 +141,18 @@ protected boolean checkURL(String url, StringBuilder results) { protected int getResponseStatus(String url, int redirects) { RequestConfig config = RequestConfig.custom().setRedirectsEnabled(true).build(); try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().buildWithRequestConfig(config)) { - try (CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(url))) { - int statusCode = httpResponse.getStatusLine().getStatusCode(); - int maxRedirect = configurationService.getIntProperty("curate.checklinks.max-redirect", 0); - if ((statusCode == HttpURLConnection.HTTP_MOVED_TEMP || statusCode == HttpURLConnection.HTTP_MOVED_PERM || - statusCode == HttpURLConnection.HTTP_SEE_OTHER)) { - String newUrl = httpResponse.getFirstHeader("Location").getValue(); - if (newUrl != null && (maxRedirect >= redirects || maxRedirect == -1)) { - redirects++; - return getResponseStatus(newUrl, redirects); - } + CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(url)); + int statusCode = httpResponse.getStatusLine().getStatusCode(); + int maxRedirect = configurationService.getIntProperty("curate.checklinks.max-redirect", 0); + if ((statusCode == HttpURLConnection.HTTP_MOVED_TEMP || statusCode == HttpURLConnection.HTTP_MOVED_PERM || + statusCode == HttpURLConnection.HTTP_SEE_OTHER)) { + String newUrl = httpResponse.getFirstHeader("Location").getValue(); + if (newUrl != null && (maxRedirect >= redirects || maxRedirect == -1)) { + redirects++; + return getResponseStatus(newUrl, redirects); } - return statusCode; } + return statusCode; } catch (IOException ioe) { // Must be a bad URL log.debug("Bad link: " + ioe.getMessage()); diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java index 7f61cad412e2..fc62d7a4b23f 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java @@ -270,8 +270,8 @@ protected int callService(String value, Item item, StringBuilder resultSb) throw // boiler-plate handling taken from Apache 4.1 javadoc InputStream instream = entity.getContent(); try { - // This next line triggers a false-positive XXE warning from LGTM, even though we disallow DTD - // parsing during initialization of docBuilder in init() + // This next line triggers a false-positive XXE warning from LGTM, even though + // we disallow DTD parsing during initialization of docBuilder in init() Document doc = docBuilder.parse(instream); // lgtm [java/xxe] status = processResponse(doc, item, resultSb); } catch (SAXException saxE) { diff --git a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java index 3faee3a4f9f7..6b9aea91de76 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventActionServiceImpl.java @@ -114,19 +114,19 @@ public void reject(Context context, QAEvent qaevent) { * Make acknowledgement to the configured urls for the event status. */ private void makeAcknowledgement(String eventId, String source, String status) { - String[] ackwnoledgeCallbacks = configurationService + String[] acknowledgeCallbacks = configurationService .getArrayProperty("qaevents." + source + ".acknowledge-url"); - if (ackwnoledgeCallbacks != null) { - for (String ackwnoledgeCallback : ackwnoledgeCallbacks) { - if (StringUtils.isNotBlank(ackwnoledgeCallback)) { + if (acknowledgeCallbacks != null) { + for (String acknowledgeCallback : acknowledgeCallbacks) { + if (StringUtils.isNotBlank(acknowledgeCallback)) { ObjectNode node = jsonMapper.createObjectNode(); node.put("eventId", eventId); node.put("status", status); StringEntity requestEntity = new StringEntity(node.toString(), ContentType.APPLICATION_JSON); - try (CloseableHttpClient httpclient = DSpaceHttpClientFactory.getInstance().buildWithoutProxy()) { - HttpPost postMethod = new HttpPost(ackwnoledgeCallback); + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().buildWithoutProxy()) { + HttpPost postMethod = new HttpPost(acknowledgeCallback); postMethod.setEntity(requestEntity); - httpclient.execute(postMethod); + httpClient.execute(postMethod); } catch (IOException e) { log.error(e.getMessage(), e); } From 838e642b2b2f728e599076c01818b701797fbab4 Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Wed, 23 Apr 2025 17:43:49 +0200 Subject: [PATCH 553/632] [DURACOM-109] Minor fix --- .../external/OpenaireRestConnector.java | 118 +++++++++--------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java b/dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java index b036a98634e0..87af01401ac0 100644 --- a/dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java +++ b/dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java @@ -27,10 +27,10 @@ import org.apache.http.NameValuePair; import org.apache.http.NoHttpResponseException; import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.logging.log4j.Logger; import org.dspace.app.client.DSpaceHttpClientFactory; @@ -120,33 +120,34 @@ public OpenaireRestToken grabNewAccessToken() throws IOException { params.add(new BasicNameValuePair("grant_type", "client_credentials")); httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); - HttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); - HttpResponse getResponse = httpClient.execute(httpPost); - - JSONObject responseObject = null; - try (InputStream is = getResponse.getEntity().getContent(); - BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, "UTF-8"))) { - String inputStr; - // verify if we have basic json - while ((inputStr = streamReader.readLine()) != null && responseObject == null) { - if (inputStr.startsWith("{") && inputStr.endsWith("}") && inputStr.contains("access_token") - && inputStr.contains("expires_in")) { - try { - responseObject = new JSONObject(inputStr); - } catch (Exception e) { - // Not as valid as I'd hoped, move along - responseObject = null; + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { + HttpResponse getResponse = httpClient.execute(httpPost); + + JSONObject responseObject = null; + try (InputStream is = getResponse.getEntity().getContent(); + BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, "UTF-8"))) { + String inputStr; + // verify if we have basic json + while ((inputStr = streamReader.readLine()) != null && responseObject == null) { + if (inputStr.startsWith("{") && inputStr.endsWith("}") && inputStr.contains("access_token") + && inputStr.contains("expires_in")) { + try { + responseObject = new JSONObject(inputStr); + } catch (Exception e) { + // Not as valid as I'd hoped, move along + responseObject = null; + } } } } - } - if (responseObject == null || !responseObject.has("access_token") || !responseObject.has("expires_in")) { - throw new IOException("Unable to grab the access token using provided service url, client id and secret"); - } - - return new OpenaireRestToken(responseObject.get("access_token").toString(), - Long.valueOf(responseObject.get("expires_in").toString())); + if (responseObject == null || !responseObject.has("access_token") || !responseObject.has("expires_in")) { + throw new IOException("Unable to grab the access token using provided service url, " + + "client id and secret"); + } + return new OpenaireRestToken(responseObject.get("access_token").toString(), + Long.valueOf(responseObject.get("expires_in").toString())); + } } /** @@ -171,42 +172,43 @@ public InputStream get(String file, String accessToken) { httpGet.addHeader("Authorization", "Bearer " + accessToken); } - HttpClient httpClient = DSpaceHttpClientFactory.getInstance().build(); - getResponse = httpClient.execute(httpGet); - - StatusLine status = getResponse.getStatusLine(); - - // registering errors - switch (status.getStatusCode()) { - case HttpStatus.SC_NOT_FOUND: - // 404 - Not found - case HttpStatus.SC_FORBIDDEN: - // 403 - Invalid Access Token - case 429: - // 429 - Rate limit abuse for unauthenticated user - Header[] limitUsed = getResponse.getHeaders("x-ratelimit-used"); - Header[] limitMax = getResponse.getHeaders("x-ratelimit-limit"); - - if (limitUsed.length > 0) { - String limitMsg = limitUsed[0].getValue(); - if (limitMax.length > 0) { - limitMsg = limitMsg.concat(" of " + limitMax[0].getValue()); + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { + getResponse = httpClient.execute(httpGet); + + StatusLine status = getResponse.getStatusLine(); + + // registering errors + switch (status.getStatusCode()) { + case HttpStatus.SC_NOT_FOUND: + // 404 - Not found + case HttpStatus.SC_FORBIDDEN: + // 403 - Invalid Access Token + case 429: + // 429 - Rate limit abuse for unauthenticated user + Header[] limitUsed = getResponse.getHeaders("x-ratelimit-used"); + Header[] limitMax = getResponse.getHeaders("x-ratelimit-limit"); + + if (limitUsed.length > 0) { + String limitMsg = limitUsed[0].getValue(); + if (limitMax.length > 0) { + limitMsg = limitMsg.concat(" of " + limitMax[0].getValue()); + } + getGotError(new NoHttpResponseException(status.getReasonPhrase() + " with usage limit " + + limitMsg), + url + '/' + file); + } else { + // 429 - Rate limit abuse + getGotError(new NoHttpResponseException(status.getReasonPhrase()), url + '/' + file); } - getGotError( - new NoHttpResponseException(status.getReasonPhrase() + " with usage limit " + limitMsg), - url + '/' + file); - } else { - // 429 - Rate limit abuse - getGotError(new NoHttpResponseException(status.getReasonPhrase()), url + '/' + file); - } - break; - default: - // 200 or other - break; - } + break; + default: + // 200 or other + break; + } - // do not close this httpClient - result = getResponse.getEntity().getContent(); + // do not close this httpClient + result = getResponse.getEntity().getContent(); + } } catch (MalformedURLException e1) { getGotError(e1, url + '/' + file); } catch (Exception e) { From 1bf06b78842ccde45ef0e0ffebe0e66cd039fe2e Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Mon, 28 Apr 2025 08:51:06 +0200 Subject: [PATCH 554/632] [DURACOM-109] fix typo and correct logic for ORCID connector --- dspace-api/pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 0946c9800eaf..02ca5dfc7778 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -512,10 +512,6 @@ org.apache.pdfbox pdfbox - - org.apache.pdfbox - fontbox - com.ibm.icu icu4j From 644d15f8811555a2c4598ef1f0cf12f9fefd4d3a Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Mon, 28 Apr 2025 10:50:32 +0200 Subject: [PATCH 555/632] [DURACOM-109] Orcid connector fix and improvement --- .../provider/impl/OrcidV3AuthorDataProvider.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java index dfbd07a83a02..a9e10f92948d 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java @@ -169,13 +169,7 @@ public Person getBio(String id) { } initializeAccessToken(); InputStream bioDocument = orcidRestConnector.get(id + ((id.endsWith("/person")) ? "" : "/person"), accessToken); - Person person = converter.convertSinglePerson(bioDocument); - try { - bioDocument.close(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - return person; + return converter.convertSinglePerson(bioDocument); } /** @@ -220,11 +214,6 @@ public List searchExternalDataObjects(String query, int star } } } - try { - bioDocument.close(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } return bios.stream().map(bio -> convertToExternalDataObject(bio)).collect(Collectors.toList()); } From ca671b2aa01c2b70a212ee56c7a37f69b4c097df Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Tue, 29 Apr 2025 08:52:36 +0200 Subject: [PATCH 556/632] [DURACOM-109] added checkstyle rules to forbid usage of HttpClientBuilder.create() --- checkstyle-suppressions.xml | 1 + checkstyle.xml | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml index 77e27b8768ac..46bd9ca80d62 100644 --- a/checkstyle-suppressions.xml +++ b/checkstyle-suppressions.xml @@ -7,4 +7,5 @@ + diff --git a/checkstyle.xml b/checkstyle.xml index a33fc4831950..36d2b15bd89e 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -136,5 +136,22 @@ For more information on CheckStyle configurations below, see: http://checkstyle. + + + + + + + + + + + + + + + + + From 480a919754ba3397b15008b0bcbfd7c26b1c8d97 Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Tue, 29 Apr 2025 09:07:25 +0200 Subject: [PATCH 557/632] [DURACOM-109] fix TruncatedChunkException error --- .../main/java/org/dspace/external/OrcidRestConnector.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java b/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java index f2c6246f4d06..aa16af7a524d 100644 --- a/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java +++ b/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java @@ -7,6 +7,7 @@ */ package org.dspace.external; +import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Scanner; @@ -51,7 +52,11 @@ public InputStream get(String path, String accessToken) { } try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { getResponse = httpClient.execute(httpGet); - result = getResponse.getEntity().getContent(); + try (InputStream responseStream = getResponse.getEntity().getContent()) { + // Read all the content of the response stream into a byte array to prevent TruncatedChunkException + byte[] content = responseStream.readAllBytes(); + result = new ByteArrayInputStream(content); + } } catch (Exception e) { getGotError(e, fullPath); } From 2c2e23f8bcf0b4ed527716def85d1dfd050823f6 Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Tue, 6 May 2025 16:43:23 +0200 Subject: [PATCH 558/632] [DURACOM-109] Fixed conflicts --- .../org/dspace/app/sherpa/SHERPAService.java | 120 +++++++++--------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java index 6f26d0cc2d27..1fec20f51fee 100644 --- a/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java @@ -63,7 +63,7 @@ public class SHERPAService { @SuppressWarnings("unused") @PostConstruct private void init() { - // Get endoint and API key from configuration + // Get endpoint and API key from configuration endpoint = configurationService.getProperty("sherpa.romeo.url", "https://v2.sherpa.ac.uk/cgi/retrieve"); apiKey = configurationService.getProperty("sherpa.romeo.apikey"); @@ -117,46 +117,47 @@ public SHERPAPublisherResponse performPublisherRequest(String type, String field timeout, sleepBetweenTimeouts)); - try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().buildWithoutAutomaticRetries(5)) { Thread.sleep(sleepBetweenTimeouts); // Construct a default HTTP method (first result) method = constructHttpGet(type, field, predicate, value, start, limit); // Execute the method - CloseableHttpResponse response = client.execute(method); - int statusCode = response.getStatusLine().getStatusCode(); + try (CloseableHttpResponse response = client.execute(method)) { + int statusCode = response.getStatusLine().getStatusCode(); - log.debug(response.getStatusLine().getStatusCode() + ": " - + response.getStatusLine().getReasonPhrase()); + log.debug(response.getStatusLine().getStatusCode() + ": " + + response.getStatusLine().getReasonPhrase()); - if (statusCode != HttpStatus.SC_OK) { - sherpaResponse = new SHERPAPublisherResponse("SHERPA/RoMEO return not OK status: " - + statusCode); - String errorBody = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); - log.error("Error from SHERPA HTTP request: " + errorBody); - } + if (statusCode != HttpStatus.SC_OK) { + sherpaResponse = new SHERPAPublisherResponse("SHERPA/RoMEO return not OK status: " + + statusCode); + String errorBody = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + log.error("Error from SHERPA HTTP request: " + errorBody); + } - HttpEntity responseBody = response.getEntity(); - - // If the response body is valid, pass to SHERPAResponse for parsing as JSON - if (null != responseBody) { - log.debug("Non-null SHERPA resonse received for query of " + value); - InputStream content = null; - try { - content = responseBody.getContent(); - sherpaResponse = - new SHERPAPublisherResponse(content, SHERPAPublisherResponse.SHERPAFormat.JSON); - } catch (IOException e) { - log.error("Encountered exception while contacting SHERPA/RoMEO: " + e.getMessage(), e); - } finally { - if (content != null) { - content.close(); + HttpEntity responseBody = response.getEntity(); + + // If the response body is valid, pass to SHERPAResponse for parsing as JSON + if (null != responseBody) { + log.debug("Non-null SHERPA response received for query of " + value); + InputStream content = null; + try { + content = responseBody.getContent(); + sherpaResponse = + new SHERPAPublisherResponse(content, SHERPAPublisherResponse.SHERPAFormat.JSON); + } catch (IOException e) { + log.error("Encountered exception while contacting SHERPA/RoMEO: " + e.getMessage(), e); + } finally { + if (content != null) { + content.close(); + } } + } else { + log.debug("Empty SHERPA response body for query on " + value); + sherpaResponse = new SHERPAPublisherResponse("SHERPA/RoMEO returned no response"); } - } else { - log.debug("Empty SHERPA response body for query on " + value); - sherpaResponse = new SHERPAPublisherResponse("SHERPA/RoMEO returned no response"); } } catch (URISyntaxException e) { String errorMessage = "Error building SHERPA v2 API URI: " + e.getMessage(); @@ -220,45 +221,46 @@ public SHERPAResponse performRequest(String type, String field, String predicate timeout, sleepBetweenTimeouts)); - try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().build()) { + try (CloseableHttpClient client = DSpaceHttpClientFactory.getInstance().buildWithoutAutomaticRetries(5)) { Thread.sleep(sleepBetweenTimeouts); // Construct a default HTTP method (first result) method = constructHttpGet(type, field, predicate, value, start, limit); // Execute the method - CloseableHttpResponse response = client.execute(method); - int statusCode = response.getStatusLine().getStatusCode(); + try (CloseableHttpResponse response = client.execute(method)) { + int statusCode = response.getStatusLine().getStatusCode(); - log.debug(response.getStatusLine().getStatusCode() + ": " - + response.getStatusLine().getReasonPhrase()); + log.debug(response.getStatusLine().getStatusCode() + ": " + + response.getStatusLine().getReasonPhrase()); - if (statusCode != HttpStatus.SC_OK) { - sherpaResponse = new SHERPAResponse("SHERPA/RoMEO return not OK status: " - + statusCode); - String errorBody = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); - log.error("Error from SHERPA HTTP request: " + errorBody); - } + if (statusCode != HttpStatus.SC_OK) { + sherpaResponse = new SHERPAResponse("SHERPA/RoMEO return not OK status: " + + statusCode); + String errorBody = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + log.error("Error from SHERPA HTTP request: " + errorBody); + } - HttpEntity responseBody = response.getEntity(); - - // If the response body is valid, pass to SHERPAResponse for parsing as JSON - if (null != responseBody) { - log.debug("Non-null SHERPA resonse received for query of " + value); - InputStream content = null; - try { - content = responseBody.getContent(); - sherpaResponse = new SHERPAResponse(content, SHERPAResponse.SHERPAFormat.JSON); - } catch (IOException e) { - log.error("Encountered exception while contacting SHERPA/RoMEO: " + e.getMessage(), e); - } finally { - if (content != null) { - content.close(); + HttpEntity responseBody = response.getEntity(); + + // If the response body is valid, pass to SHERPAResponse for parsing as JSON + if (null != responseBody) { + log.debug("Non-null SHERPA response received for query of " + value); + InputStream content = null; + try { + content = responseBody.getContent(); + sherpaResponse = new SHERPAResponse(content, SHERPAResponse.SHERPAFormat.JSON); + } catch (IOException e) { + log.error("Encountered exception while contacting SHERPA/RoMEO: " + e.getMessage(), e); + } finally { + if (content != null) { + content.close(); + } } + } else { + log.debug("Empty SHERPA response body for query on " + value); + sherpaResponse = new SHERPAResponse("SHERPA/RoMEO returned no response"); } - } else { - log.debug("Empty SHERPA response body for query on " + value); - sherpaResponse = new SHERPAResponse("SHERPA/RoMEO returned no response"); } } catch (URISyntaxException e) { String errorMessage = "Error building SHERPA v2 API URI: " + e.getMessage(); @@ -268,7 +270,7 @@ public SHERPAResponse performRequest(String type, String field, String predicate String errorMessage = "Encountered exception while contacting SHERPA/RoMEO: " + e.getMessage(); log.error(errorMessage, e); sherpaResponse = new SHERPAResponse(errorMessage); - } catch (InterruptedException e) { + } catch (InterruptedException e) { String errorMessage = "Encountered exception while sleeping thread: " + e.getMessage(); log.error(errorMessage, e); sherpaResponse = new SHERPAResponse(errorMessage); From c1f73006da27f144357a6e394aa00f1c187d38ca Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Wed, 26 Feb 2025 10:53:25 +0100 Subject: [PATCH 559/632] [DURACOM-328] fix error in check for Patch request (cherry picked from commit f787e0bb34b88eecd480466174e29d0f33774ed0) --- .../dspaceFolder/config/item-submission.xml | 13 +++++- .../config/spring/api/access-conditions.xml | 13 ++++++ .../app/rest/submit/step/UploadStep.java | 22 ++++++--- .../rest/WorkflowItemRestRepositoryIT.java | 46 +++++++++++++++++++ 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml b/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml index feb3c7c12b3d..51c6a228d4fb 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml @@ -29,6 +29,7 @@ + @@ -194,7 +195,11 @@ org.dspace.app.rest.submit.step.NotifyStep coarnotify - + + submit.progressbar.upload-no-required-metadata + org.dspace.app.rest.submit.step.UploadStep + upload + @@ -300,6 +305,12 @@ + + + + + + diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/access-conditions.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/access-conditions.xml index a9af7c66f5e8..bf02e6a23ed2 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/access-conditions.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/access-conditions.xml @@ -55,6 +55,7 @@ + @@ -116,4 +117,16 @@ + + + + + + + + + + + + diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java index 877e64756df5..cc5368add735 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java @@ -11,6 +11,7 @@ import java.io.InputStream; import java.util.List; import java.util.Objects; +import java.util.regex.Pattern; import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; @@ -48,6 +49,13 @@ public class UploadStep extends AbstractProcessingStep private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(UploadStep.class); + private static final Pattern UPDATE_METADATA_PATTERN = + Pattern.compile("^/sections/[^/]+/files/[^/]+/metadata/[^/]+(/[^/]+)?$"); + private static final Pattern PRIMARY_FLAG_PATTERN = + Pattern.compile("^/sections/[^/]+/primary$"); + private static final Pattern ACCESS_CONDITION_PATTERN = + Pattern.compile("^/sections/[^/]+/files/[^/]+/accessConditions(/[^/]+)?$"); + @Override public DataUpload getData(SubmissionService submissionService, InProgressSubmission obj, SubmissionStepConfig config) throws Exception { @@ -73,27 +81,27 @@ public void doPatchProcessing(Context context, HttpServletRequest currentRequest String instance = null; if ("remove".equals(op.getOp())) { - if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) { + if (UPDATE_METADATA_PATTERN.matcher(op.getPath()).matches()) { instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY; - } else if (op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) { + } else if (ACCESS_CONDITION_PATTERN.matcher(op.getPath()).matches()) { instance = stepConf.getType() + "." + UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY; - } else if (op.getPath().contains(PRIMARY_FLAG_ENTRY)) { + } else if (PRIMARY_FLAG_PATTERN.matcher(op.getPath()).matches()) { instance = PRIMARY_FLAG_ENTRY; } else { instance = UPLOAD_STEP_REMOVE_OPERATION_ENTRY; } } else if ("move".equals(op.getOp())) { - if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) { + if (UPDATE_METADATA_PATTERN.matcher(op.getPath()).matches()) { instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY; } else { instance = UPLOAD_STEP_MOVE_OPERATION_ENTRY; } } else { - if (op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) { + if (ACCESS_CONDITION_PATTERN.matcher(op.getPath()).matches()) { instance = stepConf.getType() + "." + UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY; - } else if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) { + } else if (UPDATE_METADATA_PATTERN.matcher(op.getPath()).matches()) { instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY; - } else if (op.getPath().contains(PRIMARY_FLAG_ENTRY)) { + } else if (PRIMARY_FLAG_PATTERN.matcher(op.getPath()).matches()) { instance = PRIMARY_FLAG_ENTRY; } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java index a9bbc752f875..9eebed85f652 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java @@ -9,6 +9,7 @@ import static com.jayway.jsonpath.JsonPath.read; import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -2218,4 +2219,49 @@ public void testWorkflowWithHiddenSections() throws Exception { } + @Test + public void deleteBitstreamTest() + throws Exception { + context.turnOffAuthorisationSystem(); + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("submitter@example.com") + .withPassword(password) + .build(); + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Collection collection1 = CollectionBuilder.createCollection(context, parentCommunity, + "123456789/collection-test-patch") + .withName("Collection 1") + .build(); + Bitstream bitstream = null; + WorkspaceItem witem = null; + String bitstreamContent = "0123456789"; + try (InputStream is = IOUtils.toInputStream(bitstreamContent, Charset.defaultCharset())) { + context.setCurrentUser(submitter); + witem = WorkspaceItemBuilder.createWorkspaceItem(context, collection1) + .withTitle("Test WorkspaceItem") + .withIssueDate("2019-10-01") + .grantLicense() + .build(); + bitstream = BitstreamBuilder.createBitstream(context, witem.getItem(), is) + .withName("Test bitstream") + .withDescription("This is a bitstream to test range requests") + .withMimeType("text/plain") + .build(); + } + context.restoreAuthSystemState(); + String tokenSubmitter = getAuthToken(submitter.getEmail(), password); + List deleteFile = new ArrayList<>(); + deleteFile.add(new RemoveOperation("/sections/bitstream-metadata-publication/files/0/")); + getClient(tokenSubmitter).perform(patch("/api/submission/workspaceitems/" + witem.getID()) + .content(getPatchContent(deleteFile)) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + // verify that the patch removed bitstream + getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + witem.getID())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.sections.bitstream-metadata-publication.files",hasSize(0))); + } + } From 742e777e2bfbfcde664a9e91befd8bc73238c0fd Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Wed, 26 Feb 2025 11:18:36 +0100 Subject: [PATCH 560/632] [DURACOM-328] fix test (cherry picked from commit a6529b413fe65a7485ca8ed6710b38334e4a8572) --- .../org/dspace/app/rest/WorkflowItemRestRepositoryIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java index 9eebed85f652..ef475353b93e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java @@ -2253,7 +2253,7 @@ public void deleteBitstreamTest() context.restoreAuthSystemState(); String tokenSubmitter = getAuthToken(submitter.getEmail(), password); List deleteFile = new ArrayList<>(); - deleteFile.add(new RemoveOperation("/sections/bitstream-metadata-publication/files/0/")); + deleteFile.add(new RemoveOperation("/sections/upload-no-required-metadata/files/0/")); getClient(tokenSubmitter).perform(patch("/api/submission/workspaceitems/" + witem.getID()) .content(getPatchContent(deleteFile)) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) @@ -2261,7 +2261,7 @@ public void deleteBitstreamTest() // verify that the patch removed bitstream getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + witem.getID())) .andExpect(status().isOk()) - .andExpect(jsonPath("$.sections.bitstream-metadata-publication.files",hasSize(0))); + .andExpect(jsonPath("$.sections.upload-no-required-metadata.files",hasSize(0))); } } From 1383f47babbe20f3c0b041cf7450d8c14ce04ef0 Mon Sep 17 00:00:00 2001 From: Elios Buzo Date: Wed, 7 May 2025 12:31:58 +0200 Subject: [PATCH 561/632] [DURACOM-109] Minor fix --- .../org/dspace/orcid/model/factory/OrcidFactoryUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/orcid/model/factory/OrcidFactoryUtils.java b/dspace-api/src/main/java/org/dspace/orcid/model/factory/OrcidFactoryUtils.java index 38aa611ff3a0..ce68ab47c26e 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/model/factory/OrcidFactoryUtils.java +++ b/dspace-api/src/main/java/org/dspace/orcid/model/factory/OrcidFactoryUtils.java @@ -20,7 +20,7 @@ import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; +import org.dspace.app.client.DSpaceHttpClientFactory; import org.json.JSONObject; /** @@ -97,7 +97,7 @@ public static Optional retrieveAccessToken(String clientId, String clien httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); HttpResponse response; - try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { + try (CloseableHttpClient httpClient = DSpaceHttpClientFactory.getInstance().build()) { response = httpClient.execute(httpPost); } JSONObject responseObject = null; From 6e9579a0d704fe50f66a635056021df5a7a24a93 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 7 May 2025 09:15:57 -0500 Subject: [PATCH 562/632] Fix test by increasing submission definitions count --- .../org/dspace/app/rest/SubmissionDefinitionsControllerIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java index 0722949ffd0b..bcea11cbb5a4 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java @@ -35,7 +35,7 @@ public class SubmissionDefinitionsControllerIT extends AbstractControllerIntegra // The total number of expected submission definitions is referred to in multiple tests and assertions as // is the last page (totalDefinitions - 1) // This integer should be maintained along with any changes to item-submissions.xml - private static final int totalDefinitions = 12; + private static final int totalDefinitions = 13; @Test public void findAll() throws Exception { From c4efc12406f49b9ba87b9ae3d85537625300138d Mon Sep 17 00:00:00 2001 From: Stefano Maffei Date: Fri, 9 May 2025 16:02:36 +0200 Subject: [PATCH 563/632] [DURACOM-109] restore missing dependency --- dspace-api/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index e323710dda4c..a7ecdb5ef5f9 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -512,6 +512,10 @@ org.apache.pdfbox pdfbox + + org.apache.pdfbox + fontbox + com.ibm.icu icu4j From 37dd836e185ec066aa6a66b399eb2ac6cc79cf55 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 9 May 2025 12:32:19 -0500 Subject: [PATCH 564/632] Potential fix for code scanning alert no. 3549: Arbitrary file access during archive extraction ("Zip Slip") Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> (cherry picked from commit 5fbdfc218f0c4da45fc430f5ee50c3813e7bb851) --- .../org/dspace/sword2/SimpleZipContentIngester.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleZipContentIngester.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleZipContentIngester.java index bd8301617ba9..7899bf861b32 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleZipContentIngester.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleZipContentIngester.java @@ -138,12 +138,18 @@ private List unzipToBundle(Context context, File depositFile, Enumeration zenum = zip.entries(); while (zenum.hasMoreElements()) { ZipEntry entry = (ZipEntry) zenum.nextElement(); + String entryName = entry.getName(); + java.nio.file.Path entryPath = java.nio.file.Paths.get(entryName).normalize(); + if (entryPath.isAbsolute() || entryPath.startsWith("..")) { + throw new SwordError(UriRegistry.ERROR_BAD_REQUEST, "Invalid zip entry: " + entryName); + } + InputStream stream = zip.getInputStream(entry); Bitstream bs = bitstreamService.create(context, target, stream); BitstreamFormat format = this - .getFormat(context, entry.getName()); + .getFormat(context, entryName); bs.setFormat(context, format); - bs.setName(context, entry.getName()); + bs.setName(context, entryName); bitstreamService.update(context, bs); derivedResources.add(bs); } From 5c7db5654588316129559a4bbaee85371c387984 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 22:39:31 +0000 Subject: [PATCH 565/632] Bump org.webjars.npm:json-editor__json-editor in the webjars group Bumps the webjars group with 1 update: [org.webjars.npm:json-editor__json-editor](https://github.com/json-editor/json-editor). Updates `org.webjars.npm:json-editor__json-editor` from 2.15.1 to 2.15.2 - [Changelog](https://github.com/json-editor/json-editor/blob/master/CHANGELOG.md) - [Commits](https://github.com/json-editor/json-editor/compare/2.15.1...2.15.2) --- updated-dependencies: - dependency-name: org.webjars.npm:json-editor__json-editor dependency-version: 2.15.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: webjars ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 153f59e8d5ab..3efef6469971 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -423,7 +423,7 @@ org.webjars.npm json-editor__json-editor - 2.15.1 + 2.15.2 ${basedir}/.. - 3.4.0 + 3.4.1 From 71e0125f3f938474e76c4a20b94f02cc2bdb14ca Mon Sep 17 00:00:00 2001 From: Zahraa Chreim Date: Tue, 11 Mar 2025 16:02:03 +0200 Subject: [PATCH 575/632] Fix invalid cast in DOIOrganiser exception handling --- .../dspace/identifier/doi/DOIOrganiser.java | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index fc978d3813fb..bc73cf8dcf11 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -448,28 +448,28 @@ public void register(DOI doiRow, Filter filter) + " is successfully registered."); } } catch (IdentifierException ex) { + String message; if (!(ex instanceof DOIIdentifierException)) { - LOG.error("It wasn't possible to register this identifier: " - + DOI.SCHEME + doiRow.getDoi() - + " online. ", ex); + message = "It wasn't possible to register this identifier: " + + DOI.SCHEME + doiRow.getDoi() + + " online. "; + } else { + DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; + message = "It wasn't possible to register this identifier : " + + DOI.SCHEME + doiRow.getDoi() + + " online. Exceptions code: " + + DOIIdentifierException.codeToString(doiIdentifierException.getCode()); } - DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; - try { sendAlertMail("Register", dso, DOI.SCHEME + doiRow.getDoi(), - doiIdentifierException.codeToString(doiIdentifierException - .getCode())); + message); } catch (IOException ioe) { LOG.error("Couldn't send mail", ioe); } - LOG.error("It wasn't possible to register this identifier : " - + DOI.SCHEME + doiRow.getDoi() - + " online. Exceptions code: " - + doiIdentifierException - .codeToString(doiIdentifierException.getCode()), ex); + LOG.error(message, ex); if (!quiet) { System.err.println("It wasn't possible to register this identifier: " @@ -541,27 +541,27 @@ public void reserve(DOI doiRow, Filter filter) { System.out.println("This identifier : " + DOI.SCHEME + doiRow.getDoi() + " is successfully reserved."); } } catch (IdentifierException ex) { + String message; if (!(ex instanceof DOIIdentifierException)) { - LOG.error("It wasn't possible to register this identifier : " - + DOI.SCHEME + doiRow.getDoi() - + " online. ", ex); + message = "It wasn't possible to register this identifier : " + + DOI.SCHEME + doiRow.getDoi() + + " online. "; + } else { + DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; + message = "It wasn't possible to reserve the identifier online. " + + " Exceptions code: " + + DOIIdentifierException.codeToString(doiIdentifierException.getCode()); } - DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; - try { sendAlertMail("Reserve", dso, DOI.SCHEME + doiRow.getDoi(), - DOIIdentifierException.codeToString( - doiIdentifierException.getCode())); + message); } catch (IOException ioe) { LOG.error("Couldn't send mail", ioe); } - LOG.error("It wasn't possible to reserve the identifier online. " - + " Exceptions code: " - + DOIIdentifierException - .codeToString(doiIdentifierException.getCode()), ex); + LOG.error(message, ex); if (!quiet) { System.err.println("It wasn't possible to reserve this identifier: " + DOI.SCHEME + doiRow.getDoi()); @@ -606,27 +606,27 @@ public void update(DOI doiRow) { + doiRow.getDoi() + "."); } } catch (IdentifierException ex) { + String message; if (!(ex instanceof DOIIdentifierException)) { - LOG.error("Registering DOI {} for object {}: the registrar returned an error.", - doiRow.getDoi(), dso.getID(), ex); + message = String.format("Registering DOI %s for object %s: the registrar returned an error.", + doiRow.getDoi(), dso.getID()); + } else { + DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; + message = "It wasn't possible to update this identifier: " + + DOI.SCHEME + doiRow.getDoi() + + " Exceptions code: " + + DOIIdentifierException.codeToString(doiIdentifierException.getCode()); } - DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; - try { sendAlertMail("Update", dso, DOI.SCHEME + doiRow.getDoi(), - doiIdentifierException.codeToString(doiIdentifierException - .getCode())); + message); } catch (IOException ioe) { LOG.error("Couldn't send mail", ioe); } - LOG.error("It wasn't possible to update this identifier: " - + DOI.SCHEME + doiRow.getDoi() - + " Exceptions code: " - + doiIdentifierException - .codeToString(doiIdentifierException.getCode()), ex); + LOG.error(message, ex); if (!quiet) { System.err.println("It wasn't possible to update this identifier: " + DOI.SCHEME + doiRow.getDoi()); @@ -830,4 +830,4 @@ private void setQuiet() { this.quiet = true; } -} \ No newline at end of file +} From 17b93c5c1527122b48f08e7885c3ea553416d860 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 22:47:15 +0000 Subject: [PATCH 576/632] Bump org.apache.httpcomponents.client5:httpclient5 from 5.4.4 to 5.5 Bumps [org.apache.httpcomponents.client5:httpclient5](https://github.com/apache/httpcomponents-client) from 5.4.4 to 5.5. - [Changelog](https://github.com/apache/httpcomponents-client/blob/master/RELEASE_NOTES.txt) - [Commits](https://github.com/apache/httpcomponents-client/compare/rel/v5.4.4...rel/v5.5) --- updated-dependencies: - dependency-name: org.apache.httpcomponents.client5:httpclient5 dependency-version: '5.5' dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 3efef6469971..47afbfd1374e 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -590,7 +590,7 @@ org.apache.httpcomponents.client5 httpclient5 - 5.4.4 + 5.5 test From 2d9d44a768edf0f6a328aa434e5acdf7384c8aac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 22:47:34 +0000 Subject: [PATCH 577/632] Bump org.xmlunit:xmlunit-core from 2.10.0 to 2.10.2 Bumps [org.xmlunit:xmlunit-core](https://github.com/xmlunit/xmlunit) from 2.10.0 to 2.10.2. - [Release notes](https://github.com/xmlunit/xmlunit/releases) - [Changelog](https://github.com/xmlunit/xmlunit/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/xmlunit/xmlunit/compare/v2.10.0...v2.10.2) --- updated-dependencies: - dependency-name: org.xmlunit:xmlunit-core dependency-version: 2.10.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index a7ecdb5ef5f9..e476e8508d76 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -785,7 +785,7 @@ org.xmlunit xmlunit-core - 2.10.0 + 2.10.2 test From ea3dc29852353e8d900fc571bc6b69159f69c38e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 16:25:13 +0000 Subject: [PATCH 578/632] Bump the spring group across 1 directory with 25 updates Bumps the spring group with 25 updates in the / directory: | Package | From | To | | --- | --- | --- | | [org.springframework:spring-orm](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-beans](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-aop](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-context-support](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-tx](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-jdbc](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-expression](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework:spring-test](https://github.com/spring-projects/spring-framework) | `6.2.6` | `6.2.7` | | [org.springframework.boot:spring-boot-starter-test](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-tomcat](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-maven-plugin](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-cache](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-thymeleaf](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-web](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-data-rest](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-security](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-aop](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-actuator](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.boot:spring-boot-starter-log4j2](https://github.com/spring-projects/spring-boot) | `3.4.5` | `3.5.0` | | [org.springframework.security:spring-security-test](https://github.com/spring-projects/spring-security) | `6.4.5` | `6.5.0` | Updates `org.springframework:spring-orm` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-core` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-beans` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-aop` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-context` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-context-support` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-tx` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-jdbc` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-web` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-webmvc` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-expression` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-test` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-core` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-beans` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-aop` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-context` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-context-support` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-tx` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-jdbc` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-web` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-webmvc` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-expression` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework:spring-test` from 6.2.6 to 6.2.7 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.6...v6.2.7) Updates `org.springframework.boot:spring-boot-starter-test` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-thymeleaf` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.security:spring-security-test` from 6.4.5 to 6.5.0 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/6.4.5...6.5.0) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-thymeleaf` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-web` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-security` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.4.5 to 3.5.0 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) --- updated-dependencies: - dependency-name: org.springframework:spring-orm dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-version: 6.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-test dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-thymeleaf dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.security:spring-security-test dependency-version: 6.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-thymeleaf dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index c455f1fb736b..59a2bb52cf0a 100644 --- a/pom.xml +++ b/pom.xml @@ -19,9 +19,9 @@ 17 - 6.2.6 - 3.4.5 - 6.4.5 + 6.2.7 + 3.5.0 + 6.5.0 6.4.8.Final 8.0.1.Final 42.7.5 From 58da9a0ca83f62f43ec697f128051e2923d4c421 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 16:25:36 +0000 Subject: [PATCH 579/632] Bump commons-beanutils:commons-beanutils in the apache-commons group Bumps the apache-commons group with 1 update: commons-beanutils:commons-beanutils. Updates `commons-beanutils:commons-beanutils` from 1.10.1 to 1.11.0 --- updated-dependencies: - dependency-name: commons-beanutils:commons-beanutils dependency-version: 1.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c455f1fb736b..ef97573f26ed 100644 --- a/pom.xml +++ b/pom.xml @@ -1468,7 +1468,7 @@ commons-beanutils commons-beanutils - 1.10.1 + 1.11.0 commons-cli From 140a6f64a962cbcadea9f5bbd7d3d1e163acb42b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 16:26:12 +0000 Subject: [PATCH 580/632] Bump org.postgresql:postgresql from 42.7.5 to 42.7.6 Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.5 to 42.7.6. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.5...REL42.7.6) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-version: 42.7.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c455f1fb736b..8105a8a2c053 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 6.4.5 6.4.8.Final 8.0.1.Final - 42.7.5 + 42.7.6 10.22.0 8.11.4 From 1506fbe307a115a3f443516cc215779d74d44a89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 02:25:11 +0000 Subject: [PATCH 581/632] Bump com.opencsv:opencsv from 5.11 to 5.11.1 Bumps com.opencsv:opencsv from 5.11 to 5.11.1. --- updated-dependencies: - dependency-name: com.opencsv:opencsv dependency-version: 5.11.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index e476e8508d76..154468aed5f0 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -772,7 +772,7 @@ com.opencsv opencsv - 5.11 + 5.11.1 From f04c116b07fdab0eb7ff9ddac88c81fc89d27449 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 2 Jun 2025 09:16:27 -0500 Subject: [PATCH 582/632] Alphabetize importers by service name --- .../config/spring/api/external-services.xml | 241 ++++++++++-------- 1 file changed, 129 insertions(+), 112 deletions(-) diff --git a/dspace/config/spring/api/external-services.xml b/dspace/config/spring/api/external-services.xml index e3a842efa094..c349a3f9307f 100644 --- a/dspace/config/spring/api/external-services.xml +++ b/dspace/config/spring/api/external-services.xml @@ -7,72 +7,75 @@ - - - - - - - - - + + + + + - Journal + Publication + none - - - - - - - - - + + + + + + - Journal + Publication + none - - - - - - - - - + + + + + + - OrgUnit + Publication + none - - - - - - - + + + + + + - Person + Publication + none - - + + + + + + + + Publication + none + + - - - - + + + + + @@ -82,9 +85,10 @@ - - - + + + + @@ -94,9 +98,10 @@ - - - + + + + @@ -106,9 +111,9 @@ - - - + + + @@ -118,6 +123,7 @@ + @@ -128,21 +134,28 @@ - - - - + + + + + + + - Publication - none + Person - - - + + + + + + + + @@ -164,21 +177,23 @@ - - - - + + + + + + - Publication - none + OrgUnit - - - + + + + @@ -188,21 +203,10 @@ - - - - - - - Publication - none - - - - - - - + + + + @@ -212,35 +216,46 @@ - - - - + + + + + + + + + + - Publication - none + Journal - - - - - + + + + + + + + + - Publication - none + Journal - - - - - - + + + + + + + + + OrgUnit @@ -248,9 +263,10 @@ - - - + + + + @@ -260,10 +276,11 @@ - - - - + + + + + Publication From 2fd984de62e1a8dc95d3b3af97f4b0bd765249c6 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Tue, 3 Jun 2025 13:11:42 +0200 Subject: [PATCH 583/632] 131448: Fixed QAEventMatcher#matchQAEventNotifyEntry sometimes failing when your default local uses a comma as a decimal separator You can view your default decimal separator using new DecimalFormatSymbols(Locale.getDefault()).getDecimalSeparator() (cherry picked from commit d74c3bd9cd3082b05cf82ba6379d25880e28ecd9) --- .../test/java/org/dspace/app/rest/matcher/QAEventMatcher.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/QAEventMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/QAEventMatcher.java index 8eb569468d4b..032696b1df00 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/QAEventMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/QAEventMatcher.java @@ -77,10 +77,11 @@ public static Matcher matchQAEventEntry(QAEvent event) { public static Matcher matchQAEventNotifyEntry(QAEvent event) { try { ObjectMapper jsonMapper = new JsonMapper(); + DecimalFormat decimalFormat = new DecimalFormat("0.000", new DecimalFormatSymbols(Locale.ENGLISH)); return allOf(hasJsonPath("$.id", is(event.getEventId())), hasJsonPath("$.originalId", is(event.getOriginalId())), hasJsonPath("$.title", is(event.getTitle())), - hasJsonPath("$.trust", is(new DecimalFormat("0.000").format(event.getTrust()))), + hasJsonPath("$.trust", is(decimalFormat.format(event.getTrust()))), hasJsonPath("$.status", Matchers.equalToIgnoringCase(event.getStatus())), hasJsonPath("$.message", matchMessage(event.getTopic(), jsonMapper.readValue(event.getMessage(), From 86c001cb0e721f5ee5006fb4790ab9f2c43e7c5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:25:53 +0000 Subject: [PATCH 584/632] Bump the hibernate group across 1 directory with 2 updates Bumps the hibernate group with 2 updates in the / directory: [org.hibernate.validator:hibernate-validator](https://github.com/hibernate/hibernate-validator) and [org.hibernate.validator:hibernate-validator-cdi](https://github.com/hibernate/hibernate-validator). Updates `org.hibernate.validator:hibernate-validator` from 8.0.1.Final to 8.0.2.Final - [Changelog](https://github.com/hibernate/hibernate-validator/blob/8.0.2.Final/changelog.txt) - [Commits](https://github.com/hibernate/hibernate-validator/compare/8.0.1.Final...8.0.2.Final) Updates `org.hibernate.validator:hibernate-validator-cdi` from 8.0.1.Final to 8.0.2.Final - [Changelog](https://github.com/hibernate/hibernate-validator/blob/8.0.2.Final/changelog.txt) - [Commits](https://github.com/hibernate/hibernate-validator/compare/8.0.1.Final...8.0.2.Final) Updates `org.hibernate.validator:hibernate-validator-cdi` from 8.0.1.Final to 8.0.2.Final - [Changelog](https://github.com/hibernate/hibernate-validator/blob/8.0.2.Final/changelog.txt) - [Commits](https://github.com/hibernate/hibernate-validator/compare/8.0.1.Final...8.0.2.Final) --- updated-dependencies: - dependency-name: org.hibernate.validator:hibernate-validator dependency-version: 8.0.2.Final dependency-type: direct:production update-type: version-update:semver-patch dependency-group: hibernate - dependency-name: org.hibernate.validator:hibernate-validator-cdi dependency-version: 8.0.2.Final dependency-type: direct:production update-type: version-update:semver-patch dependency-group: hibernate - dependency-name: org.hibernate.validator:hibernate-validator-cdi dependency-version: 8.0.2.Final dependency-type: direct:production update-type: version-update:semver-patch dependency-group: hibernate ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71886500ce50..b4b363e58e08 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 3.5.0 6.5.0 6.4.8.Final - 8.0.1.Final + 8.0.2.Final 42.7.6 10.22.0 8.11.4 From 7774e9d35dfbc8f62ca90da13561fef59f503aee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:26:09 +0000 Subject: [PATCH 585/632] Bump org.apache.maven.plugins:maven-clean-plugin Bumps the build-tools group with 1 update: [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin). Updates `org.apache.maven.plugins:maven-clean-plugin` from 3.4.1 to 3.5.0 - [Release notes](https://github.com/apache/maven-clean-plugin/releases) - [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.4.1...maven-clean-plugin-3.5.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-clean-plugin dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71886500ce50..ca708f5f60f0 100644 --- a/pom.xml +++ b/pom.xml @@ -329,7 +329,7 @@ maven-clean-plugin - 3.4.1 + 3.5.0 From c24011144a089f1814be63d54c77bf066a62e824 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:26:28 +0000 Subject: [PATCH 586/632] Bump bouncycastle.version from 1.80 to 1.81 Bumps `bouncycastle.version` from 1.80 to 1.81. Updates `org.bouncycastle:bcpkix-jdk18on` from 1.80 to 1.81 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) Updates `org.bouncycastle:bcprov-jdk18on` from 1.80 to 1.81 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) Updates `org.bouncycastle:bcutil-jdk18on` from 1.80 to 1.81 - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) --- updated-dependencies: - dependency-name: org.bouncycastle:bcpkix-jdk18on dependency-version: '1.81' dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.bouncycastle:bcprov-jdk18on dependency-version: '1.81' dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.bouncycastle:bcutil-jdk18on dependency-version: '1.81' dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71886500ce50..95de239dc9f4 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 2.0.17 2.9.4 - 1.80 + 1.81 8.0.1 3.1.10 From e44aa3a34aed7888275be47a816b710cdc8865e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:26:36 +0000 Subject: [PATCH 587/632] Bump org.checkerframework:checker-qual from 3.49.3 to 3.49.4 Bumps [org.checkerframework:checker-qual](https://github.com/typetools/checker-framework) from 3.49.3 to 3.49.4. - [Release notes](https://github.com/typetools/checker-framework/releases) - [Changelog](https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/typetools/checker-framework/compare/checker-framework-3.49.3...checker-framework-3.49.4) --- updated-dependencies: - dependency-name: org.checkerframework:checker-qual dependency-version: 3.49.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71886500ce50..996945f74f4b 100644 --- a/pom.xml +++ b/pom.xml @@ -1350,7 +1350,7 @@ org.checkerframework checker-qual - 3.49.3 + 3.49.4 From 162e3c31a52001ec9f0230cac2382ca3e23d91dc Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 9 Apr 2025 17:06:43 +0200 Subject: [PATCH 592/632] 129944: Introduce custom abstract xpath contributor for pubmed to respect their labelled structure - modify IT for it (cherry picked from commit 28bc4970b7a5471f164d400a1bbd3e560b8e3e30) --- .../PubmedAbstractMetadatumContributor.java | 67 +++++++++++++++++++ .../PubmedImportMetadataSourceServiceIT.java | 64 ++++++++---------- .../app/rest/pubmedimport-search-test.xml | 4 +- .../config/spring/api/pubmed-integration.xml | 2 +- 4 files changed, 100 insertions(+), 37 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedAbstractMetadatumContributor.java diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedAbstractMetadatumContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedAbstractMetadatumContributor.java new file mode 100644 index 000000000000..727d6b92ae35 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/contributor/PubmedAbstractMetadatumContributor.java @@ -0,0 +1,67 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.importer.external.pubmed.metadatamapping.contributor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.dspace.importer.external.metadatamapping.MetadatumDTO; +import org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor; +import org.jdom2.Element; +import org.jdom2.Namespace; +import org.jdom2.filter.Filters; +import org.jdom2.xpath.XPathExpression; +import org.jdom2.xpath.XPathFactory; + +/** + * This class is responsible for extracting the abstract from a PubMed XML document. + * It uses XPath to find the relevant elements and constructs a formatted string for the abstract, respecting + * PubMed's labelled abstract format, and including the labels in the output. + */ +public class PubmedAbstractMetadatumContributor extends SimpleXpathMetadatumContributor { + + @Override + public Collection contributeMetadata(Element t) { + List values = new LinkedList<>(); + + List namespaces = new ArrayList<>(); + for (String ns : prefixToNamespaceMapping.keySet()) { + namespaces.add(Namespace.getNamespace(prefixToNamespaceMapping.get(ns), ns)); + } + + XPathExpression xpath = XPathFactory.instance().compile(query, Filters.element(), null, namespaces); + List nodes = xpath.evaluate(t); + StringBuilder sb = new StringBuilder(); + + for (Element el : nodes) { + String label = el.getAttributeValue("Label"); + String text = el.getTextNormalize(); + + if (text == null || text.isEmpty()) { + continue; + } + + if (sb.length() > 0) { + sb.append("\n\n"); + } + + if (label != null && !label.equalsIgnoreCase("UNLABELLED")) { + sb.append(label).append(": "); + } + sb.append(text); + } + + String fullAbstract = sb.toString().trim(); + if (!fullAbstract.isEmpty()) { + values.add(metadataFieldMapping.toDCValue(field, fullAbstract)); + } + return values; + } +} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PubmedImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PubmedImportMetadataSourceServiceIT.java index 3b39d251216c..5cac853c07b5 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PubmedImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PubmedImportMetadataSourceServiceIT.java @@ -101,35 +101,34 @@ private ArrayList getRecords() { //define first record MetadatumDTO title = createMetadatumDTO("dc","title", null, "Teaching strategies of clinical reasoning in advanced nursing clinical practice: A scoping review."); - MetadatumDTO description1 = createMetadatumDTO("dc", "description", "abstract", "To report and synthesize" - + " the main strategies for teaching clinical reasoning described in the literature in the context of" - + " advanced clinical practice and promote new areas of research to improve the pedagogical approach" - + " to clinical reasoning in Advanced Practice Nursing."); - MetadatumDTO description2 = createMetadatumDTO("dc", "description", "abstract", "Clinical reasoning and" - + " clinical thinking are essential elements in the advanced nursing clinical practice decision-making" - + " process. The quality improvement of care is related to the development of those skills." - + " Therefore, it is crucial to optimize teaching strategies that can enhance the role of clinical" - + " reasoning in advanced clinical practice."); - MetadatumDTO description3 = createMetadatumDTO("dc", "description", "abstract", "A scoping review was" - + " conducted using the framework developed by Arksey and O'Malley as a research strategy." - + " Consistent with the nature of scoping reviews, a study protocol has been established."); - MetadatumDTO description4 = createMetadatumDTO("dc", "description", "abstract", "The studies included and" - + " analyzed in this scoping review cover from January 2016 to June 2022. Primary studies and secondary" - + " revision studies, published in biomedical databases, were selected, including qualitative ones." - + " Electronic databases used were: CINAHL, PubMed, Cochrane Library, Scopus, and OVID." - + " Three authors independently evaluated the articles for titles, abstracts, and full text."); - MetadatumDTO description5 = createMetadatumDTO("dc", "description", "abstract", "1433 articles were examined," - + " applying the eligibility and exclusion criteria 73 studies were assessed for eligibility," - + " and 27 were included in the scoping review. The results that emerged from the review were" - + " interpreted and grouped into three macro strategies (simulations-based education, art and visual" - + " thinking, and other learning approaches) and nineteen educational interventions."); - MetadatumDTO description6 = createMetadatumDTO("dc", "description", "abstract", "Among the different" - + " strategies, the simulations are the most used. Despite this, our scoping review reveals that is" - + " necessary to use different teaching strategies to stimulate critical thinking, improve diagnostic" - + " reasoning, refine clinical judgment, and strengthen decision-making. However, it is not possible to" - + " demonstrate which methodology is more effective in obtaining the learning outcomes necessary to" - + " acquire an adequate level of judgment and critical thinking. Therefore, it will be" - + " necessary to relate teaching methodologies with the skills developed."); + MetadatumDTO description1 = createMetadatumDTO("dc", "description", "abstract", + "AIM/OBJECTIVE: To report and synthesize the main strategies for teaching clinical reasoning " + + "described in the literature in the context of advanced clinical practice and promote new " + + "areas of research to improve the pedagogical approach to clinical reasoning in Advanced " + + "Practice Nursing.\n\nBACKGROUND: Clinical reasoning and clinical thinking are essential " + + "elements in the advanced nursing clinical practice decision-making process. The quality " + + "improvement of care is related to the development of those skills. Therefore, it is crucial " + + "to optimize teaching strategies that can enhance the role of clinical reasoning in advanced " + + "clinical practice.\n\nDESIGN: A scoping review was conducted using the framework developed " + + "by Arksey and O'Malley as a research strategy. Consistent with the nature of scoping reviews" + + ", a study protocol has been established.\n\nMETHODS: The studies included and analyzed in " + + "this scoping review cover from January 2016 to June 2022. Primary studies and secondary " + + "revision studies, published in biomedical databases, were selected, including qualitative " + + "ones. Electronic databases used were: CINAHL, PubMed, Cochrane Library, Scopus, and OVID. " + + "Three authors independently evaluated the articles for titles, abstracts, and full text.\n\n" + + "RESULTS: 1433 articles were examined, applying the eligibility and exclusion criteria 73 " + + "studies were assessed for eligibility, and 27 were included in the scoping review. The " + + "results that emerged from the review were interpreted and grouped into three macro " + + "strategies (simulations-based education, art and visual thinking, and other learning " + + "approaches) and nineteen educational interventions.\n\nCONCLUSIONS: Among the different " + + "strategies, the simulations are the most used. Despite this, our scoping review reveals " + + "that is necessary to use different teaching strategies to stimulate critical thinking, " + + "improve diagnostic reasoning, refine clinical judgment, and strengthen decision-making. " + + "However, it is not possible to demonstrate which methodology is more effective in obtaining " + + "the learning outcomes necessary to acquire an adequate level of judgment and critical " + + "thinking. Therefore, it will be necessary to relate teaching methodologies with the skills " + + "developed.\n\nAn unlabeled section of an abstract.\n\nAn abstract section with no attributes" + + " at all, concerning."); MetadatumDTO identifierOther = createMetadatumDTO("dc", "identifier", "other", "36708638"); MetadatumDTO author1 = createMetadatumDTO("dc", "contributor", "author", "Giuffrida, Silvia"); MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "Silano, Verdiana"); @@ -148,11 +147,6 @@ private ArrayList getRecords() { metadatums.add(title); metadatums.add(description1); - metadatums.add(description2); - metadatums.add(description3); - metadatums.add(description4); - metadatums.add(description5); - metadatums.add(description6); metadatums.add(identifierOther); metadatums.add(author1); metadatums.add(author2); @@ -210,4 +204,4 @@ private ArrayList getRecords2() { return records; } -} \ No newline at end of file +} diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/pubmedimport-search-test.xml b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/pubmedimport-search-test.xml index 666fb1e7d550..6af527246900 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/pubmedimport-search-test.xml +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/pubmedimport-search-test.xml @@ -41,6 +41,8 @@ The studies included and analyzed in this scoping review cover from January 2016 to June 2022. Primary studies and secondary revision studies, published in biomedical databases, were selected, including qualitative ones. Electronic databases used were: CINAHL, PubMed, Cochrane Library, Scopus, and OVID. Three authors independently evaluated the articles for titles, abstracts, and full text. 1433 articles were examined, applying the eligibility and exclusion criteria 73 studies were assessed for eligibility, and 27 were included in the scoping review. The results that emerged from the review were interpreted and grouped into three macro strategies (simulations-based education, art and visual thinking, and other learning approaches) and nineteen educational interventions. Among the different strategies, the simulations are the most used. Despite this, our scoping review reveals that is necessary to use different teaching strategies to stimulate critical thinking, improve diagnostic reasoning, refine clinical judgment, and strengthen decision-making. However, it is not possible to demonstrate which methodology is more effective in obtaining the learning outcomes necessary to acquire an adequate level of judgment and critical thinking. Therefore, it will be necessary to relate teaching methodologies with the skills developed. + An unlabeled section of an abstract. + An abstract section with no attributes at all, concerning. Copyright © 2023 Elsevier Ltd. All rights reserved. @@ -191,4 +193,4 @@ - \ No newline at end of file + diff --git a/dspace/config/spring/api/pubmed-integration.xml b/dspace/config/spring/api/pubmed-integration.xml index adec4456ea03..f488327789f9 100644 --- a/dspace/config/spring/api/pubmed-integration.xml +++ b/dspace/config/spring/api/pubmed-integration.xml @@ -57,7 +57,7 @@ - + From 64d1c88249b5e1d49d0392b1cdd49b5b90fc26f7 Mon Sep 17 00:00:00 2001 From: DSpace Bot <68393067+dspace-bot@users.noreply.github.com> Date: Wed, 11 Jun 2025 07:21:52 -0500 Subject: [PATCH 593/632] [Port dspace-8_x] Optimization of Solr Queries: Transition to Filter Queries (#10888) * use filter query instead of generic query (cherry picked from commit f2417feeca653aefdd7a201460afe3d9429bacae) * use filter query instead of generic query (cherry picked from commit d83a2525ad96e9d4cb935481c505537bdee0cae5) * use filter query instead of generic query (cherry picked from commit f3a976107e2afef5c2d0fb19e580bbbd754acc14) * remove obsolete comment (cherry picked from commit 3ee2dbcc56c157499c6db96cc3b8e90c2ae47e8f) * use filter query instead of generic query (cherry picked from commit 318afc769a6f0958c795da7506b25a28cf298f09) * add static imports (cherry picked from commit 8ad19c42df754daa6ed70c6e9d1c9146e72c0b32) * move static import to the top of the import block (cherry picked from commit b85585c34e528ce2165e25a0cf23351283360ac7) * move static imports to the top of the import block (cherry picked from commit 4b446e24a068027e8cf3c3935ad256f39b4b65ef) --------- Co-authored-by: Sascha Szott --- .../java/org/dspace/app/sitemap/GenerateSitemaps.java | 11 ++++++++--- .../app/solrdatabaseresync/SolrDatabaseResyncCli.java | 3 ++- .../main/java/org/dspace/browse/SolrBrowseDAO.java | 9 +++++++-- .../java/org/dspace/discovery/SolrSearchCore.java | 8 +++++--- .../org/dspace/statistics/SolrLoggerServiceImpl.java | 1 - 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/sitemap/GenerateSitemaps.java b/dspace-api/src/main/java/org/dspace/app/sitemap/GenerateSitemaps.java index 90962d12aa75..41b0b0f6b3dd 100644 --- a/dspace-api/src/main/java/org/dspace/app/sitemap/GenerateSitemaps.java +++ b/dspace-api/src/main/java/org/dspace/app/sitemap/GenerateSitemaps.java @@ -7,6 +7,8 @@ */ package org.dspace.app.sitemap; +import static org.dspace.discovery.SearchUtils.RESOURCE_TYPE_FIELD; + import java.io.File; import java.io.IOException; import java.sql.SQLException; @@ -189,7 +191,8 @@ public static void generateSitemaps(boolean makeHTMLMap, boolean makeSitemapOrg) try { DiscoverQuery discoveryQuery = new DiscoverQuery(); discoveryQuery.setMaxResults(PAGE_SIZE); - discoveryQuery.setQuery("search.resourcetype:Community"); + discoveryQuery.setQuery("*:*"); + discoveryQuery.addFilterQueries(RESOURCE_TYPE_FIELD + ":Community"); do { discoveryQuery.setStart(offset); DiscoverResult discoverResult = searchService.search(c, discoveryQuery); @@ -213,7 +216,8 @@ public static void generateSitemaps(boolean makeHTMLMap, boolean makeSitemapOrg) offset = 0; discoveryQuery = new DiscoverQuery(); discoveryQuery.setMaxResults(PAGE_SIZE); - discoveryQuery.setQuery("search.resourcetype:Collection"); + discoveryQuery.setQuery("*:*"); + discoveryQuery.addFilterQueries(RESOURCE_TYPE_FIELD + ":Collection"); do { discoveryQuery.setStart(offset); DiscoverResult discoverResult = searchService.search(c, discoveryQuery); @@ -237,7 +241,8 @@ public static void generateSitemaps(boolean makeHTMLMap, boolean makeSitemapOrg) offset = 0; discoveryQuery = new DiscoverQuery(); discoveryQuery.setMaxResults(PAGE_SIZE); - discoveryQuery.setQuery("search.resourcetype:Item"); + discoveryQuery.setQuery("*:*"); + discoveryQuery.addFilterQueries(RESOURCE_TYPE_FIELD + ":Item"); discoveryQuery.addSearchField("search.entitytype"); do { diff --git a/dspace-api/src/main/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncCli.java b/dspace-api/src/main/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncCli.java index aac42ce1acf9..0ce6b1a9ef3d 100644 --- a/dspace-api/src/main/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncCli.java +++ b/dspace-api/src/main/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncCli.java @@ -98,7 +98,8 @@ public void internalRun() throws Exception { private void performStatusUpdate(Context context) throws SearchServiceException, SolrServerException, IOException { SolrQuery solrQuery = new SolrQuery(); - solrQuery.setQuery(STATUS_FIELD + ":" + STATUS_FIELD_PREDB); + solrQuery.setQuery("*:*"); + solrQuery.addFilterQuery(STATUS_FIELD + ":" + STATUS_FIELD_PREDB); solrQuery.addFilterQuery(SearchUtils.RESOURCE_TYPE_FIELD + ":" + IndexableItem.TYPE); String dateRangeFilter = SearchUtils.LAST_INDEXED_FIELD + ":[* TO " + maxTime + "]"; logDebugAndOut("Date range filter used; " + dateRangeFilter); diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java index 14dab3e56174..a0a7725fa13a 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java +++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java @@ -7,6 +7,9 @@ */ package org.dspace.browse; +import static org.dspace.discovery.SearchUtils.RESOURCE_ID_FIELD; +import static org.dspace.discovery.SearchUtils.RESOURCE_TYPE_FIELD; + import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -308,8 +311,10 @@ public List doQuery() throws BrowseException { public String doMaxQuery(String column, String table, int itemID) throws BrowseException { DiscoverQuery query = new DiscoverQuery(); - query.setQuery("search.resourceid:" + itemID - + " AND search.resourcetype:" + IndexableItem.TYPE); + query.setQuery("*:*"); + query.addFilterQueries( + RESOURCE_ID_FIELD + ":" + itemID, + RESOURCE_TYPE_FIELD + ":" + IndexableItem.TYPE); query.setMaxResults(1); DiscoverResult resp = null; try { diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java b/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java index 6304f39a8ca9..57c56dc35348 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java @@ -88,9 +88,11 @@ protected void initSolr() { solrServer.setBaseURL(solrService); solrServer.setUseMultiPartPost(true); // Dummy/test query to search for Item (type=2) of ID=1 - SolrQuery solrQuery = new SolrQuery() - .setQuery(SearchUtils.RESOURCE_TYPE_FIELD + ":" + IndexableItem.TYPE + - " AND " + SearchUtils.RESOURCE_ID_FIELD + ":1"); + SolrQuery solrQuery = new SolrQuery(); + solrQuery.setQuery("*:*"); + solrQuery.addFilterQuery( + SearchUtils.RESOURCE_TYPE_FIELD + ":" + IndexableItem.TYPE, + SearchUtils.RESOURCE_ID_FIELD + ":1"); // Only return obj identifier fields in result doc solrQuery.setFields(SearchUtils.RESOURCE_TYPE_FIELD, SearchUtils.RESOURCE_ID_FIELD); solrServer.query(solrQuery, REQUEST_METHOD); diff --git a/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java b/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java index 9e5ba3256c0b..32de86744d13 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java @@ -1045,7 +1045,6 @@ public QueryResponse query(String query, String filterQuery, String facetField, return null; } - // System.out.println("QUERY"); SolrQuery solrQuery = new SolrQuery().setRows(rows).setQuery(query) .setFacetMinCount(facetMinCount); addAdditionalSolrYearCores(solrQuery); From 1c473dc1bac1ed9de04756c9f3112648089e294a Mon Sep 17 00:00:00 2001 From: DSpace Bot <68393067+dspace-bot@users.noreply.github.com> Date: Wed, 11 Jun 2025 07:27:13 -0500 Subject: [PATCH 594/632] [Port dspace-8_x] improve robustness of search in index field submit (use filter query) (#10891) * improve robustness of search in index field submit (use filter query) (cherry picked from commit a65ef008b74cac3a81c17bfd6ca44e095f6a3771) * fix checkstyle warnings (cherry picked from commit 183d5ca67113ea750a9de1a13413d34eac946169) * fix checkstyle warning (cherry picked from commit fe251f39e38dcdbba6ab3183a12fc5385c320b12) --------- Co-authored-by: Sascha Szott --- .../dspace/content/EntityTypeServiceImpl.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/EntityTypeServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/EntityTypeServiceImpl.java index b5b066d9c36f..7df892cd56f5 100644 --- a/dspace-api/src/main/java/org/dspace/content/EntityTypeServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/EntityTypeServiceImpl.java @@ -30,6 +30,7 @@ import org.dspace.core.Context; import org.dspace.discovery.SolrSearchCore; import org.dspace.discovery.indexobject.IndexableCollection; +import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.eperson.service.GroupService; import org.springframework.beans.factory.annotation.Autowired; @@ -124,24 +125,33 @@ public void delete(Context context,EntityType entityType) throws SQLException, A public List getSubmitAuthorizedTypes(Context context) throws SQLException, SolrServerException, IOException { List types = new ArrayList<>(); - StringBuilder query = new StringBuilder(); - org.dspace.eperson.EPerson currentUser = context.getCurrentUser(); + StringBuilder query = null; + EPerson currentUser = context.getCurrentUser(); if (!authorizeService.isAdmin(context)) { String userId = ""; if (currentUser != null) { userId = currentUser.getID().toString(); + query = new StringBuilder(); + query.append("submit:(e").append(userId); } - query.append("submit:(e").append(userId); + Set groups = groupService.allMemberGroupsSet(context, currentUser); for (Group group : groups) { - query.append(" OR g").append(group.getID()); + if (query == null) { + query = new StringBuilder(); + query.append("submit:(g"); + } else { + query.append(" OR g"); + } + query.append(group.getID()); } query.append(")"); - } else { - query.append("*:*"); } - SolrQuery sQuery = new SolrQuery(query.toString()); + SolrQuery sQuery = new SolrQuery("*:*"); + if (query != null) { + sQuery.addFilterQuery(query.toString()); + } sQuery.addFilterQuery("search.resourcetype:" + IndexableCollection.TYPE); sQuery.setRows(0); sQuery.addFacetField("search.entitytype"); From b75f8ec8c4542bf471313549e627360cb3e283a6 Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Sun, 13 Apr 2025 17:34:14 +0300 Subject: [PATCH 595/632] dspace-api: use static variable RESOURCE_TYPE_FIELD --- .../authorize/AuthorizeServiceImpl.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java index 932cd71744d4..b894bfa4b761 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java @@ -9,6 +9,7 @@ import static org.dspace.app.util.AuthorizeUtil.canCollectionAdminManageAccounts; import static org.dspace.app.util.AuthorizeUtil.canCommunityAdminManageAccounts; +import static org.dspace.discovery.SearchUtils.RESOURCE_TYPE_FIELD; import java.sql.SQLException; import java.util.ArrayList; @@ -736,7 +737,7 @@ public List getPoliciesActionFilterExceptRpType(Context c, DSpac */ @Override public boolean isCommunityAdmin(Context context) throws SQLException { - return performCheck(context, "search.resourcetype:" + IndexableCommunity.TYPE); + return performCheck(context, RESOURCE_TYPE_FIELD + ":" + IndexableCommunity.TYPE); } /** @@ -749,7 +750,7 @@ public boolean isCommunityAdmin(Context context) throws SQLException { */ @Override public boolean isCollectionAdmin(Context context) throws SQLException { - return performCheck(context, "search.resourcetype:" + IndexableCollection.TYPE); + return performCheck(context, RESOURCE_TYPE_FIELD + ":" + IndexableCollection.TYPE); } /** @@ -762,7 +763,7 @@ public boolean isCollectionAdmin(Context context) throws SQLException { */ @Override public boolean isItemAdmin(Context context) throws SQLException { - return performCheck(context, "search.resourcetype:" + IndexableItem.TYPE); + return performCheck(context, RESOURCE_TYPE_FIELD + ":" + IndexableItem.TYPE); } /** @@ -776,8 +777,8 @@ public boolean isItemAdmin(Context context) throws SQLException { @Override public boolean isComColAdmin(Context context) throws SQLException { return performCheck(context, - "(search.resourcetype:" + IndexableCommunity.TYPE + " OR search.resourcetype:" + - IndexableCollection.TYPE + ")"); + "(" + RESOURCE_TYPE_FIELD + ":" + IndexableCommunity.TYPE + " OR " + + RESOURCE_TYPE_FIELD + ":" + IndexableCollection.TYPE + ")"); } /** @@ -795,7 +796,7 @@ public List findAdminAuthorizedCommunity(Context context, String quer throws SearchServiceException, SQLException { List communities = new ArrayList<>(); query = formatCustomQuery(query); - DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" + + DiscoverResult discoverResult = getDiscoverResult(context, query + RESOURCE_TYPE_FIELD + ":" + IndexableCommunity.TYPE, offset, limit, null, null); for (IndexableObject solrCollections : discoverResult.getIndexableObjects()) { @@ -817,7 +818,7 @@ public List findAdminAuthorizedCommunity(Context context, String quer public long countAdminAuthorizedCommunity(Context context, String query) throws SearchServiceException, SQLException { query = formatCustomQuery(query); - DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" + + DiscoverResult discoverResult = getDiscoverResult(context, query + RESOURCE_TYPE_FIELD + ":" + IndexableCommunity.TYPE, null, null, null, null); return discoverResult.getTotalSearchResults(); @@ -842,7 +843,7 @@ public List findAdminAuthorizedCollection(Context context, String qu } query = formatCustomQuery(query); - DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" + + DiscoverResult discoverResult = getDiscoverResult(context, query + RESOURCE_TYPE_FIELD + ":" + IndexableCollection.TYPE, offset, limit, CollectionService.SOLR_SORT_FIELD, SORT_ORDER.asc); for (IndexableObject solrCollections : discoverResult.getIndexableObjects()) { @@ -864,7 +865,7 @@ public List findAdminAuthorizedCollection(Context context, String qu public long countAdminAuthorizedCollection(Context context, String query) throws SearchServiceException, SQLException { query = formatCustomQuery(query); - DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" + + DiscoverResult discoverResult = getDiscoverResult(context, query + RESOURCE_TYPE_FIELD + ":" + IndexableCollection.TYPE, null, null, null, null); return discoverResult.getTotalSearchResults(); From 4d67aec3bc5e3b9772fe007be7aad85f0dae042e Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Sun, 13 Apr 2025 17:35:55 +0300 Subject: [PATCH 596/632] dspace-api: do not request actual search hits in count-only query --- .../main/java/org/dspace/authorize/AuthorizeServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java index b894bfa4b761..f2692cf394fc 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java @@ -820,7 +820,7 @@ public long countAdminAuthorizedCommunity(Context context, String query) query = formatCustomQuery(query); DiscoverResult discoverResult = getDiscoverResult(context, query + RESOURCE_TYPE_FIELD + ":" + IndexableCommunity.TYPE, - null, null, null, null); + null, 0, null, null); return discoverResult.getTotalSearchResults(); } @@ -867,7 +867,7 @@ public long countAdminAuthorizedCollection(Context context, String query) query = formatCustomQuery(query); DiscoverResult discoverResult = getDiscoverResult(context, query + RESOURCE_TYPE_FIELD + ":" + IndexableCollection.TYPE, - null, null, null, null); + null, 0, null, null); return discoverResult.getTotalSearchResults(); } From 3d133727e97e87cee7f545618d1e65b68c855531 Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Sun, 13 Apr 2025 17:36:35 +0300 Subject: [PATCH 597/632] dspace-api: set search fields in Solr query only if we are interested in the actual search results --- .../org/dspace/discovery/SolrServiceImpl.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 3415e6b141c8..a5fa04b3dc04 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -861,16 +861,20 @@ protected SolrQuery resolveToSolrQuery(Context context, DiscoverQuery discoveryQ solrQuery.setQuery(query); - // Add any search fields to our query. This is the limited list - // of fields that will be returned in the solr result - for (String fieldName : discoveryQuery.getSearchFields()) { - solrQuery.addField(fieldName); - } - // Also ensure a few key obj identifier fields are returned with every query - solrQuery.addField(SearchUtils.RESOURCE_TYPE_FIELD); - solrQuery.addField(SearchUtils.RESOURCE_ID_FIELD); - solrQuery.addField(SearchUtils.RESOURCE_UNIQUE_ID); - solrQuery.addField(STATUS_FIELD); + if (discoveryQuery.getMaxResults() != 0) { + // set search fields in Solr query only if we are interested in the actual search results + + // Add any search fields to our query. This is the limited list + // of fields that will be returned in the solr result + for (String fieldName : discoveryQuery.getSearchFields()) { + solrQuery.addField(fieldName); + } + // Also ensure a few key obj identifier fields are returned with every query + solrQuery.addField(SearchUtils.RESOURCE_TYPE_FIELD); + solrQuery.addField(SearchUtils.RESOURCE_ID_FIELD); + solrQuery.addField(SearchUtils.RESOURCE_UNIQUE_ID); + solrQuery.addField(STATUS_FIELD); + } if (discoveryQuery.isSpellCheck()) { solrQuery.setParam(SpellingParams.SPELLCHECK_Q, query); From 1b122c1ab2dcdd1a89a078af828061518dfca99b Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Wed, 11 Jun 2025 15:43:10 -0400 Subject: [PATCH 598/632] Make POI record buffer size adjustable. --- .../mediafilter/TikaTextExtractionFilter.java | 18 ++++++++++++++---- dspace/config/dspace.cfg | 7 +++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java index b7a6063165b7..5728f4f42f48 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java @@ -18,6 +18,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.poi.util.IOUtils; import org.apache.tika.Tika; import org.apache.tika.exception.TikaException; import org.apache.tika.metadata.Metadata; @@ -37,6 +38,8 @@ public class TikaTextExtractionFilter extends MediaFilter { private final static Logger log = LogManager.getLogger(); + private static final int DEFAULT_MAX_CHARS = 100_000; + private static final int DEFAULT_MAX_ARRAY = 100_000_000; @Override public String getFilteredName(String oldFilename) { @@ -70,9 +73,12 @@ public InputStream getDestinationStream(Item currentItem, InputStream source, bo } // Not using temporary file. We'll use Tika's default in-memory parsing. - // Get maximum characters to extract. Default is 100,000 chars, which is also Tika's default setting. String extractedText; - int maxChars = configurationService.getIntProperty("textextractor.max-chars", 100000); + // Get maximum characters to extract. Default is 100,000 chars, which is also Tika's default setting. + int maxChars = configurationService.getIntProperty("textextractor.max-chars", DEFAULT_MAX_CHARS); + // Get maximum size of structure that Tika will try to buffer. + int maxArray = configurationService.getIntProperty("textextractor.max-array", DEFAULT_MAX_ARRAY); + IOUtils.setByteArrayMaxOverride(maxArray); try { // Use Tika to extract text from input. Tika will automatically detect the file type. Tika tika = new Tika(); @@ -80,13 +86,13 @@ public InputStream getDestinationStream(Item currentItem, InputStream source, bo extractedText = tika.parseToString(source); } catch (IOException e) { System.err.format("Unable to extract text from bitstream in Item %s%n", currentItem.getID().toString()); - e.printStackTrace(); + e.printStackTrace(System.err); log.error("Unable to extract text from bitstream in Item {}", currentItem.getID().toString(), e); throw e; } catch (OutOfMemoryError oe) { System.err.format("OutOfMemoryError occurred when extracting text from bitstream in Item %s. " + "You may wish to enable 'textextractor.use-temp-file'.%n", currentItem.getID().toString()); - oe.printStackTrace(); + oe.printStackTrace(System.err); log.error("OutOfMemoryError occurred when extracting text from bitstream in Item {}. " + "You may wish to enable 'textextractor.use-temp-file'.", currentItem.getID().toString(), oe); throw oe; @@ -167,6 +173,10 @@ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXExce } }); + ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); + int maxArray = configurationService.getIntProperty("textextractor.max-array", DEFAULT_MAX_ARRAY); + IOUtils.setByteArrayMaxOverride(maxArray); + AutoDetectParser parser = new AutoDetectParser(); Metadata metadata = new Metadata(); // parse our source InputStream using the above custom handler diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 7151fc6dc56b..67490dac3e6d 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -523,6 +523,13 @@ filter.org.dspace.app.mediafilter.PDFBoxThumbnail.inputFormats = Adobe PDF # text ("filter-media -f" ) and then reindex your site ("index-discovery -b"). #textextractor.use-temp-file = false +# Maximum size of a record buffer for text extraction. Set this if you are +# seeing RecordFormatException calling out excessive array length from +# 'dspace filter-media'. It is likely that you will need to increase the +# size of the Java heap if you greatly increase this value -- see JAVA_OPTS +# in 'bin/dspace' or 'bin/dspace/bat'. +#textextractor.max-array = 1000000 + # Custom settigns for ImageMagick Thumbnail Filters # ImageMagick and GhostScript must be installed on the server, set the path to ImageMagick and GhostScript executable # http://www.imagemagick.org/ From 88d8a54939499942920531a99556685132271651 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 03:15:41 +0000 Subject: [PATCH 599/632] Bump the fasterxml group with 4 updates Bumps the fasterxml group with 4 updates: [com.fasterxml.jackson.core:jackson-annotations](https://github.com/FasterXML/jackson), [com.fasterxml.jackson.core:jackson-core](https://github.com/FasterXML/jackson-core), [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) and com.fasterxml.jackson.datatype:jackson-datatype-jsr310. Updates `com.fasterxml.jackson.core:jackson-annotations` from 2.19.0 to 2.19.1 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.19.0 to 2.19.1 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.19.0...jackson-core-2.19.1) Updates `com.fasterxml.jackson.core:jackson-core` from 2.19.0 to 2.19.1 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.19.0...jackson-core-2.19.1) Updates `com.fasterxml.jackson.core:jackson-databind` from 2.19.0 to 2.19.1 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.19.0 to 2.19.1 Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.19.0 to 2.19.1 --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 118595efacc6..9d1d709e5501 100644 --- a/pom.xml +++ b/pom.xml @@ -31,8 +31,8 @@ 3.10.8 2.38.0 - 2.19.0 - 2.19.0 + 2.19.1 + 2.19.1 2.1.1 4.0.2 4.0.5 From 6df9e2dbfdafd50505b1ac33d1362aed070fa215 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 03:17:49 +0000 Subject: [PATCH 600/632] Bump org.postgresql:postgresql from 42.7.6 to 42.7.7 Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.6 to 42.7.7. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.6...REL42.7.7) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-version: 42.7.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 118595efacc6..00068da716a2 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 6.5.0 6.4.8.Final 8.0.2.Final - 42.7.6 + 42.7.7 10.22.0 8.11.4 From e9963b23532177d2abaece462bcaac3f62da0141 Mon Sep 17 00:00:00 2001 From: Mykhaylo Boychuk Date: Fri, 24 Jan 2025 01:21:25 +0100 Subject: [PATCH 601/632] [DURACOM-318] add new ITs for ResourcePolicy (cherry picked from commit d78d4f00d94ef0d4b147031b075b8df1e8896fe4) (cherry picked from commit 98c2b9942167890d24b71f5c32e6918ac2eee7a6) --- .../rest/ResourcePolicyRestRepositoryIT.java | 547 ++++++++++++++++++ 1 file changed, 547 insertions(+) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java index bc6f142abebb..5570332b16b2 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java @@ -23,6 +23,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.text.SimpleDateFormat; +import java.io.InputStream; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -32,6 +35,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.ws.rs.core.MediaType; +import org.apache.commons.codec.CharEncoding; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.matcher.ResourcePolicyMatcher; import org.dspace.app.rest.model.ResourcePolicyRest; @@ -43,12 +48,14 @@ import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.ResourcePolicyService; +import org.dspace.builder.BitstreamBuilder; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EPersonBuilder; import org.dspace.builder.GroupBuilder; import org.dspace.builder.ItemBuilder; import org.dspace.builder.ResourcePolicyBuilder; +import org.dspace.content.Bitstream; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.Item; @@ -1215,6 +1222,376 @@ public void createOneForbiddenTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(0))); } + @Test + public void createPolicyByCollectionAdminTest() throws Exception { + context.turnOffAuthorisationSystem(); + EPerson colAdmin = EPersonBuilder.createEPerson(context) + .withEmail("colAdmin@mail.test") + .withPassword(password) + .build(); + + EPerson colAdmin2 = EPersonBuilder.createEPerson(context) + .withEmail("colAdmin2@mail.test") + .withPassword(password) + .build(); + + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("colSubmitter@mail.test") + .withPassword(password) + .build(); + + Community community = CommunityBuilder.createCommunity(context) + .withName("My top commynity") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("My collection") + .withAdminGroup(colAdmin) + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + CollectionBuilder.createCollection(context, community) + .withName("My Second Collection") + .withAdminGroup(colAdmin2) + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + Item publication = ItemBuilder.createItem(context, collection) + .withTitle("Public item") + .build(); + + //Add a bitstream to a publication + Bitstream bitstream = null; + try (InputStream is = IOUtils.toInputStream("ThisIsSomeDummyText", CharEncoding.UTF_8)) { + bitstream = BitstreamBuilder.createBitstream(context, publication, is) + .withName("Bitstream") + .withDescription("description") + .withMimeType("text/plain") + .build(); + } + context.restoreAuthSystemState(); + + ResourcePolicyRest resourcePolicyRest = new ResourcePolicyRest(); + resourcePolicyRest.setPolicyType(ResourcePolicy.TYPE_CUSTOM); + resourcePolicyRest.setAction(Constants.actionText[Constants.WRITE]); + resourcePolicyRest.setName("Test for collection admin"); + + String authcolAdminToken = getAuthToken(colAdmin.getEmail(), password); + String authcolAdmin2Token = getAuthToken(colAdmin2.getEmail(), password); + String authSubmitterToken = getAuthToken(submitter.getEmail(), password); + AtomicReference idRef = new AtomicReference(); + + try { + // submitter can't create policy + getClient(authSubmitterToken).perform(post("/api/authz/resourcepolicies") + .content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest)) + .param("resource", bitstream.getID().toString()) + .param("eperson", submitter.getID().toString()) + .param("projections", "full") + .contentType(contentType)) + .andExpect(status().isForbidden()); + + // other collection admin can't create policy for other collection + getClient(authcolAdmin2Token).perform(post("/api/authz/resourcepolicies") + .content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest)) + .param("resource", bitstream.getID().toString()) + .param("eperson", submitter.getID().toString()) + .param("projections", "full") + .contentType(contentType)) + .andExpect(status().isForbidden()); + + // create policy for submitter by collection admin + getClient(authcolAdminToken).perform(post("/api/authz/resourcepolicies") + .content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest)) + .param("resource", bitstream.getID().toString()) + .param("eperson", submitter.getID().toString()) + .param("projections", "full") + .contentType(contentType)) + .andExpect(status().isCreated()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$", ResourcePolicyMatcher.matchFullEmbeds())) + .andExpect(jsonPath("$", Matchers.allOf( + hasJsonPath("$.name", is(resourcePolicyRest.getName())), + hasJsonPath("$.description", is(resourcePolicyRest.getDescription())), + hasJsonPath("$.policyType", is(resourcePolicyRest.getPolicyType())), + hasJsonPath("$.action", is(resourcePolicyRest.getAction())), + hasJsonPath("$.startDate", is(resourcePolicyRest.getStartDate())), + hasJsonPath("$.endDate", is(resourcePolicyRest.getEndDate())), + hasJsonPath("$.type", is(resourcePolicyRest.getType()))))) + .andDo(result -> idRef.set(read(result.getResponse().getContentAsString(), "$.id"))); + + // submitter can see own policy + getClient(authSubmitterToken).perform(get("/api/authz/resourcepolicies/" + idRef.get())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get()))); + + // collection admin can see that policy + getClient(authcolAdminToken).perform(get("/api/authz/resourcepolicies/" + idRef.get())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get()))); + } finally { + ResourcePolicyBuilder.delete(idRef.get()); + } + } + + @Test + public void createPolicyBySubCommunityAdminTest() throws Exception { + context.turnOffAuthorisationSystem(); + EPerson comAdmin = EPersonBuilder.createEPerson(context) + .withEmail("comAdmin@mail.test") + .withPassword(password) + .build(); + + EPerson comAdmin2 = EPersonBuilder.createEPerson(context) + .withEmail("comAdmin2@mail.test") + .withPassword(password) + .build(); + + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("colSubmitter@mail.test") + .withPassword(password) + .build(); + + Community community = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("My First Commynity") + .withAdminGroup(comAdmin) + .build(); + + Community community2 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("My Second Commynity") + .withAdminGroup(comAdmin2) + .build(); + + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("My collection") + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + CollectionBuilder.createCollection(context, community2) + .withName("My Second Collection") + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + Item publication = ItemBuilder.createItem(context, collection) + .withTitle("Public item") + .build(); + + context.restoreAuthSystemState(); + + ResourcePolicyRest resourcePolicyRest = new ResourcePolicyRest(); + resourcePolicyRest.setPolicyType(ResourcePolicy.TYPE_CUSTOM); + resourcePolicyRest.setAction(Constants.actionText[Constants.WRITE]); + resourcePolicyRest.setName("Test for collection admin"); + + String authcomAdminToken = getAuthToken(comAdmin.getEmail(), password); + String authcomAdmin2Token = getAuthToken(comAdmin2.getEmail(), password); + String authSubmitterToken = getAuthToken(submitter.getEmail(), password); + AtomicReference idRef = new AtomicReference(); + + try { + // submitter can't create policy + getClient(authSubmitterToken).perform(post("/api/authz/resourcepolicies") + .content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest)) + .param("resource", publication.getID().toString()) + .param("eperson", submitter.getID().toString()) + .param("projections", "full") + .contentType(contentType)) + .andExpect(status().isForbidden()); + + // other Community admin can't create policy for collections into other Community + getClient(authcomAdmin2Token).perform(post("/api/authz/resourcepolicies") + .content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest)) + .param("resource", publication.getID().toString()) + .param("eperson", submitter.getID().toString()) + .param("projections", "full") + .contentType(contentType)) + .andExpect(status().isForbidden()); + + // create policy for submitter by Community admin + getClient(authcomAdminToken).perform(post("/api/authz/resourcepolicies") + .content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest)) + .param("resource", publication.getID().toString()) + .param("eperson", submitter.getID().toString()) + .param("projections", "full") + .contentType(contentType)) + .andExpect(status().isCreated()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$", ResourcePolicyMatcher.matchFullEmbeds())) + .andExpect(jsonPath("$", Matchers.allOf( + hasJsonPath("$.name", is(resourcePolicyRest.getName())), + hasJsonPath("$.description", is(resourcePolicyRest.getDescription())), + hasJsonPath("$.policyType", is(resourcePolicyRest.getPolicyType())), + hasJsonPath("$.action", is(resourcePolicyRest.getAction())), + hasJsonPath("$.startDate", is(resourcePolicyRest.getStartDate())), + hasJsonPath("$.endDate", is(resourcePolicyRest.getEndDate())), + hasJsonPath("$.type", is(resourcePolicyRest.getType()))))) + .andDo(result -> idRef.set(read(result.getResponse().getContentAsString(), "$.id"))); + + // submitter can see own policy + getClient(authSubmitterToken).perform(get("/api/authz/resourcepolicies/" + idRef.get())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get()))); + + // community admin can see policies of own collections/items + getClient(authcomAdminToken).perform(get("/api/authz/resourcepolicies/" + idRef.get())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get()))); + + // Other community admin can't see policies of other community's collections/items + getClient(authcomAdmin2Token).perform(get("/api/authz/resourcepolicies/" + idRef.get())) + .andExpect(status().isForbidden()); + } finally { + ResourcePolicyBuilder.delete(idRef.get()); + } + } + + @Test + public void createPolicyByCommunityAdminTest() throws Exception { + context.turnOffAuthorisationSystem(); + EPerson rootComAdmin = EPersonBuilder.createEPerson(context) + .withEmail("rootComAdmin@mail.test") + .withPassword(password) + .build(); + + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("colSubmitter@mail.test") + .withPassword(password) + .build(); + + Community rootCommunity = CommunityBuilder.createCommunity(context) + .withName("Root Community") + .withAdminGroup(rootComAdmin) + .build(); + + Community community = CommunityBuilder.createSubCommunity(context, rootCommunity) + .withName("My First Commynity") + .build(); + + Community community2 = CommunityBuilder.createSubCommunity(context, rootCommunity) + .withName("My Second Commynity") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("My collection") + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + CollectionBuilder.createCollection(context, community2) + .withName("My Second Collection") + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + Item publication = ItemBuilder.createItem(context, collection) + .withTitle("Public item") + .build(); + + Collection collection2 = CollectionBuilder.createCollection(context, community) + .withName("My Second Collection") + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + Item publication2 = ItemBuilder.createItem(context, collection2) + .withTitle("Item of second collection") + .build(); + + //Add a bitstream to a publication + Bitstream bitstream = null; + try (InputStream is = IOUtils.toInputStream("ThisIsSomeDummyText", CharEncoding.UTF_8)) { + bitstream = BitstreamBuilder.createBitstream(context, publication2, is) + .withName("Bitstream") + .withDescription("description") + .withMimeType("text/plain") + .build(); + } + + context.restoreAuthSystemState(); + + ResourcePolicyRest resourcePolicyRest = new ResourcePolicyRest(); + resourcePolicyRest.setPolicyType(ResourcePolicy.TYPE_CUSTOM); + resourcePolicyRest.setAction(Constants.actionText[Constants.WRITE]); + resourcePolicyRest.setName("Test for collection admin"); + + ResourcePolicyRest resourcePolicyRest2 = new ResourcePolicyRest(); + resourcePolicyRest2.setPolicyType(ResourcePolicy.TYPE_CUSTOM); + resourcePolicyRest2.setAction(Constants.actionText[Constants.WRITE]); + resourcePolicyRest2.setName("Test for root community admin"); + + String authSubmitterToken = getAuthToken(submitter.getEmail(), password); + String authRootAdminToken = getAuthToken(rootComAdmin.getEmail(), password); + + AtomicReference idRef = new AtomicReference(); + AtomicReference idRef2 = new AtomicReference(); + try { + // create policy for submitter by root Community admin + getClient(authRootAdminToken).perform(post("/api/authz/resourcepolicies") + .content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest)) + .param("resource", publication.getID().toString()) + .param("eperson", submitter.getID().toString()) + .contentType(contentType)) + .andExpect(status().isCreated()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$", ResourcePolicyMatcher.matchFullEmbeds())) + .andExpect(jsonPath("$", Matchers.allOf( + hasJsonPath("$.name", is(resourcePolicyRest.getName())), + hasJsonPath("$.description", is(resourcePolicyRest.getDescription())), + hasJsonPath("$.policyType", is(resourcePolicyRest.getPolicyType())), + hasJsonPath("$.action", is(resourcePolicyRest.getAction())), + hasJsonPath("$.startDate", is(resourcePolicyRest.getStartDate())), + hasJsonPath("$.endDate", is(resourcePolicyRest.getEndDate())), + hasJsonPath("$.type", is(resourcePolicyRest.getType()))))) + .andDo(result -> idRef.set(read(result.getResponse().getContentAsString(), "$.id"))); + + // create policy for submitter by root Community admin + getClient(authRootAdminToken).perform(post("/api/authz/resourcepolicies") + .content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest)) + .param("resource", bitstream.getID().toString()) + .param("eperson", submitter.getID().toString()) + .contentType(contentType)) + .andExpect(status().isCreated()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$", ResourcePolicyMatcher.matchFullEmbeds())) + .andExpect(jsonPath("$", Matchers.allOf( + hasJsonPath("$.name", is(resourcePolicyRest.getName())), + hasJsonPath("$.description", is(resourcePolicyRest.getDescription())), + hasJsonPath("$.policyType", is(resourcePolicyRest.getPolicyType())), + hasJsonPath("$.action", is(resourcePolicyRest.getAction())), + hasJsonPath("$.startDate", is(resourcePolicyRest.getStartDate())), + hasJsonPath("$.endDate", is(resourcePolicyRest.getEndDate())), + hasJsonPath("$.type", is(resourcePolicyRest.getType()))))) + .andDo(result -> idRef2.set(read(result.getResponse().getContentAsString(), "$.id"))); + + getClient(authSubmitterToken).perform(get("/api/authz/resourcepolicies/" + idRef.get())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get()))); + + getClient(authSubmitterToken).perform(get("/api/authz/resourcepolicies/" + idRef2.get())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + idRef2.get()))); + } finally { + ResourcePolicyBuilder.delete(idRef.get()); + ResourcePolicyBuilder.delete(idRef2.get()); + } + } + @Test public void deleteOne() throws Exception { context.turnOffAuthorisationSystem(); @@ -1308,6 +1685,176 @@ public void deleteOneNotFoundTest() throws Exception { .andExpect(status().isNotFound()); } + @Test + public void deletePolicyByCollectionAdminTest() throws Exception { + context.turnOffAuthorisationSystem(); + EPerson colAdmin = EPersonBuilder.createEPerson(context) + .withEmail("colAdmin@mail.test") + .withPassword(password) + .build(); + + EPerson colAdmin2 = EPersonBuilder.createEPerson(context) + .withEmail("colAdmin2@mail.test") + .withPassword(password) + .build(); + + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("colSubmitter@mail.test") + .withPassword(password) + .build(); + + Community community = CommunityBuilder.createCommunity(context) + .withName("My top commynity") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("My collection") + .withAdminGroup(colAdmin) + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + CollectionBuilder.createCollection(context, community) + .withName("My Second Collection") + .withAdminGroup(colAdmin2) + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + Item publication = ItemBuilder.createItem(context, collection) + .withTitle("Public item") + .build(); + + //Add a bitstream to a publication + Bitstream bitstream = null; + try (InputStream is = IOUtils.toInputStream("ThisIsSomeDummyText", CharEncoding.UTF_8)) { + bitstream = BitstreamBuilder.createBitstream(context, publication, is) + .withName("Bitstream") + .withDescription("description") + .withMimeType("text/plain") + .build(); + } + + context.restoreAuthSystemState(); + + String adminToken = getAuthToken(admin.getEmail(), password); + String authcolAdminToken = getAuthToken(colAdmin.getEmail(), password); + String authcolAdmin2Token = getAuthToken(colAdmin2.getEmail(), password); + String authSubmitterToken = getAuthToken(submitter.getEmail(), password); + + ResourcePolicy rp = ResourcePolicyBuilder.createResourcePolicy(context) + .withDspaceObject(bitstream) + .withAction(Constants.READ) + .withPolicyType(ResourcePolicy.TYPE_CUSTOM) + .withUser(submitter) + .build(); + + // submitter can't delete own policy + getClient(authSubmitterToken).perform(delete("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isForbidden()); + + // check that policy wasn't deleted + getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + rp.getID()))); + + // other collection admin can't delete policy that belong to items of other collections + getClient(authcolAdmin2Token).perform(delete("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isForbidden()); + + // check that policy wasn't deleted + getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + rp.getID()))); + + // delete policy for submitter by collection admin + getClient(authcolAdminToken).perform(delete("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isNoContent()); + + getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isNotFound()); + } + + @Test + public void deletePolicyBySubCommunityAdminTest() throws Exception { + context.turnOffAuthorisationSystem(); + EPerson comAdmin = EPersonBuilder.createEPerson(context) + .withEmail("comAdmin@mail.test") + .withPassword(password) + .build(); + + EPerson comAdmin2 = EPersonBuilder.createEPerson(context) + .withEmail("comAdmin2@mail.test") + .withPassword(password) + .build(); + + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("colSubmitter@mail.test") + .withPassword(password) + .build(); + + Community community = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("My First Commynity") + .withAdminGroup(comAdmin) + .build(); + + Community community2 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("My Second Commynity") + .withAdminGroup(comAdmin2) + .build(); + + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("My collection") + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + CollectionBuilder.createCollection(context, community2) + .withName("My Second Collection") + .withSubmitterGroup(submitter) + .withEntityType("Publication") + .build(); + + Item publication = ItemBuilder.createItem(context, collection) + .withTitle("Public item") + .build(); + + context.restoreAuthSystemState(); + + ResourcePolicy rp = ResourcePolicyBuilder.createResourcePolicy(context) + .withDspaceObject(publication) + .withAction(Constants.WRITE) + .withPolicyType(ResourcePolicy.TYPE_CUSTOM) + .withUser(submitter) + .build(); + + String adminToken = getAuthToken(admin.getEmail(), password); + String authcomAdminToken = getAuthToken(comAdmin.getEmail(), password); + String authcomAdmin2Token = getAuthToken(comAdmin2.getEmail(), password); + + // other Community admin can't delete policy of other Community + getClient(authcomAdmin2Token).perform(delete("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isForbidden()); + + getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/resourcepolicies/" + rp.getID()))); + + // Community admin can delete policy + getClient(authcomAdminToken).perform(delete("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isNoContent()); + + // submitter can see own policy + getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID())) + .andExpect(status().isNotFound()); + } + @Test public void patchReplaceStartDateTest() throws Exception { context.turnOffAuthorisationSystem(); From d3ff31e50bf329f1a03202f6790f3fc40c730c27 Mon Sep 17 00:00:00 2001 From: Mykhaylo Boychuk Date: Fri, 24 Jan 2025 02:03:23 +0100 Subject: [PATCH 602/632] [DURACOM-318] update security annotations on ResourcePolicyRepository (cherry picked from commit fabcc692db68e5232986ff062e849e4ec5c68c8b) (cherry picked from commit 95836c271cb4af41d3c29f2dda118eab4674f653) --- .../ResourcePolicyRestRepository.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ResourcePolicyRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ResourcePolicyRestRepository.java index 8b598aeeae32..1bfc50481078 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ResourcePolicyRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ResourcePolicyRestRepository.java @@ -25,6 +25,7 @@ import org.dspace.app.rest.model.ResourcePolicyRest; import org.dspace.app.rest.model.patch.Patch; import org.dspace.app.rest.repository.patch.ResourcePatch; +import org.dspace.app.rest.security.DSpacePermissionEvaluator; import org.dspace.app.rest.utils.DSpaceObjectUtils; import org.dspace.app.rest.utils.Utils; import org.dspace.authorize.AuthorizeException; @@ -44,6 +45,8 @@ import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.Link; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; /** @@ -73,6 +76,9 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository resourcePatch; + @Autowired + private DSpacePermissionEvaluator permissionEvaluator; + @Autowired DiscoverableEndpointsService discoverableEndpointsService; @@ -222,14 +228,13 @@ public Page findByGroup(@Parameter(value = "uuid", required } @Override - @PreAuthorize("hasAuthority('ADMIN')") + @PreAuthorize("isAuthenticated()") protected ResourcePolicyRest createAndReturn(Context context) throws AuthorizeException, SQLException { String resourceUuidStr = getRequestService().getCurrentRequest().getServletRequest().getParameter("resource"); String epersonUuidStr = getRequestService().getCurrentRequest().getServletRequest().getParameter("eperson"); String groupUuidStr = getRequestService().getCurrentRequest().getServletRequest().getParameter("group"); - if (resourceUuidStr == null) { throw new MissingParameterException("Missing resource (uuid) parameter"); } @@ -244,6 +249,11 @@ protected ResourcePolicyRest createAndReturn(Context context) throws AuthorizeEx UUID resourceUuid = UUID.fromString(resourceUuidStr); + if (isNotAuthorized(resourceUuid, "WRITE")) { + throw new AuthorizeException( + "User unauthorized to create a new ResourcePolicy for resource: " + resourceUuid); + } + try { resourcePolicyRest = mapper.readValue(req.getInputStream(), ResourcePolicyRest.class); } catch (IOException exIO) { @@ -298,7 +308,7 @@ protected ResourcePolicyRest createAndReturn(Context context) throws AuthorizeEx } @Override - @PreAuthorize("hasAuthority('ADMIN')") + @PreAuthorize("hasPermission(#id, 'resourcepolicy', 'ADMIN')") protected void delete(Context context, Integer id) throws AuthorizeException { ResourcePolicy resourcePolicy = null; try { @@ -332,4 +342,10 @@ public void afterPropertiesSet() throws Exception { Link.of("/api/" + ResourcePolicyRest.CATEGORY + "/" + ResourcePolicyRest.PLURAL_NAME + "/search", ResourcePolicyRest.PLURAL_NAME + "-search"))); } + + private boolean isNotAuthorized(UUID id, String permission) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return !permissionEvaluator.hasPermission(authentication, id, "resourcepolicy", permission); + } + } From 8fee121b533faa1b81a9e2ba2f5b9879cd412113 Mon Sep 17 00:00:00 2001 From: Mykhaylo Boychuk Date: Fri, 24 Jan 2025 02:06:16 +0100 Subject: [PATCH 603/632] [DURACOM-318] improve sucurity plugin (cherry picked from commit b1ce88925ea36e84a77e667a94ae5577b5ee05b6) (cherry picked from commit e9be8435ec9fffec790ad965c162f89e11fedf97) --- .../authorize/ResourcePolicyServiceImpl.java | 6 ++- .../src/main/java/org/dspace/core/Utils.java | 43 +++++++++++++++++++ ...PolicyAdminPermissionEvalutatorPlugin.java | 42 +++++++++++++----- ...cePolicyRestPermissionEvaluatorPlugin.java | 1 - 4 files changed, 80 insertions(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java index 86998a2196e7..08a8a1463c03 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java @@ -19,6 +19,7 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.logging.log4j.Logger; import org.dspace.authorize.dao.ResourcePolicyDAO; +import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.DSpaceObject; import org.dspace.content.factory.ContentServiceFactory; @@ -51,6 +52,9 @@ public class ResourcePolicyServiceImpl implements ResourcePolicyService { @Autowired private GroupService groupService; + @Autowired + private AuthorizeService authorizeService; + protected ResourcePolicyServiceImpl() { } @@ -422,6 +426,6 @@ public boolean isMyResourcePolicy(Context context, EPerson eperson, Integer id) } else if (group != null && groupService.isMember(context, eperson, group)) { isMy = true; } - return isMy; + return isMy || authorizeService.isAdmin(context, eperson, resourcePolicy.getdSpaceObject()); } } diff --git a/dspace-api/src/main/java/org/dspace/core/Utils.java b/dspace-api/src/main/java/org/dspace/core/Utils.java index ea9ed57eca04..90df7240503e 100644 --- a/dspace-api/src/main/java/org/dspace/core/Utils.java +++ b/dspace-api/src/main/java/org/dspace/core/Utils.java @@ -506,4 +506,47 @@ public static String interpolateConfigsInString(String string) { ConfigurationService config = DSpaceServicesFactory.getInstance().getConfigurationService(); return StringSubstitutor.replace(string, config.getProperties()); } + + /** + * Get the maximum timestamp that can be stored in a PostgreSQL database with hibernate, + * for our "distant future" access expiry date. + * @return the maximum timestamp that can be stored with Postgres + Hibernate + */ + public static Instant getMaxTimestamp() { + return LocalDateTime.of(294276, 12, 31, 23, 59, 59) + .toInstant(ZoneOffset.UTC); + } + + /** + * Get the minimum timestamp that can be stored in a PostgreSQL database, for date validation or any other + * purpose to ensure we don't try to store a date before the epoch. + * @return the minimum timestamp that can be stored with Postgres + Hibernate + */ + public static Instant getMinTimestamp() { + return LocalDateTime.of(-4713, 11, 12, 0, 0, 0) + .toInstant(ZoneOffset.UTC); + } + + /** + * Checks whether a given string can be converted to a valid {@code int} value. + *

    + * This method returns {@code false} if the input string is {@code null}, empty, + * or contains only whitespace. Otherwise, it attempts to parse the string as an + * integer using {@link Integer#parseInt(String)}. + * + * @param str the string to check for integer convertibility + * @return {@code true} if the string is non-blank and can be parsed as an integer; + * {@code false} otherwise + */ + public static boolean isConvertibleToInt(String str) { + if (StringUtils.isBlank(str)) { + return false; + } + try { + Integer.parseInt(str); + return true; + } catch (NumberFormatException e) { + return false; + } + } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java index ccf272ecefae..230cad1e7127 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java @@ -9,17 +9,20 @@ import java.io.Serializable; import java.sql.SQLException; +import java.util.UUID; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.model.ResourcePolicyRest; import org.dspace.app.rest.utils.ContextUtil; +import org.dspace.app.util.factory.UtilServiceFactory; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; +import org.dspace.core.Utils; import org.dspace.services.RequestService; import org.dspace.services.model.Request; import org.springframework.beans.factory.annotation.Autowired; @@ -38,7 +41,7 @@ public class ResourcePolicyAdminPermissionEvalutatorPlugin extends RestObjectPer private static final Logger log = LogManager.getLogger(); - public static final String RESOURCE_POLICY_PATCH = "resourcepolicy"; + public static final String RESOURCE_POLICY_TYPE = "resourcepolicy"; @Autowired AuthorizeService authorizeService; @@ -55,8 +58,9 @@ public boolean hasDSpacePermission(Authentication authentication, Serializable t DSpaceRestPermission restPermission = DSpaceRestPermission.convert(permission); - if (!DSpaceRestPermission.ADMIN.equals(restPermission) - || !StringUtils.equalsIgnoreCase(targetType, RESOURCE_POLICY_PATCH)) { + if (!DSpaceRestPermission.ADMIN.equals(restPermission) && + !DSpaceRestPermission.WRITE.equals(restPermission) || + !StringUtils.equalsIgnoreCase(targetType, RESOURCE_POLICY_TYPE)) { return false; } @@ -64,19 +68,37 @@ public boolean hasDSpacePermission(Authentication authentication, Serializable t Context context = ContextUtil.obtainContext(request.getHttpServletRequest()); try { - int resourcePolicyID = Integer.parseInt(targetId.toString()); - ResourcePolicy resourcePolicy = resourcePolicyService.find(context, resourcePolicyID); - if (resourcePolicy == null) { - throw new ResourceNotFoundException( - ResourcePolicyRest.CATEGORY + "." + ResourcePolicyRest.NAME + - " with id: " + resourcePolicyID + " not found"); + DSpaceObject dso = null; + if (Utils.isConvertibleToInt(targetId.toString())) { + var id = Integer.parseInt(targetId.toString()); + dso = getDSO(context, id); + } else { + var uuid = UUID.fromString(targetId.toString()); + dso = getDSO(context, uuid); } - DSpaceObject dso = resourcePolicy.getdSpaceObject(); return authorizeService.isAdmin(context, dso); + } catch (SQLException e) { log.error(e::getMessage, e); } return false; } + private DSpaceObject getDSO(Context context, int id) throws SQLException { + ResourcePolicy resourcePolicy = resourcePolicyService.find(context, id); + if (resourcePolicy == null) { + throw new ResourceNotFoundException( + ResourcePolicyRest.CATEGORY + "." + ResourcePolicyRest.NAME + " with id: " + id + " not found"); + } + return resourcePolicy.getdSpaceObject(); + } + + private DSpaceObject getDSO(Context context, UUID uuid) throws SQLException { + DSpaceObject dso = UtilServiceFactory.getInstance().getDSpaceObjectUtils().findDSpaceObject(context, uuid); + if (dso == null) { + throw new ResourceNotFoundException("DSpaceObject with uuid: " + uuid + " not found"); + } + return dso; + } + } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyRestPermissionEvaluatorPlugin.java index 9a34ca68110d..6635a87a229a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyRestPermissionEvaluatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyRestPermissionEvaluatorPlugin.java @@ -55,7 +55,6 @@ public boolean hasDSpacePermission(Authentication authentication, Serializable t DSpaceRestPermission restPermission = DSpaceRestPermission.convert(permission); if (!DSpaceRestPermission.READ.equals(restPermission) - && !DSpaceRestPermission.WRITE.equals(restPermission) && !DSpaceRestPermission.DELETE.equals(restPermission) || !StringUtils.equalsIgnoreCase(targetType, ResourcePolicyRest.NAME)) { return false; From 0161f20036419ff9bc7c3163cd3bba5c615fd7b5 Mon Sep 17 00:00:00 2001 From: Adamo Date: Fri, 2 May 2025 09:38:28 +0200 Subject: [PATCH 604/632] [DURACOM-318] IT fix (cherry picked from commit accba0738f7684e31af707bf5bd06508e5571621) --- .../dspace/app/rest/ResourcePolicyRestRepositoryIT.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java index 5570332b16b2..e065bf27c81d 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java @@ -190,7 +190,7 @@ public void findOneUnAuthenticatedTest() throws Exception { public void findOneNotFoundTest() throws Exception { String authToken = getAuthToken(admin.getEmail(), password); - getClient(authToken).perform(get("/api/authz/resourcepolicies/" + UUID.randomUUID().toString())) + getClient(authToken).perform(get("/api/authz/resourcepolicies/" + UUID.randomUUID())) .andExpect(status().isNotFound()); } @@ -1742,11 +1742,10 @@ public void deletePolicyByCollectionAdminTest() throws Exception { String authcolAdmin2Token = getAuthToken(colAdmin2.getEmail(), password); String authSubmitterToken = getAuthToken(submitter.getEmail(), password); - ResourcePolicy rp = ResourcePolicyBuilder.createResourcePolicy(context) + ResourcePolicy rp = ResourcePolicyBuilder.createResourcePolicy(context, submitter, null) .withDspaceObject(bitstream) .withAction(Constants.READ) .withPolicyType(ResourcePolicy.TYPE_CUSTOM) - .withUser(submitter) .build(); // submitter can't delete own policy @@ -1825,11 +1824,10 @@ public void deletePolicyBySubCommunityAdminTest() throws Exception { context.restoreAuthSystemState(); - ResourcePolicy rp = ResourcePolicyBuilder.createResourcePolicy(context) + ResourcePolicy rp = ResourcePolicyBuilder.createResourcePolicy(context, submitter, null) .withDspaceObject(publication) .withAction(Constants.WRITE) .withPolicyType(ResourcePolicy.TYPE_CUSTOM) - .withUser(submitter) .build(); String adminToken = getAuthToken(admin.getEmail(), password); From ae26a8facd2fb709027359a7ca7a63ea2f65567e Mon Sep 17 00:00:00 2001 From: Mykhaylo Boychuk Date: Mon, 3 Feb 2025 19:30:16 +0100 Subject: [PATCH 605/632] [DURACOM-318] improve code (cherry picked from commit 8e0ca2e6f88b0251edf8a840f65135590c65f088) (cherry picked from commit 4270170d40833b7cd4c505a850c47f4bdff55a1c) --- dspace-api/src/main/java/org/dspace/core/Utils.java | 1 + .../ResourcePolicyAdminPermissionEvalutatorPlugin.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/core/Utils.java b/dspace-api/src/main/java/org/dspace/core/Utils.java index 90df7240503e..59d37f71cf42 100644 --- a/dspace-api/src/main/java/org/dspace/core/Utils.java +++ b/dspace-api/src/main/java/org/dspace/core/Utils.java @@ -549,4 +549,5 @@ public static boolean isConvertibleToInt(String str) { return false; } } + } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java index 230cad1e7127..a7a2b767656b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java @@ -11,6 +11,7 @@ import java.sql.SQLException; import java.util.UUID; +import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -69,7 +70,7 @@ public boolean hasDSpacePermission(Authentication authentication, Serializable t try { DSpaceObject dso = null; - if (Utils.isConvertibleToInt(targetId.toString())) { + if (NumberUtils.isNumber(targetId.toString())) { var id = Integer.parseInt(targetId.toString()); dso = getDSO(context, id); } else { From 84deaf3cb6583a7860fabdf35fb6c68583b7b0c2 Mon Sep 17 00:00:00 2001 From: Mykhaylo Boychuk Date: Mon, 3 Feb 2025 22:54:52 +0100 Subject: [PATCH 606/632] [DURACOM-318] remove unused import (cherry picked from commit ed91462ccd7f99f5cf0dc326ed06ab42c13b80e0) (cherry picked from commit 8df4e35e76364bf20dad51073e33cda8f3c3f623) --- .../security/ResourcePolicyAdminPermissionEvalutatorPlugin.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java index a7a2b767656b..ad83284b84b3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResourcePolicyAdminPermissionEvalutatorPlugin.java @@ -23,7 +23,6 @@ import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; -import org.dspace.core.Utils; import org.dspace.services.RequestService; import org.dspace.services.model.Request; import org.springframework.beans.factory.annotation.Autowired; From 01b0f63fff2d2f310e44f7f461e5d020cd6f5a08 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Tue, 24 Jun 2025 06:52:17 +0200 Subject: [PATCH 607/632] fix missing imports --- dspace-api/src/main/java/org/dspace/core/Utils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/core/Utils.java b/dspace-api/src/main/java/org/dspace/core/Utils.java index 59d37f71cf42..2e360e02960b 100644 --- a/dspace-api/src/main/java/org/dspace/core/Utils.java +++ b/dspace-api/src/main/java/org/dspace/core/Utils.java @@ -22,6 +22,10 @@ import java.rmi.dgc.VMID; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.time.Instant; +import java.time.LocalDateTime +import java.time.Instant; +import java.time.ZoneOffset import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; From db6c4362ec867b919a77fc7d090b5d47df56d1d2 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Tue, 24 Jun 2025 07:03:38 +0200 Subject: [PATCH 608/632] fix imports for checkstyle --- dspace-api/src/main/java/org/dspace/core/Utils.java | 2 +- .../org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/Utils.java b/dspace-api/src/main/java/org/dspace/core/Utils.java index 2e360e02960b..980c1f471688 100644 --- a/dspace-api/src/main/java/org/dspace/core/Utils.java +++ b/dspace-api/src/main/java/org/dspace/core/Utils.java @@ -25,7 +25,7 @@ import java.time.Instant; import java.time.LocalDateTime import java.time.Instant; -import java.time.ZoneOffset +import java.time.ZoneOffset; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java index e065bf27c81d..fdf98ab940d0 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java @@ -22,10 +22,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import java.text.SimpleDateFormat; import java.io.InputStream; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; From 75aecc1d759674c867f1fd2f77d56866b2e76356 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Tue, 24 Jun 2025 07:06:59 +0200 Subject: [PATCH 609/632] fix another missing semicolon --- dspace-api/src/main/java/org/dspace/core/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/core/Utils.java b/dspace-api/src/main/java/org/dspace/core/Utils.java index 980c1f471688..d35266ac6c3b 100644 --- a/dspace-api/src/main/java/org/dspace/core/Utils.java +++ b/dspace-api/src/main/java/org/dspace/core/Utils.java @@ -23,7 +23,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.time.Instant; -import java.time.LocalDateTime +import java.time.LocalDateTime; import java.time.Instant; import java.time.ZoneOffset; import java.text.ParseException; From d0ca7bd8b009b6b334045ce4b57755b74a76cd67 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Tue, 24 Jun 2025 07:19:39 +0200 Subject: [PATCH 610/632] fix import ordering --- dspace-api/src/main/java/org/dspace/core/Utils.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/Utils.java b/dspace-api/src/main/java/org/dspace/core/Utils.java index d35266ac6c3b..b13eb3ba360c 100644 --- a/dspace-api/src/main/java/org/dspace/core/Utils.java +++ b/dspace-api/src/main/java/org/dspace/core/Utils.java @@ -22,12 +22,11 @@ import java.rmi.dgc.VMID; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.time.Instant; import java.time.LocalDateTime; -import java.time.Instant; import java.time.ZoneOffset; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; From eb4e741bc76b7675b0399b0fae44d4df26e95589 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Wed, 25 Jun 2025 10:36:10 +0200 Subject: [PATCH 611/632] remove unnecessary code --- .../src/main/java/org/dspace/core/Utils.java | 46 ------------------- 1 file changed, 46 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/Utils.java b/dspace-api/src/main/java/org/dspace/core/Utils.java index b13eb3ba360c..a1294c3317ce 100644 --- a/dspace-api/src/main/java/org/dspace/core/Utils.java +++ b/dspace-api/src/main/java/org/dspace/core/Utils.java @@ -24,9 +24,6 @@ import java.security.NoSuchAlgorithmException; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; @@ -510,47 +507,4 @@ public static String interpolateConfigsInString(String string) { return StringSubstitutor.replace(string, config.getProperties()); } - /** - * Get the maximum timestamp that can be stored in a PostgreSQL database with hibernate, - * for our "distant future" access expiry date. - * @return the maximum timestamp that can be stored with Postgres + Hibernate - */ - public static Instant getMaxTimestamp() { - return LocalDateTime.of(294276, 12, 31, 23, 59, 59) - .toInstant(ZoneOffset.UTC); - } - - /** - * Get the minimum timestamp that can be stored in a PostgreSQL database, for date validation or any other - * purpose to ensure we don't try to store a date before the epoch. - * @return the minimum timestamp that can be stored with Postgres + Hibernate - */ - public static Instant getMinTimestamp() { - return LocalDateTime.of(-4713, 11, 12, 0, 0, 0) - .toInstant(ZoneOffset.UTC); - } - - /** - * Checks whether a given string can be converted to a valid {@code int} value. - *

    - * This method returns {@code false} if the input string is {@code null}, empty, - * or contains only whitespace. Otherwise, it attempts to parse the string as an - * integer using {@link Integer#parseInt(String)}. - * - * @param str the string to check for integer convertibility - * @return {@code true} if the string is non-blank and can be parsed as an integer; - * {@code false} otherwise - */ - public static boolean isConvertibleToInt(String str) { - if (StringUtils.isBlank(str)) { - return false; - } - try { - Integer.parseInt(str); - return true; - } catch (NumberFormatException e) { - return false; - } - } - } From 8e5bc3c9622999cac18e0871e248554a90e01c5b Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 25 Jun 2025 16:40:11 -0500 Subject: [PATCH 612/632] Update deploy demo.dspace.org branch to 9.x to ensure older branches never trigger a redeploy. --- .github/workflows/reusable-docker-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index 36907459747b..0c3261da95da 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -72,7 +72,7 @@ env: REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} # Current DSpace branches (and architecture) which are deployed to demo.dspace.org & sandbox.dspace.org respectively - DEPLOY_DEMO_BRANCH: 'dspace-8_x' + DEPLOY_DEMO_BRANCH: 'dspace-9_x' DEPLOY_SANDBOX_BRANCH: 'main' DEPLOY_ARCH: 'linux/amd64' # Registry used during building of Docker images. (All images are later copied to docker.io registry) From 47922396d33ccc95262c71fe872c3f7abbcf0dc3 Mon Sep 17 00:00:00 2001 From: nwoodward Date: Thu, 26 Jun 2025 11:16:32 -0500 Subject: [PATCH 613/632] dspace-api: improve date parsing for Solr sort --- .../java/org/dspace/sort/OrderFormatDate.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/sort/OrderFormatDate.java b/dspace-api/src/main/java/org/dspace/sort/OrderFormatDate.java index f56a97776f64..a8a6e5b98a00 100644 --- a/dspace-api/src/main/java/org/dspace/sort/OrderFormatDate.java +++ b/dspace-api/src/main/java/org/dspace/sort/OrderFormatDate.java @@ -7,31 +7,28 @@ */ package org.dspace.sort; +import java.util.Date; + +import org.dspace.util.MultiFormatDateParser; + /** - * Standard date ordering delegate implementation. The only "special" need is - * to treat dates with less than 4-digit year. + * Standard date ordering delegate implementation using date format + * parsing from o.d.u.MultiFormatDateParser. * * @author Andrea Bollini + * @author Alan Orth */ public class OrderFormatDate implements OrderFormatDelegate { @Override public String makeSortString(String value, String language) { - int padding = 0; - int endYearIdx = value.indexOf('-'); - - if (endYearIdx >= 0 && endYearIdx < 4) { - padding = 4 - endYearIdx; - } else if (value.length() < 4) { - padding = 4 - value.length(); - } + Date result = MultiFormatDateParser.parse(value); - if (padding > 0) { - // padding the value from left with 0 so that 87 -> 0087, 687-11-24 - // -> 0687-11-24 - return String.format("%1$0" + padding + "d", 0) - + value; + // If parsing was successful we return the value as an ISO instant, + // otherwise we return null so Solr does not index this date value. + if (result != null) { + return result.toInstant().toString(); } else { - return value; + return null; } } } From 1538920276db3e78535a2e7f097f9a0455f321fe Mon Sep 17 00:00:00 2001 From: abhinav Date: Wed, 25 Jun 2025 16:01:22 +0200 Subject: [PATCH 614/632] fix metadata getting cleared on patch request with invalid field (cherry picked from commit e559af1841ba52890279fdc5efdcc441e7f9eb79) --- .../DSpaceObjectMetadataReplaceOperation.java | 3 +-- .../org/dspace/app/rest/PatchMetadataIT.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 1cf15684587b..a3de8d3c9ea6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -80,8 +80,7 @@ private void replace(Context context, DSpaceObject dso, DSpaceObjectService dsoS MetadataValueRest metadataValue, String index, String propertyOfMd, String valueMdProperty) { // replace entire set of metadata if (metadataField == null) { - this.replaceAllMetadata(context, dso, dsoService); - return; + throw new UnprocessableEntityException("Metadata field does not exist"); } // replace all metadata for existing key diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java index 9b9db41a7c92..557401ac1aa3 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java @@ -1426,6 +1426,27 @@ public void moveMetadataAuthorFourToOneMultiOpTest() throws Exception { moveMetadataAuthorTest(moves, expectedOrder); } + @Test + public void replaceInvalidMetadataShouldFailTest() throws Exception { + initSimplePublicationItem(); + assertEquals(12, publicationItem.getMetadata().size()); + + String patchBody = getPatchContent(List.of( + new ReplaceOperation("/metadata/dc.contributor.invalid/0", "some value") + )); + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(patch("/api/core/items/" + publicationItem.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isUnprocessableEntity()); + + publicationItem = context.reloadEntity(publicationItem); + + assertEquals(12, publicationItem.getMetadata().size()); + assertEquals(0, + itemService.getMetadata(publicationItem, "dc", "contributor", "invalid", Item.ANY, false).size()); + } + /** * This method moves an author (dc.contributor.author) within a workspace publication's "traditionalpageone" * section from position "from" to "path" using a PATCH request and verifies the order of the authors within the From a60f219353619e7a7581198d84c69fe85a942546 Mon Sep 17 00:00:00 2001 From: abhinav Date: Wed, 25 Jun 2025 16:19:56 +0200 Subject: [PATCH 615/632] Update PatchMetadataIT (cherry picked from commit 27d59085dbcdc702bf779a309b4ed11148ebb5dc) --- .../src/test/java/org/dspace/app/rest/PatchMetadataIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java index 557401ac1aa3..26e3f209050b 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java @@ -1429,7 +1429,7 @@ public void moveMetadataAuthorFourToOneMultiOpTest() throws Exception { @Test public void replaceInvalidMetadataShouldFailTest() throws Exception { initSimplePublicationItem(); - assertEquals(12, publicationItem.getMetadata().size()); + assertEquals(11, publicationItem.getMetadata().size()); String patchBody = getPatchContent(List.of( new ReplaceOperation("/metadata/dc.contributor.invalid/0", "some value") @@ -1442,7 +1442,7 @@ public void replaceInvalidMetadataShouldFailTest() throws Exception { publicationItem = context.reloadEntity(publicationItem); - assertEquals(12, publicationItem.getMetadata().size()); + assertEquals(11, publicationItem.getMetadata().size()); assertEquals(0, itemService.getMetadata(publicationItem, "dc", "contributor", "invalid", Item.ANY, false).size()); } From d91dc5c691ff14212ef9497f4c1c8ffd40d02706 Mon Sep 17 00:00:00 2001 From: abhinav Date: Thu, 26 Jun 2025 09:25:40 +0200 Subject: [PATCH 616/632] move the exception to patchUtils (cherry picked from commit a2dc6fbdf89e15db0d51d261dd1708e00a526d27) --- .../operation/DSpaceObjectMetadataPatchUtils.java | 15 +++++++++++++-- .../DSpaceObjectMetadataReplaceOperation.java | 3 ++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataPatchUtils.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataPatchUtils.java index 954cc844f237..5bbd5c013c9e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataPatchUtils.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataPatchUtils.java @@ -14,6 +14,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; +import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.JsonValueEvaluator; import org.dspace.app.rest.model.patch.Operation; @@ -135,10 +136,20 @@ protected String extractNewValueOfMd(Operation operation) { * @param context Context the retrieve metadataField from service with string * @param operation Operation of the patch * @return The metadataField corresponding to the md element string of the operation + * Null if no metadata field is passed in the operation + * @throws UnprocessableEntityException if an invalid metadata field is passed in the operation */ - protected MetadataField getMetadataField(Context context, Operation operation) throws SQLException { + protected MetadataField getMetadataField(Context context, Operation operation) + throws SQLException, UnprocessableEntityException { String mdElement = this.extractMdFieldStringFromOperation(operation); - return metadataFieldService.findByString(context, mdElement, '.'); + if (StringUtils.isBlank(mdElement)) { + return null; + } + MetadataField metadataField = metadataFieldService.findByString(context, mdElement, '.'); + if (metadataField == null) { + throw new UnprocessableEntityException("Metadata field does not exist"); + } + return metadataField; } /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index a3de8d3c9ea6..1cf15684587b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -80,7 +80,8 @@ private void replace(Context context, DSpaceObject dso, DSpaceObjectService dsoS MetadataValueRest metadataValue, String index, String propertyOfMd, String valueMdProperty) { // replace entire set of metadata if (metadataField == null) { - throw new UnprocessableEntityException("Metadata field does not exist"); + this.replaceAllMetadata(context, dso, dsoService); + return; } // replace all metadata for existing key From b713b26daf50d4ee8b90addb854b588981c775cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:15:16 +0000 Subject: [PATCH 617/632] Bump org.checkerframework:checker-qual from 3.49.4 to 3.49.5 Bumps [org.checkerframework:checker-qual](https://github.com/typetools/checker-framework) from 3.49.4 to 3.49.5. - [Release notes](https://github.com/typetools/checker-framework/releases) - [Changelog](https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/typetools/checker-framework/compare/checker-framework-3.49.4...checker-framework-3.49.5) --- updated-dependencies: - dependency-name: org.checkerframework:checker-qual dependency-version: 3.49.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 189115079da2..086e0f46db4a 100644 --- a/pom.xml +++ b/pom.xml @@ -1350,7 +1350,7 @@ org.checkerframework checker-qual - 3.49.4 + 3.49.5 - org.sonatype.plugins - nexus-staging-maven-plugin - 1.7.0 + org.sonatype.central + central-publishing-maven-plugin + 0.8.0 @@ -923,7 +923,7 @@ + - org.sonatype.plugins - nexus-staging-maven-plugin + org.sonatype.central + central-publishing-maven-plugin true - - - ossrh - https://oss.sonatype.org/ - - true - - false - - 10 - - + org.apache.maven.plugins maven-source-plugin @@ -972,7 +970,7 @@ - + org.apache.maven.plugins maven-javadoc-plugin @@ -985,8 +983,8 @@ - + org.apache.maven.plugins maven-gpg-plugin @@ -1911,24 +1909,10 @@ scm:git:git@github.com:DSpace/DSpace.git scm:git:git@github.com:DSpace/DSpace.git - git@github.com:DSpace/DSpace.git + https://github.com/DSpace/DSpace dspace-8_x - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - @@ -1938,11 +1922,10 @@ false - + - maven-snapshots - https://oss.sonatype.org/content/repositories/snapshots - default + central-portal-snapshots + https://central.sonatype.com/repository/maven-snapshots/ false From 59ddbe5ee8765dab8f6a52f80543b0bc19572abc Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Wed, 2 Jul 2025 10:24:18 +0200 Subject: [PATCH 619/632] Point directly to HTTPS address for ArXiv (cherry picked from commit cf0d6635f2683b1c8a9c116d33a3e82779e70f77) --- .../resources/spring/spring-dspace-addon-import-services.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/resources/spring/spring-dspace-addon-import-services.xml b/dspace-api/src/main/resources/spring/spring-dspace-addon-import-services.xml index f7943fb2320c..e693d26e538e 100644 --- a/dspace-api/src/main/resources/spring/spring-dspace-addon-import-services.xml +++ b/dspace-api/src/main/resources/spring/spring-dspace-addon-import-services.xml @@ -59,7 +59,7 @@ - + From 4685450194552effdf832784f37369fef97baf04 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 2 Jul 2025 10:39:50 +0200 Subject: [PATCH 620/632] Safe and consistent XML entity handling in parsers --- .../dspace/administer/RegistryImporter.java | 7 +- .../org/dspace/administer/RegistryLoader.java | 9 +- .../org/dspace/administer/StructBuilder.java | 6 +- .../app/itemimport/ItemImportServiceImpl.java | 8 +- .../dspace/app/itemupdate/ItemArchive.java | 18 +-- .../dspace/app/launcher/ScriptLauncher.java | 3 +- .../app/sfx/SFXFileReaderServiceImpl.java | 5 +- .../org/dspace/app/util/DCInputsReader.java | 6 +- .../dspace/app/util/InitializeEntities.java | 6 +- .../app/util/SubmissionConfigReader.java | 9 +- .../java/org/dspace/app/util/XMLUtils.java | 123 ++++++++++++++++++ .../crosswalk/METSDisseminationCrosswalk.java | 3 +- .../crosswalk/MODSDisseminationCrosswalk.java | 3 +- .../content/crosswalk/QDCCrosswalk.java | 3 +- .../content/crosswalk/RoleCrosswalk.java | 3 +- .../crosswalk/XSLTIngestionCrosswalk.java | 3 +- .../dspace/content/packager/METSManifest.java | 8 +- .../dspace/content/packager/RoleIngester.java | 5 +- .../ctask/general/MetadataWebService.java | 11 +- .../provider/orcid/xml/Converter.java | 5 +- .../identifier/doi/DataCiteConnector.java | 3 +- .../ArXivImportMetadataSourceServiceImpl.java | 5 +- .../CiniiImportMetadataSourceServiceImpl.java | 15 +-- .../crossref/CrossRefAbstractProcessor.java | 5 +- .../EpoImportMetadataSourceServiceImpl.java | 13 +- ...enAireImportMetadataSourceServiceImpl.java | 5 +- ...PubmedImportMetadataSourceServiceImpl.java | 20 ++- ...PubmedEuropeMetadataSourceServiceImpl.java | 11 +- ...ScopusImportMetadataSourceServiceImpl.java | 9 +- .../WOSImportMetadataSourceServiceImpl.java | 11 +- .../CCLicenseConnectorServiceImpl.java | 3 +- .../dspace/orcid/client/OrcidClientImpl.java | 4 +- .../vocabulary/ControlledVocabulary.java | 4 +- 33 files changed, 229 insertions(+), 123 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/administer/RegistryImporter.java b/dspace-api/src/main/java/org/dspace/administer/RegistryImporter.java index 27a653421312..c74e56bce890 100644 --- a/dspace-api/src/main/java/org/dspace/administer/RegistryImporter.java +++ b/dspace-api/src/main/java/org/dspace/administer/RegistryImporter.java @@ -10,7 +10,6 @@ import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.xpath.XPath; @@ -18,6 +17,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.dspace.app.util.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -49,8 +49,9 @@ private RegistryImporter() { } */ public static Document loadXML(String filename) throws IOException, ParserConfigurationException, SAXException { - DocumentBuilder builder = DocumentBuilderFactory.newInstance() - .newDocumentBuilder(); + // This XML builder will *not* disable external entities as XML + // registries are considered trusted content + DocumentBuilder builder = XMLUtils.getTrustedDocumentBuilder(); Document document = builder.parse(new File(filename)); diff --git a/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java b/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java index d503bfc00b7f..8bb72e18521e 100644 --- a/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java +++ b/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java @@ -13,7 +13,6 @@ import java.util.ArrayList; import java.util.Arrays; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.xpath.XPath; @@ -29,6 +28,7 @@ import org.apache.commons.cli.ParseException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.BitstreamFormat; import org.dspace.content.factory.ContentServiceFactory; @@ -266,8 +266,9 @@ private static void loadFormat(Context context, Node node) */ private static Document loadXML(String filename) throws IOException, ParserConfigurationException, SAXException { - DocumentBuilder builder = DocumentBuilderFactory.newInstance() - .newDocumentBuilder(); + // This XML builder will *not* disable external entities as XML + // registries are considered trusted content + DocumentBuilder builder = XMLUtils.getTrustedDocumentBuilder(); return builder.parse(new File(filename)); } @@ -351,4 +352,4 @@ private static String[] getRepeatedElementData(Node parentElement, return data; } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java b/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java index 8bbcfe0ff753..f2577a37b176 100644 --- a/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java +++ b/dspace-api/src/main/java/org/dspace/administer/StructBuilder.java @@ -27,7 +27,6 @@ import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.xpath.XPath; @@ -43,6 +42,7 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.lang3.StringUtils; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; import org.dspace.content.Community; @@ -613,8 +613,8 @@ private static String validateCollections(NodeList collections, int level) */ private static org.w3c.dom.Document loadXML(InputStream input) throws IOException, ParserConfigurationException, SAXException { - DocumentBuilder builder = DocumentBuilderFactory.newInstance() - .newDocumentBuilder(); + // This builder factory does not disable external DTD, entities, etc. + DocumentBuilder builder = XMLUtils.getTrustedDocumentBuilder(); org.w3c.dom.Document document = builder.parse(input); diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java index 087a33026151..b40ecae2f7e0 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java @@ -47,7 +47,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.xpath.XPath; @@ -67,6 +66,7 @@ import org.dspace.app.itemimport.service.ItemImportService; import org.dspace.app.util.LocalSchemaFilenameFilter; import org.dspace.app.util.RelationshipUtils; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.service.AuthorizeService; @@ -179,6 +179,8 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea @Autowired(required = true) protected MetadataValueService metadataValueService; + protected DocumentBuilder builder; + protected String tempWorkDir; protected boolean isTest = false; @@ -1888,9 +1890,7 @@ protected String getStringValue(Node node) { */ protected Document loadXML(String filename) throws IOException, ParserConfigurationException, SAXException { - DocumentBuilder builder = DocumentBuilderFactory.newInstance() - .newDocumentBuilder(); - + DocumentBuilder builder = XMLUtils.getDocumentBuilder(); return builder.parse(new File(filename)); } diff --git a/dspace-api/src/main/java/org/dspace/app/itemupdate/ItemArchive.java b/dspace-api/src/main/java/org/dspace/app/itemupdate/ItemArchive.java index 26de45caf77e..7dda65a0a75b 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemupdate/ItemArchive.java +++ b/dspace-api/src/main/java/org/dspace/app/itemupdate/ItemArchive.java @@ -23,8 +23,6 @@ import java.util.Iterator; import java.util.List; import java.util.UUID; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; @@ -33,6 +31,7 @@ import org.apache.logging.log4j.Logger; import org.dspace.app.util.LocalSchemaFilenameFilter; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; @@ -52,7 +51,6 @@ public class ItemArchive { public static final String DUBLIN_CORE_XML = "dublin_core.xml"; - protected static DocumentBuilder builder = null; protected Transformer transformer = null; protected List dtomList = null; @@ -95,14 +93,14 @@ public static ItemArchive create(Context context, File dir, String itemField) InputStream is = null; try { is = new FileInputStream(new File(dir, DUBLIN_CORE_XML)); - itarch.dtomList = MetadataUtilities.loadDublinCore(getDocumentBuilder(), is); + itarch.dtomList = MetadataUtilities.loadDublinCore(XMLUtils.getDocumentBuilder(), is); //The code to search for local schema files was copied from org.dspace.app.itemimport // .ItemImportServiceImpl.java File file[] = dir.listFiles(new LocalSchemaFilenameFilter()); for (int i = 0; i < file.length; i++) { is = new FileInputStream(file[i]); - itarch.dtomList.addAll(MetadataUtilities.loadDublinCore(getDocumentBuilder(), is)); + itarch.dtomList.addAll(MetadataUtilities.loadDublinCore(XMLUtils.getDocumentBuilder(), is)); } } finally { if (is != null) { @@ -126,14 +124,6 @@ public static ItemArchive create(Context context, File dir, String itemField) return itarch; } - protected static DocumentBuilder getDocumentBuilder() - throws ParserConfigurationException { - if (builder == null) { - builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - } - return builder; - } - /** * Getter for Transformer * @@ -318,7 +308,7 @@ public void writeUndo(File undoDir) try { out = new FileOutputStream(new File(dir, "dublin_core.xml")); - Document doc = MetadataUtilities.writeDublinCore(getDocumentBuilder(), undoDtomList); + Document doc = MetadataUtilities.writeDublinCore(XMLUtils.getDocumentBuilder(), undoDtomList); MetadataUtilities.writeDocument(doc, getTransformer(), out); // if undo has delete bitstream diff --git a/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java b/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java index 89a416bfa883..ab8807c2cae3 100644 --- a/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java +++ b/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java @@ -19,6 +19,7 @@ import org.apache.commons.cli.ParseException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.core.Context; import org.dspace.scripts.DSpaceRunnable; import org.dspace.scripts.DSpaceRunnable.StepResult; @@ -314,7 +315,7 @@ public static Document getConfig(DSpaceKernelImpl kernelImpl) { String config = kernelImpl.getConfigurationService().getProperty("dspace.dir") + System.getProperty("file.separator") + "config" + System.getProperty("file.separator") + "launcher.xml"; - SAXBuilder saxBuilder = new SAXBuilder(); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document doc = null; try { doc = saxBuilder.build(config); diff --git a/dspace-api/src/main/java/org/dspace/app/sfx/SFXFileReaderServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/sfx/SFXFileReaderServiceImpl.java index 184f00a53e59..d3b447374a2c 100644 --- a/dspace-api/src/main/java/org/dspace/app/sfx/SFXFileReaderServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/sfx/SFXFileReaderServiceImpl.java @@ -18,6 +18,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.sfx.service.SFXFileReaderService; +import org.dspace.app.util.XMLUtils; import org.dspace.content.DCPersonName; import org.dspace.content.Item; import org.dspace.content.MetadataValue; @@ -79,9 +80,9 @@ public Document parseFile(String fileName) { log.info("Parsing XML file... " + fileName); DocumentBuilder docBuilder; Document doc = null; - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - docBuilderFactory.setIgnoringElementContentWhitespace(true); try { + DocumentBuilderFactory docBuilderFactory = XMLUtils.getDocumentBuilderFactory(); + docBuilderFactory.setIgnoringElementContentWhitespace(true); docBuilder = docBuilderFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { log.error("Wrong parser configuration: " + e.getMessage()); diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java index c77c3bf10e08..d2f3ac0dc5d9 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java @@ -121,7 +121,11 @@ private void buildInputs(String fileName) String uri = "file:" + new File(fileName).getAbsolutePath(); try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // This document builder factory will *not* disable external + // entities as they can be useful in managing large forms, but + // it is up to site administrators to validate the XML they are + // storing + DocumentBuilderFactory factory = XMLUtils.getTrustedDocumentBuilderFactory(); factory.setValidating(false); factory.setIgnoringComments(true); factory.setIgnoringElementContentWhitespace(true); diff --git a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java index 8d3964a3e3c7..4e64c18fcedd 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java +++ b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java @@ -11,7 +11,6 @@ import java.io.IOException; import java.sql.SQLException; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.cli.CommandLine; @@ -139,8 +138,9 @@ private void run(String fileLocation) throws SQLException, AuthorizeException { private void parseXMLToRelations(Context context, String fileLocation) throws AuthorizeException { try { File fXmlFile = new File(fileLocation); - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + // This XML builder will allow external entities, so the relationship types XML should + // be considered trusted by administrators + DocumentBuilder dBuilder = XMLUtils.getTrustedDocumentBuilder(); Document doc = dBuilder.parse(fXmlFile); doc.getDocumentElement().normalize(); diff --git a/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java b/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java index 78be2bd4a41b..64e62317c515 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java @@ -170,8 +170,11 @@ private void buildInputs(String fileName) throws SubmissionConfigReaderException String uri = "file:" + new File(fileName).getAbsolutePath(); try { - DocumentBuilderFactory factory = DocumentBuilderFactory - .newInstance(); + // This document builder factory will *not* disable external + // entities as they can be useful in managing large forms, but + // it is up to site administrators to validate the XML they are + // storing + DocumentBuilderFactory factory = XMLUtils.getTrustedDocumentBuilderFactory(); factory.setValidating(false); factory.setIgnoringComments(true); factory.setIgnoringElementContentWhitespace(true); @@ -732,4 +735,4 @@ public List getCollectionsBySubmissionConfig(Context context, String } return results; } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java b/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java index c39d0d26fd5e..389d53fe6da4 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java +++ b/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java @@ -9,8 +9,13 @@ import java.util.ArrayList; import java.util.List; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLInputFactory; import org.apache.commons.lang3.StringUtils; +import org.jdom2.input.SAXBuilder; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -161,4 +166,122 @@ public static List getElementValueArrayList(Element rootElement, } return result; } + + /** + * Initialize and return a javax DocumentBuilderFactory with NO security + * applied. This is intended only for internal, administrative/configuration + * use where external entities and other dangerous features are actually + * purposefully included. + * The method here is tiny, but may be expanded with other features like + * whitespace handling, and calling this method name helps to document + * the fact that the caller knows it is trusting the XML source / factory. + * + * @return document builder factory to generate new builders + * @throws ParserConfigurationException + */ + public static DocumentBuilderFactory getTrustedDocumentBuilderFactory() + throws ParserConfigurationException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + return factory; + } + + /** + * Initialize and return the javax DocumentBuilderFactory with some basic security + * applied to avoid XXE attacks and other unwanted content inclusion + * @return document builder factory to generate new builders + * @throws ParserConfigurationException + */ + public static DocumentBuilderFactory getDocumentBuilderFactory() + throws ParserConfigurationException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // No DOCTYPE / DTDs + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + // No external general entities + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + // No external parameter entities + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + // No external DTDs + factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + // Even if entities somehow get defined, they will not be expanded + factory.setExpandEntityReferences(false); + // Disable "XInclude" markup processing + factory.setXIncludeAware(false); + + return factory; + } + + /** + * Initialize and return a javax DocumentBuilder with NO security + * applied. This is intended only for internal, administrative/configuration + * use where external entities and other dangerous features are actually + * purposefully included. + * The method here is tiny, but may be expanded with other features like + * whitespace handling, and calling this method name helps to document + * the fact that the caller knows it is trusting the XML source / builder + * + * @return document builder with no security features set + * @throws ParserConfigurationException + */ + public static DocumentBuilder getTrustedDocumentBuilder() + throws ParserConfigurationException { + return getTrustedDocumentBuilderFactory().newDocumentBuilder(); + } + + /** + * Initialize and return the javax DocumentBuilder with some basic security applied + * to avoid XXE attacks and other unwanted content inclusion + * @return document builder for use in XML parsing + * @throws ParserConfigurationException + */ + public static DocumentBuilder getDocumentBuilder() + throws ParserConfigurationException { + return getDocumentBuilderFactory().newDocumentBuilder(); + } + + /** + * Initialize and return the SAX document builder with some basic security applied + * to avoid XXE attacks and other unwanted content inclusion + * @return SAX document builder for use in XML parsing + */ + public static SAXBuilder getSAXBuilder() { + return getSAXBuilder(false); + } + + /** + * Initialize and return the SAX document builder with some basic security applied + * to avoid XXE attacks and other unwanted content inclusion + * @param validate whether to use JDOM XSD validation + * @return SAX document builder for use in XML parsing + */ + public static SAXBuilder getSAXBuilder(boolean validate) { + SAXBuilder saxBuilder = new SAXBuilder(); + if (validate) { + saxBuilder.setValidation(true); + } + // No DOCTYPE / DTDs + saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + // No external general entities + saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false); + // No external parameter entities + saxBuilder.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + // No external DTDs + saxBuilder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + // Don't expand entities + saxBuilder.setExpandEntities(false); + + return saxBuilder; + } + + /** + * Initialize and return the Java XML Input Factory with some basic security applied + * to avoid XXE attacks and other unwanted content inclusion + * @return XML input factory for use in XML parsing + */ + public static XMLInputFactory getXMLInputFactory() { + XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); + xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + + return xmlInputFactory; + } + } diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/METSDisseminationCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/METSDisseminationCrosswalk.java index b8a4a8aef390..5ceacc933e4c 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/METSDisseminationCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/METSDisseminationCrosswalk.java @@ -14,6 +14,7 @@ import java.util.List; import org.apache.commons.lang3.ArrayUtils; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.packager.PackageDisseminator; @@ -129,7 +130,7 @@ public Element disseminateElement(Context context, DSpaceObject dso) try { //Return just the root Element of the METS file - SAXBuilder builder = new SAXBuilder(); + SAXBuilder builder = XMLUtils.getSAXBuilder(); Document metsDocument = builder.build(tempFile); return metsDocument.getRootElement(); } catch (JDOMException je) { diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/MODSDisseminationCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/MODSDisseminationCrosswalk.java index 1e63be5ba1b9..205b3ef5b343 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/MODSDisseminationCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/MODSDisseminationCrosswalk.java @@ -22,6 +22,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; import org.dspace.content.Community; @@ -144,7 +145,7 @@ public static String[] getPluginNames() { MODS_NS.getURI() + " " + MODS_XSD; private static final XMLOutputter outputUgly = new XMLOutputter(); - private static final SAXBuilder builder = new SAXBuilder(); + private static final SAXBuilder builder = XMLUtils.getSAXBuilder(); private Map modsMap = null; diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/QDCCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/QDCCrosswalk.java index 2fdbaaad003e..51e6357d93e1 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/QDCCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/QDCCrosswalk.java @@ -22,6 +22,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; @@ -125,7 +126,7 @@ public class QDCCrosswalk extends SelfNamedPlugin // XML schemaLocation fragment for this crosswalk, from config. private String schemaLocation = null; - private static final SAXBuilder builder = new SAXBuilder(); + private static final SAXBuilder builder = XMLUtils.getSAXBuilder(); protected ItemService itemService = ContentServiceFactory.getInstance().getItemService(); diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/RoleCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/RoleCrosswalk.java index 2c763036ce33..8d5bf49902cc 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/RoleCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/RoleCrosswalk.java @@ -13,6 +13,7 @@ import java.sql.SQLException; import java.util.List; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.packager.PackageDisseminator; @@ -208,7 +209,7 @@ public Element disseminateElement(Context context, DSpaceObject dso) try { //Try to parse our XML results (which were disseminated by the Packager) - SAXBuilder builder = new SAXBuilder(); + SAXBuilder builder = XMLUtils.getSAXBuilder(); Document xmlDocument = builder.build(tempFile); //If XML parsed successfully, return root element of doc if (xmlDocument != null && xmlDocument.hasRootElement()) { diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/XSLTIngestionCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/XSLTIngestionCrosswalk.java index 63ef5f7336c7..b07b2b2228e4 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/XSLTIngestionCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/XSLTIngestionCrosswalk.java @@ -18,6 +18,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; import org.dspace.content.Community; @@ -297,7 +298,7 @@ public static void main(String[] argv) throws Exception { "Failed to initialize transformer, probably error loading stylesheet."); } - SAXBuilder builder = new SAXBuilder(); + SAXBuilder builder = XMLUtils.getSAXBuilder(); Document inDoc = builder.build(new FileInputStream(argv[i + 1])); XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); List dimList; diff --git a/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java b/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java index 3399bdf0f07e..a1ed3c124374 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java @@ -20,6 +20,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; @@ -265,12 +266,13 @@ protected METSManifest(SAXBuilder builder, Element mets, String configName) { public static METSManifest create(InputStream is, boolean validate, String configName) throws IOException, MetadataValidationException { - SAXBuilder builder = new SAXBuilder(validate); + SAXBuilder builder = XMLUtils.getSAXBuilder(); builder.setIgnoringElementContentWhitespace(true); // Set validation feature if (validate) { + builder.setValidation(true); builder.setFeature("http://apache.org/xml/features/validation/schema", true); // Tell the parser where local copies of schemas are, to speed up @@ -278,10 +280,6 @@ public static METSManifest create(InputStream is, boolean validate, String confi if (localSchemas.length() > 0) { builder.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation", localSchemas); } - } else { - // disallow DTD parsing to ensure no XXE attacks can occur. - // See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html - builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); } // Parse the METS file diff --git a/dspace-api/src/main/java/org/dspace/content/packager/RoleIngester.java b/dspace-api/src/main/java/org/dspace/content/packager/RoleIngester.java index ca27abe20614..a0ac43282c32 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/RoleIngester.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/RoleIngester.java @@ -21,6 +21,7 @@ import org.apache.commons.codec.DecoderException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; import org.dspace.content.Community; @@ -385,7 +386,7 @@ public void ingestStream(Context context, DSpaceObject parent, Document document; try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory dbf = XMLUtils.getDocumentBuilderFactory(); dbf.setIgnoringComments(true); dbf.setCoalescing(true); DocumentBuilder db = dbf.newDocumentBuilder(); @@ -419,7 +420,7 @@ public DSpaceObject ingest(Context context, DSpaceObject parent, Document document; try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory dbf = XMLUtils.getDocumentBuilderFactory(); dbf.setIgnoringComments(true); dbf.setCoalescing(true); DocumentBuilder db = dbf.newDocumentBuilder(); diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java index fc62d7a4b23f..1b618ad31fb7 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java @@ -37,6 +37,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.client.DSpaceHttpClientFactory; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; @@ -176,7 +177,7 @@ public void init(Curator curator, String taskId) throws IOException { fieldSeparator = (fldSep != null) ? fldSep : " "; urlTemplate = taskProperty("template"); templateParam = urlTemplate.substring(urlTemplate.indexOf("{") + 1, - urlTemplate.indexOf("}")); + urlTemplate.indexOf("}")); String[] parsed = parseTransform(templateParam); lookupField = parsed[0]; lookupTransform = parsed[1]; @@ -204,13 +205,9 @@ public void init(Curator curator, String taskId) throws IOException { } } // initialize response document parser - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); try { - // disallow DTD parsing to ensure no XXE attacks can occur - // See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setXIncludeAware(false); + DocumentBuilderFactory factory = XMLUtils.getDocumentBuilderFactory(); + factory.setNamespaceAware(true); docBuilder = factory.newDocumentBuilder(); } catch (ParserConfigurationException pcE) { log.error("caught exception: " + pcE); diff --git a/dspace-api/src/main/java/org/dspace/external/provider/orcid/xml/Converter.java b/dspace-api/src/main/java/org/dspace/external/provider/orcid/xml/Converter.java index 578db6c56749..ab641c00042b 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/orcid/xml/Converter.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/orcid/xml/Converter.java @@ -16,6 +16,7 @@ import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.Unmarshaller; +import org.dspace.app.util.XMLUtils; import org.xml.sax.SAXException; /** @@ -31,9 +32,7 @@ public abstract class Converter { protected Object unmarshall(InputStream input, Class type) throws SAXException, URISyntaxException { try { - XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); - // disallow DTD parsing to ensure no XXE attacks can occur - xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + XMLInputFactory xmlInputFactory = XMLUtils.getXMLInputFactory(); XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(input); JAXBContext context = JAXBContext.newInstance(type); diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index 59c8b2c701c9..23853979be05 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -40,6 +40,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.client.DSpaceHttpClientFactory; +import org.dspace.app.util.XMLUtils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.crosswalk.CrosswalkException; @@ -829,7 +830,7 @@ protected String extractAlternateIdentifier(Context context, String content) } // parse the XML - SAXBuilder saxBuilder = new SAXBuilder(); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document doc = null; try { doc = saxBuilder.build(new ByteArrayInputStream(content.getBytes("UTF-8"))); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/arxiv/service/ArXivImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/arxiv/service/ArXivImportMetadataSourceServiceImpl.java index 660e0c9754bd..a790c6a9a544 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/arxiv/service/ArXivImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/arxiv/service/ArXivImportMetadataSourceServiceImpl.java @@ -22,6 +22,7 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; +import org.dspace.app.util.XMLUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -218,7 +219,7 @@ public Integer call() throws Exception { if (response.getStatus() == 200) { String responseString = response.readEntity(String.class); - SAXBuilder saxBuilder = new SAXBuilder(); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(responseString)); Element root = document.getRootElement(); @@ -399,7 +400,7 @@ private String getQuery(Query query) { private List splitToRecords(String recordsSrc) { try { - SAXBuilder saxBuilder = new SAXBuilder(); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(recordsSrc)); Element root = document.getRootElement(); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java index 82a4b2d77968..41c80ab7fe64 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java @@ -26,6 +26,7 @@ import org.apache.http.client.utils.URIBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -301,9 +302,7 @@ protected List search(String id, String appId) private List splitToRecords(String recordsSrc) { try { - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(recordsSrc)); Element root = document.getRootElement(); return root.getChildren(); @@ -356,9 +355,7 @@ private List getCiniiIds(String appId, Integer maxResult, String author, Map> params = new HashMap>(); String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params); int url_len = this.url.length() - 1; - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(response)); Element root = document.getRootElement(); List namespaces = Arrays.asList( @@ -420,9 +417,7 @@ private Integer countCiniiElement(String appId, Integer maxResult, String author Map> params = new HashMap>(); String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params); - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(response)); Element root = document.getRootElement(); List namespaces = Arrays @@ -449,4 +444,4 @@ private MetadatumDTO createIdentifier(String id) { return metadatumDTO; } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAbstractProcessor.java b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAbstractProcessor.java index 1b6da9d37b16..99f1ee37a54e 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAbstractProcessor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefAbstractProcessor.java @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.Collection; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import com.fasterxml.jackson.core.JsonProcessingException; @@ -21,6 +20,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.importer.external.metadatamapping.contributor.JsonPathMetadataProcessor; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -64,10 +64,9 @@ private String prettifyAbstract(String abstractValue) { } String xmlString = "" + abstractValue + ""; - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document xmlDoc; try { - DocumentBuilder builder = factory.newDocumentBuilder(); + DocumentBuilder builder = XMLUtils.getDocumentBuilder(); InputSource is = new InputSource(new StringReader(xmlString)); xmlDoc = builder.parse(is); } catch (SAXException | IOException | ParserConfigurationException e) { diff --git a/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoImportMetadataSourceServiceImpl.java index fbae302bca6a..7edd3f9d01c5 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoImportMetadataSourceServiceImpl.java @@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.xerces.impl.dv.util.Base64; +import org.dspace.app.util.XMLUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -397,9 +398,7 @@ private Integer countDocument(String bearer, String query) { String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params); - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(response)); Element root = document.getRootElement(); @@ -436,9 +435,7 @@ private List searchDocumentIds(String bearer, String query, int s String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params); - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(response)); Element root = document.getRootElement(); @@ -489,9 +486,7 @@ private List searchDocument(String bearer, String id, String docTy private List splitToRecords(String recordsSrc) { try { - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(recordsSrc)); Element root = document.getRootElement(); List namespaces = Arrays.asList(Namespace.getNamespace("ns", "http://www.epo.org/exchange")); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/openaire/service/OpenAireImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/openaire/service/OpenAireImportMetadataSourceServiceImpl.java index 7fb5f27354f7..ea5b7a67617c 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/openaire/service/OpenAireImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/openaire/service/OpenAireImportMetadataSourceServiceImpl.java @@ -20,6 +20,7 @@ import jakarta.ws.rs.client.Invocation; import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.Response; +import org.dspace.app.util.XMLUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -248,7 +249,7 @@ public Integer call() throws Exception { if (response.getStatus() == 200) { String responseString = response.readEntity(String.class); - SAXBuilder saxBuilder = new SAXBuilder(); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(responseString)); Element root = document.getRootElement(); @@ -330,7 +331,7 @@ private ImportRecord filterMultipleTitles(ImportRecord transformSourceRecords) { private List splitToRecords(String recordsSrc) { try { - SAXBuilder saxBuilder = new SAXBuilder(); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(recordsSrc)); Element root = document.getRootElement(); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java index 000ef19eaec5..7718e59e483e 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java @@ -24,6 +24,7 @@ import com.google.common.io.CharStreams; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.URIBuilder; +import org.dspace.app.util.XMLUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -233,11 +234,13 @@ private String getSingleElementValue(String src, String elementName) { String value = null; try { - SAXBuilder saxBuilder = new SAXBuilder(); - // Disallow external entities & entity expansion to protect against XXE attacks - // (NOTE: We receive errors if we disable all DTDs for PubMed, so this is the best we can do) - saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false); - saxBuilder.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); + // To properly parse PubMed responses, we must allow DOCTYPE/DTDs overall but + // we can still take advantage of entities themselves being disabled, and not + // expanded. + saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + saxBuilder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", + true); Document document = saxBuilder.build(new StringReader(src)); Element root = document.getRootElement(); @@ -354,12 +357,7 @@ public Collection call() throws Exception { private List splitToRecords(String recordsSrc) { try { - SAXBuilder saxBuilder = new SAXBuilder(); - // Disallow external entities & entity expansion to protect against XXE attacks - // (NOTE: We receive errors if we disable all DTDs for PubMed, so this is the best we can do) - saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false); - saxBuilder.setFeature("http://xml.org/sax/features/external-parameter-entities", false); - saxBuilder.setExpandEntities(false); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(recordsSrc)); Element root = document.getRootElement(); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeMetadataSourceServiceImpl.java index 7cd297eb2815..24f40339ddec 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeMetadataSourceServiceImpl.java @@ -24,6 +24,7 @@ import org.apache.http.client.utils.URIBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -292,9 +293,7 @@ public Integer count(String query) throws URISyntaxException, ClientProtocolExce Map> params = new HashMap>(); String response = liveImportClient.executeHttpGetRequest(1000, buildURI(1, query), params); - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(response)); Element root = document.getRootElement(); Element element = root.getChild("hitCount"); @@ -365,9 +364,7 @@ public List search(String query, Integer size, Integer start) thro String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params); String cursorMark = StringUtils.EMPTY; if (StringUtils.isNotBlank(response)) { - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(response)); XPathFactory xpfac = XPathFactory.instance(); XPathExpression xPath = xpfac.compile("//responseWrapper/resultList/result", @@ -419,4 +416,4 @@ public void setUrl(String url) { this.url = url; } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusImportMetadataSourceServiceImpl.java index a3f74694becf..22e3534ca89f 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusImportMetadataSourceServiceImpl.java @@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -208,9 +209,7 @@ public Integer call() throws Exception { return 0; } - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(response)); Element root = document.getRootElement(); @@ -397,9 +396,7 @@ private Map getRequestParameters(String query, String viewMode, private List splitToRecords(String recordsSrc) { try { - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(recordsSrc)); Element root = document.getRootElement(); String totalResults = root.getChildText("totalResults", Namespace.getNamespace("http://a9.com/-/spec/opensearch/1.1/")); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java index 9bffa2a84a19..2ac63d50513f 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSImportMetadataSourceServiceImpl.java @@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.app.util.XMLUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; @@ -145,9 +146,7 @@ public Integer call() throws Exception { params.put(HEADER_PARAMETERS, getRequestParameters()); String response = liveImportClient.executeHttpGetRequest(timeout, url, params); - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(response)); Element root = document.getRootElement(); XPathExpression xpath = XPathFactory.instance().compile("//*[@name=\"RecordsFound\"]", @@ -288,9 +287,7 @@ private boolean isIsi(String query) { private List splitToRecords(String recordsSrc) { try { - SAXBuilder saxBuilder = new SAXBuilder(); - // disallow DTD parsing to ensure no XXE attacks can occur - saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); + SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); Document document = saxBuilder.build(new StringReader(recordsSrc)); Element root = document.getRootElement(); String cData = XPathFactory.instance().compile("//*[@name=\"Records\"]", @@ -332,4 +329,4 @@ public void setApiKey(String apiKey) { this.apiKey = apiKey; } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java b/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java index 1d777a2e13c8..3c9088bda5df 100644 --- a/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/license/CCLicenseConnectorServiceImpl.java @@ -28,6 +28,7 @@ import org.apache.http.util.EntityUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.client.DSpaceHttpClientFactory; +import org.dspace.app.util.XMLUtils; import org.dspace.services.ConfigurationService; import org.jdom2.Attribute; import org.jdom2.Document; @@ -50,7 +51,7 @@ public class CCLicenseConnectorServiceImpl implements CCLicenseConnectorService, private Logger log = org.apache.logging.log4j.LogManager.getLogger(CCLicenseConnectorServiceImpl.class); private CloseableHttpClient client; - protected SAXBuilder parser = new SAXBuilder(); + protected SAXBuilder parser = XMLUtils.getSAXBuilder(); private String postArgument = "answers"; private String postAnswerFormat = diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java index da1de465251d..11bf444384cd 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java @@ -43,6 +43,7 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.message.BasicNameValuePair; import org.dspace.app.client.DSpaceHttpClientFactory; +import org.dspace.app.util.XMLUtils; import org.dspace.orcid.OrcidToken; import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidEntityType; @@ -351,8 +352,7 @@ private String marshall(Object object) throws JAXBException { @SuppressWarnings("unchecked") private T unmarshall(HttpEntity entity, Class clazz) throws Exception { JAXBContext jaxbContext = JAXBContext.newInstance(clazz); - XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); - xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + XMLInputFactory xmlInputFactory = XMLUtils.getXMLInputFactory(); XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(entity.getContent()); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); return (T) unmarshaller.unmarshal(xmlStreamReader); diff --git a/dspace-api/src/main/java/org/dspace/vocabulary/ControlledVocabulary.java b/dspace-api/src/main/java/org/dspace/vocabulary/ControlledVocabulary.java index 7f2bdc6ef771..bd19a1254fe3 100644 --- a/dspace-api/src/main/java/org/dspace/vocabulary/ControlledVocabulary.java +++ b/dspace-api/src/main/java/org/dspace/vocabulary/ControlledVocabulary.java @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.xpath.XPath; @@ -20,6 +19,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.dspace.app.util.XMLUtils; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; import org.w3c.dom.Document; @@ -71,7 +71,7 @@ public static ControlledVocabulary loadVocabulary(String fileName) File controlledVocFile = new File(filePath.toString()); if (controlledVocFile.exists()) { - DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + DocumentBuilder builder = XMLUtils.getDocumentBuilder(); Document document = builder.parse(controlledVocFile); XPath xPath = XPathFactory.newInstance().newXPath(); Node node = (Node) xPath.compile("node").evaluate(document, XPathConstants.NODE); From d3f62c7f1be476c036236ba77661cbed92f44af1 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 2 Jul 2025 15:30:04 -0500 Subject: [PATCH 621/632] EPO and PubMed only need to allow for DOCTYPEs. All other XML security changes can be used. --- .../service/EpoImportMetadataSourceServiceImpl.java | 4 ++++ .../service/PubmedImportMetadataSourceServiceImpl.java | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoImportMetadataSourceServiceImpl.java index 7edd3f9d01c5..552f607827a8 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoImportMetadataSourceServiceImpl.java @@ -399,6 +399,10 @@ private Integer countDocument(String bearer, String query) { String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params); SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); + // To properly parse EPO responses, we must allow DOCTYPEs overall. But, we can still apply all the + // other default XXE protections, including disabling external entities and entity expansion. + // NOTE: we only need to allow DOCTYPEs for this initial API call. All other calls have them disabled. + saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); Document document = saxBuilder.build(new StringReader(response)); Element root = document.getRootElement(); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java index 7718e59e483e..c870161bf9bd 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/service/PubmedImportMetadataSourceServiceImpl.java @@ -235,12 +235,9 @@ private String getSingleElementValue(String src, String elementName) { try { SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); - // To properly parse PubMed responses, we must allow DOCTYPE/DTDs overall but - // we can still take advantage of entities themselves being disabled, and not - // expanded. + // To properly parse PubMed responses, we must allow DOCTYPEs overall. But, we can still apply all the + // other default XXE protections, including disabling external entities and entity expansion. saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); - saxBuilder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", - true); Document document = saxBuilder.build(new StringReader(src)); Element root = document.getRootElement(); @@ -358,6 +355,9 @@ public Collection call() throws Exception { private List splitToRecords(String recordsSrc) { try { SAXBuilder saxBuilder = XMLUtils.getSAXBuilder(); + // To properly parse PubMed responses, we must allow DOCTYPEs overall. But, we can still apply all the + // other default XXE protections, including disabling external entities and entity expansion. + saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); Document document = saxBuilder.build(new StringReader(recordsSrc)); Element root = document.getRootElement(); From 2f4c5e8826cbe758b819e584eab8d9e53b457221 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 02:52:43 +0000 Subject: [PATCH 622/632] Bump the spring group across 1 directory with 25 updates Bumps the spring group with 25 updates in the / directory: | Package | From | To | | --- | --- | --- | | [org.springframework:spring-orm](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-beans](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-aop](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-context-support](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-tx](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-jdbc](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-expression](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework:spring-test](https://github.com/spring-projects/spring-framework) | `6.2.7` | `6.2.8` | | [org.springframework.boot:spring-boot-starter-test](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-tomcat](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-maven-plugin](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-cache](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-thymeleaf](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-web](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-data-rest](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-security](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-aop](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-actuator](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.boot:spring-boot-starter-log4j2](https://github.com/spring-projects/spring-boot) | `3.5.0` | `3.5.3` | | [org.springframework.security:spring-security-test](https://github.com/spring-projects/spring-security) | `6.5.0` | `6.5.1` | Updates `org.springframework:spring-orm` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-core` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-beans` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-aop` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-context` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-context-support` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-tx` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-jdbc` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-web` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-webmvc` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-expression` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-test` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-core` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-beans` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-aop` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-context` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-context-support` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-tx` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-jdbc` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-web` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-webmvc` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-expression` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework:spring-test` from 6.2.7 to 6.2.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.7...v6.2.8) Updates `org.springframework.boot:spring-boot-starter-test` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-thymeleaf` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-web` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-security` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-tomcat` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.security:spring-security-test` from 6.5.0 to 6.5.1 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/6.5.0...6.5.1) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-cache` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-thymeleaf` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-web` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-data-rest` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-security` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-aop` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) Updates `org.springframework.boot:spring-boot-starter-log4j2` from 3.5.0 to 3.5.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.0...v3.5.3) --- updated-dependencies: - dependency-name: org.springframework:spring-orm dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-core dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-beans dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-aop dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-context-support dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-tx dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-jdbc dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-web dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-webmvc dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-expression dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework:spring-test dependency-version: 6.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-test dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-thymeleaf dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-tomcat dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.security:spring-security-test dependency-version: 6.5.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-cache dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-thymeleaf dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-web dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-data-rest dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-security dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-aop dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-actuator dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring - dependency-name: org.springframework.boot:spring-boot-starter-log4j2 dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 29b3d93836b9..e34a3c1bd509 100644 --- a/pom.xml +++ b/pom.xml @@ -19,9 +19,9 @@ 17 - 6.2.7 - 3.5.0 - 6.5.0 + 6.2.8 + 3.5.3 + 6.5.1 6.4.8.Final 8.0.2.Final 42.7.7 From d90065ee9a851d1ff651edc60872e688205d5806 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Thu, 10 Jul 2025 16:00:34 +0200 Subject: [PATCH 623/632] Allow trusted XML builder to enforce base path for entities --- .../org/dspace/app/util/DCInputsReader.java | 19 ++-- .../app/util/SubmissionConfigReader.java | 10 +- .../java/org/dspace/app/util/XMLUtils.java | 94 +++++++++++++++++-- 3 files changed, 99 insertions(+), 24 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java index d2f3ac0dc5d9..293ceaac47d7 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java @@ -8,6 +8,7 @@ package org.dspace.app.util; import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -118,19 +119,17 @@ private void buildInputs(String fileName) formDefns = new HashMap>>>(); valuePairs = new HashMap>(); - String uri = "file:" + new File(fileName).getAbsolutePath(); + File inputFile = new File(fileName); + String inputFileDir = inputFile.toPath().normalize().getParent().toString(); + + String uri = "file:" + inputFile.getAbsolutePath(); try { - // This document builder factory will *not* disable external + // This document builder will *not* disable external // entities as they can be useful in managing large forms, but - // it is up to site administrators to validate the XML they are - // storing - DocumentBuilderFactory factory = XMLUtils.getTrustedDocumentBuilderFactory(); - factory.setValidating(false); - factory.setIgnoringComments(true); - factory.setIgnoringElementContentWhitespace(true); - - DocumentBuilder db = factory.newDocumentBuilder(); + // it will restrict them to be within the directory that the + // current input form XML file exists (or a sub-directory) + DocumentBuilder db = XMLUtils.getTrustedDocumentBuilder(inputFileDir); Document doc = db.parse(uri); doNodes(doc); checkValues(); diff --git a/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java b/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java index 64e62317c515..5b487045a0d9 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java @@ -172,14 +172,8 @@ private void buildInputs(String fileName) throws SubmissionConfigReaderException try { // This document builder factory will *not* disable external // entities as they can be useful in managing large forms, but - // it is up to site administrators to validate the XML they are - // storing - DocumentBuilderFactory factory = XMLUtils.getTrustedDocumentBuilderFactory(); - factory.setValidating(false); - factory.setIgnoringComments(true); - factory.setIgnoringElementContentWhitespace(true); - - DocumentBuilder db = factory.newDocumentBuilder(); + // it will restrict them to the config dir containing submission definitions + DocumentBuilder db = XMLUtils.getTrustedDocumentBuilder(configDir); Document doc = db.parse(uri); doNodes(doc); } catch (FactoryConfigurationError fe) { diff --git a/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java b/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java index 389d53fe6da4..6b419a0485e8 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java +++ b/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java @@ -7,7 +7,13 @@ */ package org.dspace.app.util; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -18,6 +24,9 @@ import org.jdom2.input.SAXBuilder; import org.w3c.dom.Element; import org.w3c.dom.NodeList; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; /** * Simple class to read information from small XML using DOM manipulation @@ -211,27 +220,36 @@ public static DocumentBuilderFactory getDocumentBuilderFactory() } /** - * Initialize and return a javax DocumentBuilder with NO security + * Initialize and return a javax DocumentBuilder with less security * applied. This is intended only for internal, administrative/configuration * use where external entities and other dangerous features are actually - * purposefully included. + * purposefully included, but are only allowed from specified paths, e.g. + * dspace.dir or some other path specified by the java caller. * The method here is tiny, but may be expanded with other features like * whitespace handling, and calling this method name helps to document * the fact that the caller knows it is trusting the XML source / builder + *

    + * If no allowedPaths are passed, then all external entities are rejected * * @return document builder with no security features set - * @throws ParserConfigurationException + * @throws ParserConfigurationException if the builder can not be configured */ - public static DocumentBuilder getTrustedDocumentBuilder() + public static DocumentBuilder getTrustedDocumentBuilder(String... allowedPaths) throws ParserConfigurationException { - return getTrustedDocumentBuilderFactory().newDocumentBuilder(); + DocumentBuilderFactory factory = getTrustedDocumentBuilderFactory(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setEntityResolver(new PathRestrictedEntityResolver(allowedPaths)); + return factory.newDocumentBuilder(); } /** * Initialize and return the javax DocumentBuilder with some basic security applied * to avoid XXE attacks and other unwanted content inclusion * @return document builder for use in XML parsing - * @throws ParserConfigurationException + * @throws ParserConfigurationException if the builder can not be configured */ public static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException { @@ -284,4 +302,68 @@ public static XMLInputFactory getXMLInputFactory() { return xmlInputFactory; } + /** + * This entity resolver accepts one or more path strings in its + * constructor and throws a SAXException if the entity systemID + * is not within the allowed path (or a subdirectory). + * If no parameters are passed, then this effectively disallows + * any external entity resolution. + */ + public static class PathRestrictedEntityResolver implements EntityResolver { + private final List allowedBasePaths; + + public PathRestrictedEntityResolver(String... allowedBasePaths) { + this.allowedBasePaths = Arrays.asList(allowedBasePaths); + } + + @Override + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + + if (systemId == null) { + return null; + } + + String filePath; + if (systemId.startsWith("file://")) { + filePath = systemId.substring(7); + } else if (systemId.startsWith("file:")) { + filePath = systemId.substring(5); + } else if (!systemId.contains("://")) { + filePath = systemId; + } else { + throw new SAXException("External resources not allowed: " + systemId + + ". Only local file paths are permitted."); + } + + Path resolvedPath; + try { + resolvedPath = Paths.get(filePath).toAbsolutePath().normalize(); + } catch (Exception e) { + throw new SAXException("Invalid path: " + systemId, e); + } + + boolean isAllowed = false; + for (String basePath : allowedBasePaths) { + Path allowedPath = Paths.get(basePath).toAbsolutePath().normalize(); + if (resolvedPath.startsWith(allowedPath)) { + isAllowed = true; + break; + } + } + + if (!isAllowed) { + throw new SAXException("Access denied to path: " + resolvedPath); + } + + File file = resolvedPath.toFile(); + if (!file.exists() || !file.canRead()) { + throw new SAXException("File not found or not readable: " + resolvedPath); + } + + return new InputSource(new FileInputStream(file)); + } + } + + } From 85dbfd22190c5f942f9fe04b5675c4291ea67840 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 11 Jul 2025 13:51:03 -0500 Subject: [PATCH 624/632] Update LICENSES_THIRD_PARTY to prepare for 8.2 release --- LICENSES_THIRD_PARTY | 299 ++++++++++++++++++++++--------------------- pom.xml | 4 +- 2 files changed, 157 insertions(+), 146 deletions(-) diff --git a/LICENSES_THIRD_PARTY b/LICENSES_THIRD_PARTY index 5049903ffc62..5d99bd7e426c 100644 --- a/LICENSES_THIRD_PARTY +++ b/LICENSES_THIRD_PARTY @@ -21,29 +21,29 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines Apache Software License, Version 2.0: * Ant-Contrib Tasks (ant-contrib:ant-contrib:1.0b3 - http://ant-contrib.sourceforge.net) - * AWS SDK for Java - Core (com.amazonaws:aws-java-sdk-core:1.12.780 - https://aws.amazon.com/sdkforjava) - * AWS Java SDK for AWS KMS (com.amazonaws:aws-java-sdk-kms:1.12.780 - https://aws.amazon.com/sdkforjava) - * AWS Java SDK for Amazon S3 (com.amazonaws:aws-java-sdk-s3:1.12.780 - https://aws.amazon.com/sdkforjava) - * JMES Path Query library (com.amazonaws:jmespath-java:1.12.780 - https://aws.amazon.com/sdkforjava) + * AWS SDK for Java - Core (com.amazonaws:aws-java-sdk-core:1.12.785 - https://aws.amazon.com/sdkforjava) + * AWS Java SDK for AWS KMS (com.amazonaws:aws-java-sdk-kms:1.12.785 - https://aws.amazon.com/sdkforjava) + * AWS Java SDK for Amazon S3 (com.amazonaws:aws-java-sdk-s3:1.12.785 - https://aws.amazon.com/sdkforjava) + * JMES Path Query library (com.amazonaws:jmespath-java:1.12.785 - https://aws.amazon.com/sdkforjava) * Titanium JSON-LD 1.1 (JRE11) (com.apicatalog:titanium-json-ld:1.3.2 - https://github.com/filip26/titanium-json-ld) * HPPC Collections (com.carrotsearch:hppc:0.8.1 - http://labs.carrotsearch.com/hppc.html/hppc) * com.drewnoakes:metadata-extractor (com.drewnoakes:metadata-extractor:2.19.0 - https://drewnoakes.com/code/exif/) * parso (com.epam:parso:2.0.14 - https://github.com/epam/parso) * Internet Time Utility (com.ethlo.time:itu:1.7.0 - https://github.com/ethlo/itu) * ClassMate (com.fasterxml:classmate:1.7.0 - https://github.com/FasterXML/java-classmate) - * Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.18.2 - https://github.com/FasterXML/jackson) - * Jackson-core (com.fasterxml.jackson.core:jackson-core:2.18.2 - https://github.com/FasterXML/jackson-core) - * jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.18.2 - https://github.com/FasterXML/jackson) + * Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.19.1 - https://github.com/FasterXML/jackson) + * Jackson-core (com.fasterxml.jackson.core:jackson-core:2.19.1 - https://github.com/FasterXML/jackson-core) + * jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.19.1 - https://github.com/FasterXML/jackson) * Jackson dataformat: CBOR (com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.17.2 - https://github.com/FasterXML/jackson-dataformats-binary) * Jackson dataformat: Smile (com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.15.2 - https://github.com/FasterXML/jackson-dataformats-binary) * Jackson-dataformat-TOML (com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2 - https://github.com/FasterXML/jackson-dataformats-text) * Jackson-dataformat-YAML (com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.2 - https://github.com/FasterXML/jackson-dataformats-text) - * Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8) - * Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310) + * Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.19.1 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8) + * Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.19.1 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310) * Jackson Jakarta-RS: base (com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-base:2.16.2 - https://github.com/FasterXML/jackson-jakarta-rs-providers/jackson-jakarta-rs-base) * Jackson Jakarta-RS: JSON (com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-json-provider:2.16.2 - https://github.com/FasterXML/jackson-jakarta-rs-providers/jackson-jakarta-rs-json-provider) * Jackson module: Jakarta XML Bind Annotations (jakarta.xml.bind) (com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.16.2 - https://github.com/FasterXML/jackson-modules-base) - * Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.18.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names) + * Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.19.1 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names) * Java UUID Generator (com.fasterxml.uuid:java-uuid-generator:4.1.0 - https://github.com/cowtowncoder/java-uuid-generator) * Woodstox (com.fasterxml.woodstox:woodstox-core:6.5.1 - https://github.com/FasterXML/woodstox) * zjsonpatch (com.flipkart.zjsonpatch:zjsonpatch:0.4.16 - https://github.com/flipkart-incubator/zjsonpatch/) @@ -60,17 +60,16 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * uri-template (com.github.java-json-tools:uri-template:0.10 - https://github.com/java-json-tools/uri-template) * JCIP Annotations under Apache License (com.github.stephenc.jcip:jcip-annotations:1.0-1 - http://stephenc.github.com/jcip-annotations) * FindBugs-jsr305 (com.google.code.findbugs:jsr305:3.0.2 - http://findbugs.sourceforge.net/) - * Gson (com.google.code.gson:gson:2.11.0 - https://github.com/google/gson) - * error-prone annotations (com.google.errorprone:error_prone_annotations:2.36.0 - https://errorprone.info/error_prone_annotations) + * Gson (com.google.code.gson:gson:2.13.1 - https://github.com/google/gson) + * error-prone annotations (com.google.errorprone:error_prone_annotations:2.38.0 - https://errorprone.info/error_prone_annotations) * Guava InternalFutureFailureAccess and InternalFutures (com.google.guava:failureaccess:1.0.1 - https://github.com/google/guava/failureaccess) * Guava: Google Core Libraries for Java (com.google.guava:guava:32.1.3-jre - https://github.com/google/guava) * Guava ListenableFuture only (com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava - https://github.com/google/guava/listenablefuture) * J2ObjC Annotations (com.google.j2objc:j2objc-annotations:1.3 - https://github.com/google/j2objc/) * J2ObjC Annotations (com.google.j2objc:j2objc-annotations:2.8 - https://github.com/google/j2objc/) - * ConcurrentLinkedHashMap (com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2 - http://code.google.com/p/concurrentlinkedhashmap) * libphonenumber (com.googlecode.libphonenumber:libphonenumber:8.11.1 - https://github.com/google/libphonenumber/) - * Jackcess (com.healthmarketscience.jackcess:jackcess:4.0.5 - https://jackcess.sourceforge.io) - * Jackcess Encrypt (com.healthmarketscience.jackcess:jackcess-encrypt:4.0.2 - http://jackcessencrypt.sf.net) + * Jackcess (com.healthmarketscience.jackcess:jackcess:4.0.8 - https://jackcess.sourceforge.io) + * Jackcess Encrypt (com.healthmarketscience.jackcess:jackcess-encrypt:4.0.3 - http://jackcessencrypt.sf.net) * json-path (com.jayway.jsonpath:json-path:2.9.0 - https://github.com/jayway/JsonPath) * json-path-assert (com.jayway.jsonpath:json-path-assert:2.9.0 - https://github.com/jayway/JsonPath) * Disruptor Framework (com.lmax:disruptor:3.4.2 - http://lmax-exchange.github.com/disruptor) @@ -79,11 +78,15 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * JsonSchemaValidator (com.networknt:json-schema-validator:1.0.76 - https://github.com/networknt/json-schema-validator) * Nimbus JOSE+JWT (com.nimbusds:nimbus-jose-jwt:9.28 - https://bitbucket.org/connect2id/nimbus-jose-jwt) * Nimbus JOSE+JWT (com.nimbusds:nimbus-jose-jwt:9.48 - https://bitbucket.org/connect2id/nimbus-jose-jwt) - * opencsv (com.opencsv:opencsv:5.10 - http://opencsv.sf.net) + * opencsv (com.opencsv:opencsv:5.11.1 - http://opencsv.sf.net) * java-libpst (com.pff:java-libpst:0.9.3 - https://github.com/rjohnsondev/java-libpst) * rome (com.rometools:rome:1.19.0 - http://rometools.com/rome) * rome-modules (com.rometools:rome-modules:1.19.0 - http://rometools.com/rome-modules) * rome-utils (com.rometools:rome-utils:1.19.0 - http://rometools.com/rome-utils) + * mockwebserver (com.squareup.okhttp3:mockwebserver:4.12.0 - https://square.github.io/okhttp/) + * okhttp (com.squareup.okhttp3:okhttp:4.12.0 - https://square.github.io/okhttp/) + * okio (com.squareup.okio:okio:3.6.0 - https://github.com/square/okio/) + * okio (com.squareup.okio:okio-jvm:3.6.0 - https://github.com/square/okio/) * T-Digest (com.tdunning:t-digest:3.1 - https://github.com/tdunning/t-digest) * config (com.typesafe:config:1.3.3 - https://github.com/lightbend/config) * ssl-config-core (com.typesafe:ssl-config-core_2.13:0.3.8 - https://github.com/lightbend/ssl-config) @@ -96,14 +99,14 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * scala-logging (com.typesafe.scala-logging:scala-logging_2.13:3.9.2 - https://github.com/lightbend/scala-logging) * JSON library from Android SDK (com.vaadin.external.google:android-json:0.0.20131108.vaadin1 - http://developer.android.com/sdk) * SparseBitSet (com.zaxxer:SparseBitSet:1.3 - https://github.com/brettwooldridge/SparseBitSet) - * Apache Commons BeanUtils (commons-beanutils:commons-beanutils:1.10.0 - https://commons.apache.org/proper/commons-beanutils) + * Apache Commons BeanUtils (commons-beanutils:commons-beanutils:1.11.0 - https://commons.apache.org/proper/commons-beanutils) * Apache Commons CLI (commons-cli:commons-cli:1.9.0 - https://commons.apache.org/proper/commons-cli/) - * Apache Commons Codec (commons-codec:commons-codec:1.17.2 - https://commons.apache.org/proper/commons-codec/) + * Apache Commons Codec (commons-codec:commons-codec:1.18.0 - https://commons.apache.org/proper/commons-codec/) * Apache Commons Collections (commons-collections:commons-collections:3.2.2 - http://commons.apache.org/collections/) * Commons Digester (commons-digester:commons-digester:2.1 - http://commons.apache.org/digester/) - * Apache Commons IO (commons-io:commons-io:2.18.0 - https://commons.apache.org/proper/commons-io/) + * Apache Commons IO (commons-io:commons-io:2.19.0 - https://commons.apache.org/proper/commons-io/) * Commons Lang (commons-lang:commons-lang:2.6 - http://commons.apache.org/lang/) - * Apache Commons Logging (commons-logging:commons-logging:1.3.4 - https://commons.apache.org/proper/commons-logging/) + * Apache Commons Logging (commons-logging:commons-logging:1.3.5 - https://commons.apache.org/proper/commons-logging/) * Apache Commons Validator (commons-validator:commons-validator:1.9.0 - http://commons.apache.org/proper/commons-validator/) * GeoJson POJOs for Jackson (de.grundid.opendatalab:geojson-jackson:1.14 - https://github.com/opendatalab-de/geojson-jackson) * broker-client (eu.openaire:broker-client:1.1.2 - http://api.openaire.eu/broker/broker-client) @@ -114,12 +117,10 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Metrics Integration with JMX (io.dropwizard.metrics:metrics-jmx:4.1.5 - https://metrics.dropwizard.io/metrics-jmx) * JVM Integration for Metrics (io.dropwizard.metrics:metrics-jvm:4.1.5 - https://metrics.dropwizard.io/metrics-jvm) * SWORD v2 Common Server Library (forked) (io.gdcc:sword2-server:2.0.0 - https://github.com/gdcc/sword2-server) - * micrometer-commons (io.micrometer:micrometer-commons:1.14.2 - https://github.com/micrometer-metrics/micrometer) - * micrometer-commons (io.micrometer:micrometer-commons:1.14.3 - https://github.com/micrometer-metrics/micrometer) - * micrometer-core (io.micrometer:micrometer-core:1.14.3 - https://github.com/micrometer-metrics/micrometer) - * micrometer-jakarta9 (io.micrometer:micrometer-jakarta9:1.14.3 - https://github.com/micrometer-metrics/micrometer) - * micrometer-observation (io.micrometer:micrometer-observation:1.14.2 - https://github.com/micrometer-metrics/micrometer) - * micrometer-observation (io.micrometer:micrometer-observation:1.14.3 - https://github.com/micrometer-metrics/micrometer) + * micrometer-commons (io.micrometer:micrometer-commons:1.14.8 - https://github.com/micrometer-metrics/micrometer) + * micrometer-core (io.micrometer:micrometer-core:1.15.1 - https://github.com/micrometer-metrics/micrometer) + * micrometer-jakarta9 (io.micrometer:micrometer-jakarta9:1.15.1 - https://github.com/micrometer-metrics/micrometer) + * micrometer-observation (io.micrometer:micrometer-observation:1.14.8 - https://github.com/micrometer-metrics/micrometer) * Netty/Buffer (io.netty:netty-buffer:4.1.99.Final - https://netty.io/netty-buffer/) * Netty/Codec (io.netty:netty-codec:4.1.99.Final - https://netty.io/netty-codec/) * Netty/Codec/HTTP (io.netty:netty-codec-http:4.1.86.Final - https://netty.io/netty-codec-http/) @@ -167,16 +168,17 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Jakarta Bean Validation API (jakarta.validation:jakarta.validation-api:3.0.2 - https://beanvalidation.org) * JSR107 API and SPI (javax.cache:cache-api:1.1.1 - https://github.com/jsr107/jsr107spec) * jdbm (jdbm:jdbm:1.0 - no url defined) - * Joda-Time (joda-time:joda-time:2.13.0 - https://www.joda.org/joda-time/) - * Byte Buddy (without dependencies) (net.bytebuddy:byte-buddy:1.16.1 - https://bytebuddy.net/byte-buddy) + * Joda-Time (joda-time:joda-time:2.12.7 - https://www.joda.org/joda-time/) + * Byte Buddy (without dependencies) (net.bytebuddy:byte-buddy:1.11.13 - https://bytebuddy.net/byte-buddy) + * Byte Buddy (without dependencies) (net.bytebuddy:byte-buddy:1.14.11 - https://bytebuddy.net/byte-buddy) * Byte Buddy agent (net.bytebuddy:byte-buddy-agent:1.11.13 - https://bytebuddy.net/byte-buddy-agent) * eigenbase-properties (net.hydromatic:eigenbase-properties:1.1.5 - http://github.com/julianhyde/eigenbase-properties) * json-unit-core (net.javacrumbs.json-unit:json-unit-core:2.36.0 - https://github.com/lukas-krecan/JsonUnit/json-unit-core) * "Java Concurrency in Practice" book annotations (net.jcip:jcip-annotations:1.0 - http://jcip.net/) * ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.5.0 - https://urielch.github.io/) - * ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.5.1 - https://urielch.github.io/) + * ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.5.2 - https://urielch.github.io/) * JSON Small and Fast Parser (net.minidev:json-smart:2.5.0 - https://urielch.github.io/) - * JSON Small and Fast Parser (net.minidev:json-smart:2.5.1 - https://urielch.github.io/) + * JSON Small and Fast Parser (net.minidev:json-smart:2.5.2 - https://urielch.github.io/) * Abdera Core (org.apache.abdera:abdera-core:1.1.3 - http://abdera.apache.org/abdera-core) * I18N Libraries (org.apache.abdera:abdera-i18n:1.1.3 - http://abdera.apache.org) * Abdera Parser (org.apache.abdera:abdera-parser:1.1.3 - http://abdera.apache.org/abdera-parser) @@ -187,18 +189,18 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Calcite Linq4j (org.apache.calcite:calcite-linq4j:1.35.0 - https://calcite.apache.org) * Apache Calcite Avatica (org.apache.calcite.avatica:avatica-core:1.23.0 - https://calcite.apache.org/avatica) * Apache Calcite Avatica Metrics (org.apache.calcite.avatica:avatica-metrics:1.23.0 - https://calcite.apache.org/avatica) - * Apache Commons Collections (org.apache.commons:commons-collections4:4.4 - https://commons.apache.org/proper/commons-collections/) + * Apache Commons Collections (org.apache.commons:commons-collections4:4.5.0 - https://commons.apache.org/proper/commons-collections/) * Apache Commons Compress (org.apache.commons:commons-compress:1.27.1 - https://commons.apache.org/proper/commons-compress/) - * Apache Commons Configuration (org.apache.commons:commons-configuration2:2.11.0 - https://commons.apache.org/proper/commons-configuration/) - * Apache Commons CSV (org.apache.commons:commons-csv:1.13.0 - https://commons.apache.org/proper/commons-csv/) + * Apache Commons Configuration (org.apache.commons:commons-configuration2:2.12.0 - https://commons.apache.org/proper/commons-configuration/) + * Apache Commons CSV (org.apache.commons:commons-csv:1.14.0 - https://commons.apache.org/proper/commons-csv/) * Apache Commons DBCP (org.apache.commons:commons-dbcp2:2.13.0 - https://commons.apache.org/proper/commons-dbcp/) * Apache Commons Digester (org.apache.commons:commons-digester3:3.2 - http://commons.apache.org/digester/) * Apache Commons Exec (org.apache.commons:commons-exec:1.3 - http://commons.apache.org/proper/commons-exec/) * Apache Commons Exec (org.apache.commons:commons-exec:1.4.0 - https://commons.apache.org/proper/commons-exec/) * Apache Commons Lang (org.apache.commons:commons-lang3:3.17.0 - https://commons.apache.org/proper/commons-lang/) * Apache Commons Math (org.apache.commons:commons-math3:3.6.1 - http://commons.apache.org/proper/commons-math/) - * Apache Commons Pool (org.apache.commons:commons-pool2:2.12.0 - https://commons.apache.org/proper/commons-pool/) - * Apache Commons Text (org.apache.commons:commons-text:1.13.0 - https://commons.apache.org/proper/commons-text) + * Apache Commons Pool (org.apache.commons:commons-pool2:2.12.1 - https://commons.apache.org/proper/commons-pool/) + * Apache Commons Text (org.apache.commons:commons-text:1.13.1 - https://commons.apache.org/proper/commons-text) * Curator Client (org.apache.curator:curator-client:2.13.0 - http://curator.apache.org/curator-client) * Curator Framework (org.apache.curator:curator-framework:2.13.0 - http://curator.apache.org/curator-framework) * Curator Recipes (org.apache.curator:curator-recipes:2.13.0 - http://curator.apache.org/curator-recipes) @@ -212,13 +214,13 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.16 - http://hc.apache.org/httpcomponents-core-ga) * Apache HttpClient Mime (org.apache.httpcomponents:httpmime:4.5.14 - http://hc.apache.org/httpcomponents-client-ga) * Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.1.3 - https://hc.apache.org/httpcomponents-client-5.0.x/5.1.3/httpclient5/) - * Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.4.1 - https://hc.apache.org/httpcomponents-client-5.4.x/5.4.1/httpclient5/) + * Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.5 - https://hc.apache.org/httpcomponents-client-5.5.x/5.5/httpclient5/) * Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.1.3 - https://hc.apache.org/httpcomponents-core-5.1.x/5.1.3/httpcore5/) - * Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.3.1 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.1/httpcore5/) + * Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.3.4 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.4/httpcore5/) * Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.1.3 - https://hc.apache.org/httpcomponents-core-5.1.x/5.1.3/httpcore5-h2/) - * Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.3.1 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.1/httpcore5-h2/) + * Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.3.4 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.4/httpcore5-h2/) * Apache James :: Mime4j :: Core (org.apache.james:apache-mime4j-core:0.8.12 - http://james.apache.org/mime4j/apache-mime4j-core) - * Apache James :: Mime4j :: DOM (org.apache.james:apache-mime4j-dom:0.8.11 - http://james.apache.org/mime4j/apache-mime4j-dom) + * Apache James :: Mime4j :: DOM (org.apache.james:apache-mime4j-dom:0.8.12 - http://james.apache.org/mime4j/apache-mime4j-dom) * Apache Jena - Libraries POM (org.apache.jena:apache-jena-libs:4.10.0 - https://jena.apache.org/apache-jena-libs/) * Apache Jena - ARQ (org.apache.jena:jena-arq:4.10.0 - https://jena.apache.org/jena-arq/) * Apache Jena - Base (org.apache.jena:jena-base:4.10.0 - https://jena.apache.org/jena-base/) @@ -270,59 +272,60 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Lucene Spatial Extras (org.apache.lucene:lucene-spatial-extras:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-spatial-extras) * Lucene Spatial 3D (org.apache.lucene:lucene-spatial3d:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-spatial3d) * Lucene Suggest (org.apache.lucene:lucene-suggest:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-suggest) - * Apache FontBox (org.apache.pdfbox:fontbox:2.0.33 - http://pdfbox.apache.org/) + * Apache FontBox (org.apache.pdfbox:fontbox:2.0.34 - http://pdfbox.apache.org/) * PDFBox JBIG2 ImageIO plugin (org.apache.pdfbox:jbig2-imageio:3.0.4 - https://www.apache.org/jbig2-imageio/) * Apache JempBox (org.apache.pdfbox:jempbox:1.8.17 - http://www.apache.org/pdfbox-parent/jempbox/) - * Apache PDFBox (org.apache.pdfbox:pdfbox:2.0.33 - https://www.apache.org/pdfbox-parent/pdfbox/) - * Apache PDFBox tools (org.apache.pdfbox:pdfbox-tools:2.0.31 - https://www.apache.org/pdfbox-parent/pdfbox-tools/) - * Apache XmpBox (org.apache.pdfbox:xmpbox:2.0.31 - https://www.apache.org/pdfbox-parent/xmpbox/) - * Apache POI - Common (org.apache.poi:poi:5.2.5 - https://poi.apache.org/) - * Apache POI - API based on OPC and OOXML schemas (org.apache.poi:poi-ooxml:5.2.5 - https://poi.apache.org/) - * Apache POI (org.apache.poi:poi-ooxml-lite:5.2.5 - https://poi.apache.org/) - * Apache POI (org.apache.poi:poi-scratchpad:5.2.5 - https://poi.apache.org/) + * Apache PDFBox (org.apache.pdfbox:pdfbox:2.0.34 - https://www.apache.org/pdfbox-parent/pdfbox/) + * Apache PDFBox tools (org.apache.pdfbox:pdfbox-tools:2.0.34 - https://www.apache.org/pdfbox-parent/pdfbox-tools/) + * Apache XmpBox (org.apache.pdfbox:xmpbox:2.0.34 - https://www.apache.org/pdfbox-parent/xmpbox/) + * Apache POI - Common (org.apache.poi:poi:5.4.1 - https://poi.apache.org/) + * Apache POI - API based on OPC and OOXML schemas (org.apache.poi:poi-ooxml:5.4.1 - https://poi.apache.org/) + * Apache POI (org.apache.poi:poi-ooxml-lite:5.4.1 - https://poi.apache.org/) + * Apache POI (org.apache.poi:poi-scratchpad:5.4.1 - https://poi.apache.org/) * Apache Solr Core (org.apache.solr:solr-core:8.11.4 - https://lucene.apache.org/solr-parent/solr-core) * Apache Solr Solrj (org.apache.solr:solr-solrj:8.11.4 - https://lucene.apache.org/solr-parent/solr-solrj) * Apache Standard Taglib Implementation (org.apache.taglibs:taglibs-standard-impl:1.2.5 - http://tomcat.apache.org/taglibs/standard-1.2.5/taglibs-standard-impl) * Apache Standard Taglib Specification API (org.apache.taglibs:taglibs-standard-spec:1.2.5 - http://tomcat.apache.org/taglibs/standard-1.2.5/taglibs-standard-spec) * Apache Thrift (org.apache.thrift:libthrift:0.19.0 - http://thrift.apache.org) - * Apache Tika core (org.apache.tika:tika-core:2.9.2 - https://tika.apache.org/) - * Apache Tika Apple parser module (org.apache.tika:tika-parser-apple-module:2.9.2 - https://tika.apache.org/tika-parser-apple-module/) - * Apache Tika audiovideo parser module (org.apache.tika:tika-parser-audiovideo-module:2.9.2 - https://tika.apache.org/tika-parser-audiovideo-module/) - * Apache Tika cad parser module (org.apache.tika:tika-parser-cad-module:2.9.2 - https://tika.apache.org/tika-parser-cad-module/) - * Apache Tika code parser module (org.apache.tika:tika-parser-code-module:2.9.2 - https://tika.apache.org/tika-parser-code-module/) - * Apache Tika crypto parser module (org.apache.tika:tika-parser-crypto-module:2.9.2 - https://tika.apache.org/tika-parser-crypto-module/) - * Apache Tika digest commons (org.apache.tika:tika-parser-digest-commons:2.9.2 - https://tika.apache.org/tika-parser-digest-commons/) - * Apache Tika font parser module (org.apache.tika:tika-parser-font-module:2.9.2 - https://tika.apache.org/tika-parser-font-module/) - * Apache Tika html parser module (org.apache.tika:tika-parser-html-module:2.9.2 - https://tika.apache.org/tika-parser-html-module/) - * Apache Tika image parser module (org.apache.tika:tika-parser-image-module:2.9.2 - https://tika.apache.org/tika-parser-image-module/) - * Apache Tika mail commons (org.apache.tika:tika-parser-mail-commons:2.9.2 - https://tika.apache.org/tika-parser-mail-commons/) - * Apache Tika mail parser module (org.apache.tika:tika-parser-mail-module:2.9.2 - https://tika.apache.org/tika-parser-mail-module/) - * Apache Tika Microsoft parser module (org.apache.tika:tika-parser-microsoft-module:2.9.2 - https://tika.apache.org/tika-parser-microsoft-module/) - * Apache Tika miscellaneous office format parser module (org.apache.tika:tika-parser-miscoffice-module:2.9.2 - https://tika.apache.org/tika-parser-miscoffice-module/) - * Apache Tika news parser module (org.apache.tika:tika-parser-news-module:2.9.2 - https://tika.apache.org/tika-parser-news-module/) - * Apache Tika OCR parser module (org.apache.tika:tika-parser-ocr-module:2.9.2 - https://tika.apache.org/tika-parser-ocr-module/) - * Apache Tika PDF parser module (org.apache.tika:tika-parser-pdf-module:2.9.2 - https://tika.apache.org/tika-parser-pdf-module/) - * Apache Tika package parser module (org.apache.tika:tika-parser-pkg-module:2.9.2 - https://tika.apache.org/tika-parser-pkg-module/) - * Apache Tika text parser module (org.apache.tika:tika-parser-text-module:2.9.2 - https://tika.apache.org/tika-parser-text-module/) - * Apache Tika WARC parser module (org.apache.tika:tika-parser-webarchive-module:2.9.2 - https://tika.apache.org/tika-parser-webarchive-module/) - * Apache Tika XML parser module (org.apache.tika:tika-parser-xml-module:2.9.2 - https://tika.apache.org/tika-parser-xml-module/) - * Apache Tika XMP commons (org.apache.tika:tika-parser-xmp-commons:2.9.2 - https://tika.apache.org/tika-parser-xmp-commons/) - * Apache Tika ZIP commons (org.apache.tika:tika-parser-zip-commons:2.9.2 - https://tika.apache.org/tika-parser-zip-commons/) - * Apache Tika standard parser package (org.apache.tika:tika-parsers-standard-package:2.9.2 - https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) - * tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:10.1.34 - https://tomcat.apache.org/) - * tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:10.1.34 - https://tomcat.apache.org/) - * tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:10.1.34 - https://tomcat.apache.org/) + * Apache Tika core (org.apache.tika:tika-core:2.9.4 - https://tika.apache.org/) + * Apache Tika Apple parser module (org.apache.tika:tika-parser-apple-module:2.9.4 - https://tika.apache.org/tika-parser-apple-module/) + * Apache Tika audiovideo parser module (org.apache.tika:tika-parser-audiovideo-module:2.9.4 - https://tika.apache.org/tika-parser-audiovideo-module/) + * Apache Tika cad parser module (org.apache.tika:tika-parser-cad-module:2.9.4 - https://tika.apache.org/tika-parser-cad-module/) + * Apache Tika code parser module (org.apache.tika:tika-parser-code-module:2.9.4 - https://tika.apache.org/tika-parser-code-module/) + * Apache Tika crypto parser module (org.apache.tika:tika-parser-crypto-module:2.9.4 - https://tika.apache.org/tika-parser-crypto-module/) + * Apache Tika digest commons (org.apache.tika:tika-parser-digest-commons:2.9.4 - https://tika.apache.org/tika-parser-digest-commons/) + * Apache Tika font parser module (org.apache.tika:tika-parser-font-module:2.9.4 - https://tika.apache.org/tika-parser-font-module/) + * Apache Tika html parser module (org.apache.tika:tika-parser-html-module:2.9.4 - https://tika.apache.org/tika-parser-html-module/) + * Apache Tika image parser module (org.apache.tika:tika-parser-image-module:2.9.4 - https://tika.apache.org/tika-parser-image-module/) + * Apache Tika mail commons (org.apache.tika:tika-parser-mail-commons:2.9.4 - https://tika.apache.org/tika-parser-mail-commons/) + * Apache Tika mail parser module (org.apache.tika:tika-parser-mail-module:2.9.4 - https://tika.apache.org/tika-parser-mail-module/) + * Apache Tika Microsoft parser module (org.apache.tika:tika-parser-microsoft-module:2.9.4 - https://tika.apache.org/tika-parser-microsoft-module/) + * Apache Tika miscellaneous office format parser module (org.apache.tika:tika-parser-miscoffice-module:2.9.4 - https://tika.apache.org/tika-parser-miscoffice-module/) + * Apache Tika news parser module (org.apache.tika:tika-parser-news-module:2.9.4 - https://tika.apache.org/tika-parser-news-module/) + * Apache Tika OCR parser module (org.apache.tika:tika-parser-ocr-module:2.9.4 - https://tika.apache.org/tika-parser-ocr-module/) + * Apache Tika PDF parser module (org.apache.tika:tika-parser-pdf-module:2.9.4 - https://tika.apache.org/tika-parser-pdf-module/) + * Apache Tika package parser module (org.apache.tika:tika-parser-pkg-module:2.9.4 - https://tika.apache.org/tika-parser-pkg-module/) + * Apache Tika text parser module (org.apache.tika:tika-parser-text-module:2.9.4 - https://tika.apache.org/tika-parser-text-module/) + * Apache Tika WARC parser module (org.apache.tika:tika-parser-webarchive-module:2.9.4 - https://tika.apache.org/tika-parser-webarchive-module/) + * Apache Tika XML parser module (org.apache.tika:tika-parser-xml-module:2.9.4 - https://tika.apache.org/tika-parser-xml-module/) + * Apache Tika XMP commons (org.apache.tika:tika-parser-xmp-commons:2.9.4 - https://tika.apache.org/tika-parser-xmp-commons/) + * Apache Tika ZIP commons (org.apache.tika:tika-parser-zip-commons:2.9.4 - https://tika.apache.org/tika-parser-zip-commons/) + * Apache Tika standard parser package (org.apache.tika:tika-parsers-standard-package:2.9.4 - https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) + * tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:10.1.42 - https://tomcat.apache.org/) + * tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:10.1.42 - https://tomcat.apache.org/) + * tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:10.1.42 - https://tomcat.apache.org/) * Apache Velocity - Engine (org.apache.velocity:velocity-engine-core:2.4.1 - http://velocity.apache.org/engine/devel/velocity-engine-core/) * Apache Velocity - JSR 223 Scripting (org.apache.velocity:velocity-engine-scripting:2.3 - http://velocity.apache.org/engine/devel/velocity-engine-scripting/) * Apache Velocity Tools - Generic tools (org.apache.velocity.tools:velocity-tools-generic:3.1 - https://velocity.apache.org/tools/devel/velocity-tools-generic/) * Axiom API (org.apache.ws.commons.axiom:axiom-api:1.2.14 - http://ws.apache.org/axiom/) * Axiom Impl (org.apache.ws.commons.axiom:axiom-impl:1.2.14 - http://ws.apache.org/axiom/) - * XmlBeans (org.apache.xmlbeans:xmlbeans:5.2.0 - https://xmlbeans.apache.org/) + * XmlBeans (org.apache.xmlbeans:xmlbeans:5.3.0 - https://xmlbeans.apache.org/) * Apache ZooKeeper - Server (org.apache.zookeeper:zookeeper:3.6.2 - http://zookeeper.apache.org/zookeeper) * Apache ZooKeeper - Jute (org.apache.zookeeper:zookeeper-jute:3.6.2 - http://zookeeper.apache.org/zookeeper-jute) * org.apiguardian:apiguardian-api (org.apiguardian:apiguardian-api:1.1.2 - https://github.com/apiguardian-team/apiguardian) - * AssertJ Core (org.assertj:assertj-core:3.26.3 - https://assertj.github.io/doc/#assertj-core) + * AssertJ Core (org.assertj:assertj-core:3.27.3 - https://assertj.github.io/doc/#assertj-core) * Evo Inflector (org.atteo:evo-inflector:1.3 - http://atteo.org/static/evo-inflector) + * attoparser (org.attoparser:attoparser:2.0.7.RELEASE - https://www.attoparser.org) * Awaitility (org.awaitility:awaitility:4.2.2 - http://awaitility.org) * jose4j (org.bitbucket.b_c:jose4j:0.6.5 - https://bitbucket.org/b_c/jose4j/) * TagSoup (org.ccil.cowan.tagsoup:tagsoup:1.2.1 - http://home.ccil.org/~cowan/XML/tagsoup/) @@ -376,24 +379,28 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common) * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) - * Hibernate Validator Engine (org.hibernate.validator:hibernate-validator:8.0.1.Final - http://hibernate.org/validator/hibernate-validator) - * Hibernate Validator Portable Extension (org.hibernate.validator:hibernate-validator-cdi:8.0.1.Final - http://hibernate.org/validator/hibernate-validator-cdi) + * Hibernate Validator Engine (org.hibernate.validator:hibernate-validator:8.0.2.Final - http://hibernate.org/validator/hibernate-validator) + * Hibernate Validator Portable Extension (org.hibernate.validator:hibernate-validator-cdi:8.0.2.Final - http://hibernate.org/validator/hibernate-validator-cdi) * org.immutables.value-annotations (org.immutables:value-annotations:2.9.2 - http://immutables.org/value-annotations) * leveldb (org.iq80.leveldb:leveldb:0.12 - http://github.com/dain/leveldb/leveldb) * leveldb-api (org.iq80.leveldb:leveldb-api:0.12 - http://github.com/dain/leveldb/leveldb-api) * Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/) * JBoss Logging 3 (org.jboss.logging:jboss-logging:3.6.1.Final - http://www.jboss.org) * JDOM (org.jdom:jdom2:2.0.6.1 - http://www.jdom.org) + * IntelliJ IDEA Annotations (org.jetbrains:annotations:13.0 - http://www.jetbrains.org) + * Kotlin Stdlib (org.jetbrains.kotlin:kotlin-stdlib:1.8.21 - https://kotlinlang.org/) + * Kotlin Stdlib Common (org.jetbrains.kotlin:kotlin-stdlib-common:1.8.21 - https://kotlinlang.org/) + * Kotlin Stdlib Jdk7 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21 - https://kotlinlang.org/) + * Kotlin Stdlib Jdk8 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21 - https://kotlinlang.org/) * Proj4J (org.locationtech.proj4j:proj4j:1.1.5 - https://github.com/locationtech/proj4j) * Spatial4J (org.locationtech.spatial4j:spatial4j:0.7 - https://projects.eclipse.org/projects/locationtech.spatial4j) * MockServer Java Client (org.mock-server:mockserver-client-java:5.15.0 - https://www.mock-server.com) * MockServer Core (org.mock-server:mockserver-core:5.15.0 - https://www.mock-server.com) * MockServer JUnit 4 Integration (org.mock-server:mockserver-junit-rule:5.15.0 - https://www.mock-server.com) * MockServer & Proxy Netty (org.mock-server:mockserver-netty:5.15.0 - https://www.mock-server.com) - * jwarc (org.netpreserve:jwarc:0.29.0 - https://github.com/iipc/jwarc) + * jwarc (org.netpreserve:jwarc:0.31.1 - https://github.com/iipc/jwarc) * Objenesis (org.objenesis:objenesis:3.2 - http://objenesis.org/objenesis) - * parboiled-core (org.parboiled:parboiled-core:1.1.7 - http://parboiled.org) - * parboiled-java (org.parboiled:parboiled-java:1.1.7 - http://parboiled.org) + * org.opentest4j:opentest4j (org.opentest4j:opentest4j:1.3.0 - https://github.com/ota4j-team/opentest4j) * org.roaringbitmap:RoaringBitmap (org.roaringbitmap:RoaringBitmap:1.0.0 - https://github.com/RoaringBitmap/RoaringBitmap) * RRD4J (org.rrd4j:rrd4j:3.5 - https://github.com/rrd4j/rrd4j/) * Scala Library (org.scala-lang:scala-library:2.13.2 - https://www.scala-lang.org/) @@ -403,53 +410,56 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * scala-parser-combinators (org.scala-lang.modules:scala-parser-combinators_2.13:1.1.2 - http://www.scala-lang.org/) * scala-xml (org.scala-lang.modules:scala-xml_2.13:1.3.0 - http://www.scala-lang.org/) * JSONassert (org.skyscreamer:jsonassert:1.5.3 - https://github.com/skyscreamer/JSONassert) - * JCL 1.2 implemented over SLF4J (org.slf4j:jcl-over-slf4j:2.0.16 - http://www.slf4j.org) - * Spring AOP (org.springframework:spring-aop:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Beans (org.springframework:spring-beans:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Context (org.springframework:spring-context:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Context Support (org.springframework:spring-context-support:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Core (org.springframework:spring-core:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Expression Language (SpEL) (org.springframework:spring-expression:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Commons Logging Bridge (org.springframework:spring-jcl:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring JDBC (org.springframework:spring-jdbc:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Object/Relational Mapping (org.springframework:spring-orm:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring TestContext Framework (org.springframework:spring-test:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Transaction (org.springframework:spring-tx:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Web (org.springframework:spring-web:6.2.2 - https://github.com/spring-projects/spring-framework) - * Spring Web MVC (org.springframework:spring-webmvc:6.2.2 - https://github.com/spring-projects/spring-framework) - * spring-boot (org.springframework.boot:spring-boot:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-actuator (org.springframework.boot:spring-boot-actuator:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:3.4.2 - https://spring.io/projects/spring-boot) - * Spring Boot Configuration Processor (org.springframework.boot:spring-boot-configuration-processor:2.0.0.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-tools/spring-boot-configuration-processor) - * spring-boot-starter (org.springframework.boot:spring-boot-starter:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-aop (org.springframework.boot:spring-boot-starter-aop:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-cache (org.springframework.boot:spring-boot-starter-cache:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-data-rest (org.springframework.boot:spring-boot-starter-data-rest:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-log4j2 (org.springframework.boot:spring-boot-starter-log4j2:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-security (org.springframework.boot:spring-boot-starter-security:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-test (org.springframework.boot:spring-boot-starter-test:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-test (org.springframework.boot:spring-boot-test:3.4.2 - https://spring.io/projects/spring-boot) - * spring-boot-test-autoconfigure (org.springframework.boot:spring-boot-test-autoconfigure:3.4.2 - https://spring.io/projects/spring-boot) - * Spring Data Core (org.springframework.data:spring-data-commons:3.4.2 - https://spring.io/projects/spring-data) - * Spring Data REST - Core (org.springframework.data:spring-data-rest-core:4.4.2 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-core) - * Spring Data REST - WebMVC (org.springframework.data:spring-data-rest-webmvc:4.4.2 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-webmvc) - * Spring HATEOAS (org.springframework.hateoas:spring-hateoas:2.4.1 - https://github.com/spring-projects/spring-hateoas) + * JCL 1.2 implemented over SLF4J (org.slf4j:jcl-over-slf4j:2.0.17 - http://www.slf4j.org) + * Spring AOP (org.springframework:spring-aop:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Beans (org.springframework:spring-beans:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Context (org.springframework:spring-context:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Context Support (org.springframework:spring-context-support:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Core (org.springframework:spring-core:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Expression Language (SpEL) (org.springframework:spring-expression:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Commons Logging Bridge (org.springframework:spring-jcl:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring JDBC (org.springframework:spring-jdbc:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Object/Relational Mapping (org.springframework:spring-orm:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring TestContext Framework (org.springframework:spring-test:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Transaction (org.springframework:spring-tx:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Web (org.springframework:spring-web:6.2.8 - https://github.com/spring-projects/spring-framework) + * Spring Web MVC (org.springframework:spring-webmvc:6.2.8 - https://github.com/spring-projects/spring-framework) + * spring-boot (org.springframework.boot:spring-boot:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-actuator (org.springframework.boot:spring-boot-actuator:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter (org.springframework.boot:spring-boot-starter:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-aop (org.springframework.boot:spring-boot-starter-aop:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-cache (org.springframework.boot:spring-boot-starter-cache:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-data-rest (org.springframework.boot:spring-boot-starter-data-rest:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-log4j2 (org.springframework.boot:spring-boot-starter-log4j2:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-security (org.springframework.boot:spring-boot-starter-security:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-test (org.springframework.boot:spring-boot-starter-test:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-thymeleaf (org.springframework.boot:spring-boot-starter-thymeleaf:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-test (org.springframework.boot:spring-boot-test:3.5.3 - https://spring.io/projects/spring-boot) + * spring-boot-test-autoconfigure (org.springframework.boot:spring-boot-test-autoconfigure:3.5.3 - https://spring.io/projects/spring-boot) + * Spring Data Core (org.springframework.data:spring-data-commons:3.5.1 - https://spring.io/projects/spring-data) + * Spring Data REST - Core (org.springframework.data:spring-data-rest-core:4.5.1 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-core) + * Spring Data REST - WebMVC (org.springframework.data:spring-data-rest-webmvc:4.5.1 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-webmvc) + * Spring HATEOAS (org.springframework.hateoas:spring-hateoas:2.5.1 - https://github.com/spring-projects/spring-hateoas) * Spring Plugin - Core (org.springframework.plugin:spring-plugin-core:3.0.0 - https://github.com/spring-projects/spring-plugin/spring-plugin-core) - * spring-security-config (org.springframework.security:spring-security-config:6.4.2 - https://spring.io/projects/spring-security) - * spring-security-core (org.springframework.security:spring-security-core:6.4.2 - https://spring.io/projects/spring-security) - * spring-security-crypto (org.springframework.security:spring-security-crypto:6.4.2 - https://spring.io/projects/spring-security) - * spring-security-test (org.springframework.security:spring-security-test:6.4.2 - https://spring.io/projects/spring-security) - * spring-security-web (org.springframework.security:spring-security-web:6.4.2 - https://spring.io/projects/spring-security) + * spring-security-config (org.springframework.security:spring-security-config:6.5.1 - https://spring.io/projects/spring-security) + * spring-security-core (org.springframework.security:spring-security-core:6.5.1 - https://spring.io/projects/spring-security) + * spring-security-crypto (org.springframework.security:spring-security-crypto:6.5.1 - https://spring.io/projects/spring-security) + * spring-security-test (org.springframework.security:spring-security-test:6.5.1 - https://spring.io/projects/spring-security) + * spring-security-web (org.springframework.security:spring-security-web:6.5.1 - https://spring.io/projects/spring-security) + * thymeleaf (org.thymeleaf:thymeleaf:3.1.3.RELEASE - http://www.thymeleaf.org/thymeleaf-lib/thymeleaf) + * thymeleaf-spring6 (org.thymeleaf:thymeleaf-spring6:3.1.3.RELEASE - http://www.thymeleaf.org/thymeleaf-lib/thymeleaf-spring6) + * unbescape (org.unbescape:unbescape:1.1.6.RELEASE - http://www.unbescape.org) * snappy-java (org.xerial.snappy:snappy-java:1.1.10.1 - https://github.com/xerial/snappy-java) * xml-matchers (org.xmlmatchers:xml-matchers:0.10 - http://code.google.com/p/xml-matchers/) - * org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.10.0 - https://www.xmlunit.org/) + * org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.10.2 - https://www.xmlunit.org/) * org.xmlunit:xmlunit-placeholders (org.xmlunit:xmlunit-placeholders:2.9.1 - https://www.xmlunit.org/xmlunit-placeholders/) - * SnakeYAML (org.yaml:snakeyaml:2.3 - https://bitbucket.org/snakeyaml/snakeyaml) + * SnakeYAML (org.yaml:snakeyaml:2.4 - https://bitbucket.org/snakeyaml/snakeyaml) * Xerces2-j (xerces:xercesImpl:2.12.2 - https://xerces.apache.org/xerces2-j/) BSD License: @@ -463,7 +473,7 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * Protocol Buffers [Core] (com.google.protobuf:protobuf-java:3.24.3 - https://developers.google.com/protocol-buffers/protobuf-java/) * JZlib (com.jcraft:jzlib:1.1.3 - http://www.jcraft.com/jzlib/) * jmustache (com.samskivert:jmustache:1.15 - http://github.com/samskivert/jmustache) - * dnsjava (dnsjava:dnsjava:3.6.2 - https://github.com/dnsjava/dnsjava) + * dnsjava (dnsjava:dnsjava:3.6.3 - https://github.com/dnsjava/dnsjava) * jaxen (jaxen:jaxen:2.0.0 - http://www.cafeconleche.org/jaxen/jaxen) * ANTLR 4 Runtime (org.antlr:antlr4-runtime:4.13.2 - https://www.antlr.org/antlr4-runtime/) * commons-compiler (org.codehaus.janino:commons-compiler:3.1.8 - http://janino-compiler.github.io/commons-compiler/) @@ -481,10 +491,10 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * asm-analysis (org.ow2.asm:asm-analysis:8.0.1 - http://asm.ow2.io/) * asm-commons (org.ow2.asm:asm-commons:8.0.1 - http://asm.ow2.io/) * asm-tree (org.ow2.asm:asm-tree:8.0.1 - http://asm.ow2.io/) - * ASM Util (org.ow2.asm:asm-util:5.0.3 - http://asm.objectweb.org/asm-util/) - * PostgreSQL JDBC Driver (org.postgresql:postgresql:42.7.5 - https://jdbc.postgresql.org) + * PostgreSQL JDBC Driver (org.postgresql:postgresql:42.7.7 - https://jdbc.postgresql.org) * Reflections (org.reflections:reflections:0.9.12 - http://github.com/ronmamo/reflections) * JMatIO (org.tallison:jmatio:1.5 - https://github.com/tballison/jmatio) + * XZ for Java (org.tukaani:xz:1.10 - https://tukaani.org/xz/java.html) * XMLUnit for Java (xmlunit:xmlunit:1.3 - http://xmlunit.sourceforge.net/) CC0: @@ -549,14 +559,13 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * System Rules (com.github.stefanbirkner:system-rules:1.19.0 - http://stefanbirkner.github.io/system-rules/) * H2 Database Engine (com.h2database:h2:2.3.232 - https://h2database.com) * Jakarta Annotations API (jakarta.annotation:jakarta.annotation-api:2.1.1 - https://projects.eclipse.org/projects/ee4j.ca) - * Jakarta Expression Language API (jakarta.el:jakarta.el-api:5.0.1 - https://projects.eclipse.org/projects/ee4j.el) * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.3 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api) * Jakarta Persistence API (jakarta.persistence:jakarta.persistence-api:3.1.0 - https://github.com/eclipse-ee4j/jpa-api) * Jakarta Servlet (jakarta.servlet:jakarta.servlet-api:6.1.0 - https://projects.eclipse.org/projects/ee4j.servlet) * jakarta.transaction API (jakarta.transaction:jakarta.transaction-api:2.0.1 - https://projects.eclipse.org/projects/ee4j.jta) * Jakarta RESTful WS API (jakarta.ws.rs:jakarta.ws.rs-api:3.1.0 - https://github.com/eclipse-ee4j/jaxrs-api) * JUnit (junit:junit:4.13.2 - http://junit.org) - * AspectJ Weaver (org.aspectj:aspectjweaver:1.9.22.1 - https://www.eclipse.org/aspectj/) + * AspectJ Weaver (org.aspectj:aspectjweaver:1.9.24 - https://www.eclipse.org/aspectj/) * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.3 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail) * Jetty :: Apache JSP Implementation (org.eclipse.jetty:apache-jsp:9.4.15.v20190215 - http://www.eclipse.org/jetty) * Apache :: JSTL module (org.eclipse.jetty:apache-jstl:9.4.15.v20190215 - http://tomcat.apache.org/taglibs/standard/) @@ -606,16 +615,19 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common) * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) + * JUnit Platform Commons (org.junit.platform:junit-platform-commons:1.11.4 - https://junit.org/junit5/) + * JUnit Platform Engine API (org.junit.platform:junit-platform-engine:1.11.4 - https://junit.org/junit5/) + * JUnit Vintage Engine (org.junit.vintage:junit-vintage-engine:5.11.4 - https://junit.org/junit5/) * org.locationtech.jts:jts-core (org.locationtech.jts:jts-core:1.19.0 - https://www.locationtech.org/projects/technology.jts/jts-modules/jts-core) * org.locationtech.jts.io:jts-io-common (org.locationtech.jts.io:jts-io-common:1.19.0 - https://www.locationtech.org/projects/technology.jts/jts-modules/jts-io/jts-io-common) GENERAL PUBLIC LICENSE, version 3 (GPL-3.0): - * juniversalchardet (com.github.albfernandez:juniversalchardet:2.4.0 - https://github.com/albfernandez/juniversalchardet) + * juniversalchardet (com.github.albfernandez:juniversalchardet:2.5.0 - https://github.com/albfernandez/juniversalchardet) GNU LESSER GENERAL PUBLIC LICENSE, version 3 (LGPL-3.0): - * juniversalchardet (com.github.albfernandez:juniversalchardet:2.4.0 - https://github.com/albfernandez/juniversalchardet) + * juniversalchardet (com.github.albfernandez:juniversalchardet:2.5.0 - https://github.com/albfernandez/juniversalchardet) GNU Lesser General Public License (LGPL): @@ -641,9 +653,9 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * RE2/J (com.google.re2j:re2j:1.2 - http://github.com/google/re2j) - Handle.Net Public License Agreement (Ver.2): + Handle.Net Public License Agreement (Ver.3): - * Handle Server (net.handle:handle:9.3.1 - https://www.handle.net) + * Handle Server (net.handle:handle:9.3.2 - https://www.handle.net) ISC License: @@ -659,18 +671,18 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * s3mock (io.findify:s3mock_2.13:0.2.6 - https://github.com/findify/s3mock) * ClassGraph (io.github.classgraph:classgraph:4.8.165 - https://github.com/classgraph/classgraph) * JOpt Simple (net.sf.jopt-simple:jopt-simple:5.0.4 - http://jopt-simple.github.io/jopt-simple) - * Bouncy Castle S/MIME API (org.bouncycastle:bcmail-jdk18on:1.77 - https://www.bouncycastle.org/java.html) - * Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk18on:1.80 - https://www.bouncycastle.org/download/bouncy-castle-java/) - * Bouncy Castle Provider (org.bouncycastle:bcprov-jdk18on:1.80 - https://www.bouncycastle.org/download/bouncy-castle-java/) - * Bouncy Castle ASN.1 Extension and Utility APIs (org.bouncycastle:bcutil-jdk18on:1.80 - https://www.bouncycastle.org/download/bouncy-castle-java/) + * Bouncy Castle JavaMail S/MIME APIs (org.bouncycastle:bcmail-jdk18on:1.80 - https://www.bouncycastle.org/download/bouncy-castle-java/) + * Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk18on:1.81 - https://www.bouncycastle.org/download/bouncy-castle-java/) + * Bouncy Castle Provider (org.bouncycastle:bcprov-jdk18on:1.81 - https://www.bouncycastle.org/download/bouncy-castle-java/) + * Bouncy Castle ASN.1 Extension and Utility APIs (org.bouncycastle:bcutil-jdk18on:1.81 - https://www.bouncycastle.org/download/bouncy-castle-java/) * org.brotli:dec (org.brotli:dec:0.1.2 - http://brotli.org/dec) - * Checker Qual (org.checkerframework:checker-qual:3.48.4 - https://checkerframework.org/) + * Checker Qual (org.checkerframework:checker-qual:3.49.5 - https://checkerframework.org/) * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client) * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2) * jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart) * mockito-core (org.mockito:mockito-core:3.12.4 - https://github.com/mockito/mockito) * mockito-inline (org.mockito:mockito-inline:3.12.4 - https://github.com/mockito/mockito) - * SLF4J API Module (org.slf4j:slf4j-api:2.0.16 - http://www.slf4j.org) + * SLF4J API Module (org.slf4j:slf4j-api:2.0.17 - http://www.slf4j.org) * HAL Browser (org.webjars:hal-browser:ad9b865 - http://webjars.org) * toastr (org.webjars.bowergithub.codeseven:toastr:2.1.4 - http://webjars.org) * backbone (org.webjars.bowergithub.jashkenas:backbone:1.4.1 - https://www.webjars.org) @@ -678,14 +690,14 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * jquery (org.webjars.bowergithub.jquery:jquery-dist:3.7.1 - https://www.webjars.org) * urijs (org.webjars.bowergithub.medialize:uri.js:1.19.11 - https://www.webjars.org) * bootstrap (org.webjars.bowergithub.twbs:bootstrap:4.6.2 - https://www.webjars.org) - * core-js (org.webjars.npm:core-js:3.40.0 - https://www.webjars.org) - * @json-editor/json-editor (org.webjars.npm:json-editor__json-editor:2.15.1 - https://www.webjars.org) + * core-js (org.webjars.npm:core-js:3.42.0 - https://www.webjars.org) + * @json-editor/json-editor (org.webjars.npm:json-editor__json-editor:2.15.2 - https://www.webjars.org) Mozilla Public License: - * juniversalchardet (com.github.albfernandez:juniversalchardet:2.4.0 - https://github.com/albfernandez/juniversalchardet) + * juniversalchardet (com.github.albfernandez:juniversalchardet:2.5.0 - https://github.com/albfernandez/juniversalchardet) * H2 Database Engine (com.h2database:h2:2.3.232 - https://h2database.com) - * Saxon-HE (net.sf.saxon:Saxon-HE:9.8.0-14 - http://www.saxonica.com/) + * Saxon-HE (net.sf.saxon:Saxon-HE:9.9.1-8 - http://www.saxonica.com/) * Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/) * Mozilla Rhino (org.mozilla:rhino:1.7.7.2 - https://developer.mozilla.org/en/Rhino) @@ -699,7 +711,6 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines * JSON in Java (org.json:json:20231013 - https://github.com/douglascrockford/JSON-java) * LatencyUtils (org.latencyutils:LatencyUtils:2.0.3 - http://latencyutils.github.io/LatencyUtils/) * Reflections (org.reflections:reflections:0.9.12 - http://github.com/ronmamo/reflections) - * XZ for Java (org.tukaani:xz:1.9 - https://tukaani.org/xz/java.html) UnRar License: diff --git a/pom.xml b/pom.xml index 9bddbe276164..e6f580426266 100644 --- a/pom.xml +++ b/pom.xml @@ -719,7 +719,7 @@ Apache Software License, Version 2.0|The SAX License|The W3C License Apache Software License, Version 2.0|Similar to Apache License but with the acknowledgment clause removed - BSD License|The BSD License|BSD licence|BSD license|BSD|BSD-style license|New BSD License|New BSD license|Revised BSD License|BSD 2-Clause license|3-Clause BSD License|BSD 2-Clause|BSD 3-clause New License|BSD Licence 3|BSD-2-Clause|BSD-3-Clause|Modified BSD|The New BSD License|The BSD 3-Clause License (BSD3)|BSD License 3|BSD License 2.0|The (New) BSD License + BSD License|The BSD License|BSD licence|BSD license|BSD|BSD-style license|New BSD License|New BSD license|Revised BSD License|BSD 2-Clause license|3-Clause BSD License|BSD 2-Clause|BSD 3-clause New License|BSD Licence 3|BSD-2-Clause|BSD-3-Clause|Modified BSD|The New BSD License|The BSD 3-Clause License (BSD3)|BSD License 3|BSD License 2.0|The (New) BSD License|0BSD BSD License|DSpace BSD License|DSpace Sourcecode License @@ -740,7 +740,7 @@ Common Development and Distribution License (CDDL)|GNU General Public License, Version 2 with the Classpath Exception Eclipse Distribution License, Version 1.0|Eclipse Distribution License (EDL), Version 1.0|Eclipse Distribution License - v 1.0|Eclipse Distribution License v. 1.0|EDL 1.0 - Eclipse Public License|Eclipse Public License - Version 1.0|Eclipse Public License - v 1.0|EPL 1.0 license|Eclipse Public License (EPL), Version 1.0|Eclipse Public License 1.0|Eclipse Public License v1.0|Eclipse Public License, Version 1.0|EPL 1.0|EPL 2.0|Eclipse Public License - v 2.0|EPL-2.0|Eclipse Public License 2.0|Eclipse Public License v. 2.0|Eclipse Public License, Version 2.0 + Eclipse Public License|Eclipse Public License - Version 1.0|Eclipse Public License - v 1.0|EPL 1.0 license|Eclipse Public License (EPL), Version 1.0|Eclipse Public License 1.0|Eclipse Public License v1.0|Eclipse Public License, Version 1.0|EPL 1.0|EPL 2.0|Eclipse Public License - v 2.0|EPL-2.0|Eclipse Public License 2.0|Eclipse Public License v. 2.0|Eclipse Public License, Version 2.0|Eclipse Public License v2.0 Eclipse Public License|Common Public License Version 1.0 From 55c33ede6391ad2d6f2ca98af7994aad8b6b0326 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Sun, 13 Jul 2025 10:06:33 +0200 Subject: [PATCH 625/632] Enforce path traversal check on import subdir (pre-processing) --- .../app/itemimport/ItemImportServiceImpl.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java index b40ecae2f7e0..74fe4c461913 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java @@ -29,6 +29,7 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.net.URL; +import java.nio.file.Path; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -744,15 +745,20 @@ protected Item addItem(Context c, List mycollections, String path, myitem = wi.getItem(); } + // normalize and validate path to make sure itemname doesn't contain path traversal + Path itemPath = new File(path + File.separatorChar + itemname + File.separatorChar) + .toPath().normalize(); + if (!itemPath.startsWith(path)) { + throw new IOException("Illegal item metadata path: '" + itemPath); + } + // now fill out dublin core for item - loadMetadata(c, myitem, path + File.separatorChar + itemname - + File.separatorChar); + loadMetadata(c, myitem, itemPath.toString()); // and the bitstreams from the contents file // process contents file, add bistreams and bundles, return any // non-standard permissions - List options = processContentsFile(c, myitem, path - + File.separatorChar + itemname, "contents"); + List options = processContentsFile(c, myitem, itemPath.toString(), "contents"); if (useWorkflow) { // don't process handle file @@ -770,8 +776,7 @@ protected Item addItem(Context c, List mycollections, String path, } } else { // only process handle file if not using workflow system - String myhandle = processHandleFile(c, myitem, path - + File.separatorChar + itemname, "handle"); + String myhandle = processHandleFile(c, myitem, itemPath.toString(), "handle"); // put item in system if (!isTest) { From f473272a08d9ad1c846c5a013602566733694560 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Mon, 14 Jul 2025 12:48:55 +0200 Subject: [PATCH 626/632] Re-add file separator to normalized SAF item path --- .../org/dspace/app/itemimport/ItemImportServiceImpl.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java index 74fe4c461913..89fbb6d78cb0 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java @@ -751,14 +751,16 @@ protected Item addItem(Context c, List mycollections, String path, if (!itemPath.startsWith(path)) { throw new IOException("Illegal item metadata path: '" + itemPath); } + // Normalization chops off the last separator, and we need to put it back + String itemPathDir = itemPath.toString() + File.separatorChar; // now fill out dublin core for item - loadMetadata(c, myitem, itemPath.toString()); + loadMetadata(c, myitem, itemPathDir); // and the bitstreams from the contents file // process contents file, add bistreams and bundles, return any // non-standard permissions - List options = processContentsFile(c, myitem, itemPath.toString(), "contents"); + List options = processContentsFile(c, myitem, itemPathDir, "contents"); if (useWorkflow) { // don't process handle file @@ -776,7 +778,7 @@ protected Item addItem(Context c, List mycollections, String path, } } else { // only process handle file if not using workflow system - String myhandle = processHandleFile(c, myitem, itemPath.toString(), "handle"); + String myhandle = processHandleFile(c, myitem, itemPathDir, "handle"); // put item in system if (!isTest) { From 6b909126e65175d1b2c5ebe162372665e00e8c61 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Mon, 14 Jul 2025 13:06:08 +0200 Subject: [PATCH 627/632] Remove unused imports --- .../src/main/java/org/dspace/app/util/DCInputsReader.java | 2 -- .../main/java/org/dspace/app/util/SubmissionConfigReader.java | 1 - 2 files changed, 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java index 293ceaac47d7..7c0ad4830f13 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java @@ -8,7 +8,6 @@ package org.dspace.app.util; import java.io.File; -import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -16,7 +15,6 @@ import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import org.apache.commons.lang3.StringUtils; diff --git a/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java b/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java index 5b487045a0d9..2016fb2ce64e 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SubmissionConfigReader.java @@ -16,7 +16,6 @@ import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import org.apache.commons.lang3.StringUtils; From 2c934dfbf71ca4257d54fea8f6eba4768f4128d3 Mon Sep 17 00:00:00 2001 From: MMilosz Date: Fri, 4 Jul 2025 17:13:02 +0200 Subject: [PATCH 628/632] fix: prevent path traversal in SAF import (cherry picked from commit 596d8666f4b91c6af92f72f45da262d761b96607) --- .../app/itemimport/ItemImportServiceImpl.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java index 087a33026151..e29a0b567095 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java @@ -1001,6 +1001,34 @@ protected void addDCValue(Context c, Item i, String schema, Node n) } } + /** + * Ensures a file path does not attempt to access files outside the designated parent directory. + * + * @param parentDir The absolute path to the parent directory that should contain the file + * @param fileName The name or path of the file to validate + * @throws IOException If an error occurs while resolving canonical paths, or the file path attempts + * to access a location outside the parent directory + */ + private void validateFilePath(String parentDir, String fileName) throws IOException { + File parent = new File(parentDir); + File file = new File(fileName); + + // If the fileName is not an absolute path, we resolve it against the parentDir + if (!file.isAbsolute()) { + file = new File(parent, fileName); + } + + String parentCanonicalPath = parent.getCanonicalPath(); + String fileCanonicalPath = file.getCanonicalPath(); + + if (!fileCanonicalPath.startsWith(parentCanonicalPath)) { + log.error("File path outside of canonical root requested: fileCanonicalPath={} does not begin " + + "with parentCanonicalPath={}", fileCanonicalPath, parentCanonicalPath); + throw new IOException("Illegal file path '" + fileName + "' encountered. This references a path " + + "outside of the import package. Please see the system logs for more details."); + } + } + /** * Read the collections file inside the item directory. If there * is one and it is not empty return a list of collections in @@ -1201,6 +1229,7 @@ protected List processContentsFile(Context c, Item i, String path, sDescription = sDescription.replaceFirst("description:", ""); } + validateFilePath(path, sFilePath); registerBitstream(c, i, iAssetstore, sFilePath, sBundle, sDescription); logInfo("\tRegistering Bitstream: " + sFilePath + "\tAssetstore: " + iAssetstore @@ -1414,6 +1443,7 @@ protected void processContentFileEntry(Context c, Item i, String path, return; } + validateFilePath(path, fileName); String fullpath = path + File.separatorChar + fileName; // get an input stream From daca9d8ec7c9451ae430b420248cb7c60c180e72 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 9 Jul 2025 13:59:37 +0200 Subject: [PATCH 629/632] Enforce bitstream path to be within (fs) bitstore base on get (cherry picked from commit 6799660a903bfea985c818654cca3891527780de) --- .../org/dspace/storage/bitstore/DSBitStoreService.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java index 6fef7365e482..3f92ccaac5f1 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java @@ -12,6 +12,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -249,6 +250,12 @@ protected File getFile(Bitstream bitstream) throws IOException { log.debug("Local filename for " + sInternalId + " is " + bufFilename.toString()); } + File bitstreamFile = new File(bufFilename.toString()); + Path normalizedPath = bitstreamFile.toPath().normalize(); + if (!normalizedPath.startsWith(baseDir.getAbsolutePath())) { + log.error("Bitstream path outside of assetstore root requested: bitstream={}, path={}, assetstore={}", bitstream.getID(), normalizedPath, baseDir.getAbsolutePath()); + throw new IOException("Illegal bitstream path constructed"); + } return new File(bufFilename.toString()); } From 0e95ba80de86e3e0029a06165153aff9eb375a9d Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Wed, 9 Jul 2025 19:07:32 +0200 Subject: [PATCH 630/632] return existing File constructed and validated for bitstream (cherry picked from commit 31b1c922b2cba42857679f291cb9320cf820db46) --- .../java/org/dspace/storage/bitstore/DSBitStoreService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java index 3f92ccaac5f1..6589f99bc749 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java @@ -256,7 +256,7 @@ protected File getFile(Bitstream bitstream) throws IOException { log.error("Bitstream path outside of assetstore root requested: bitstream={}, path={}, assetstore={}", bitstream.getID(), normalizedPath, baseDir.getAbsolutePath()); throw new IOException("Illegal bitstream path constructed"); } - return new File(bufFilename.toString()); + return bitstreamFile; } public boolean isRegisteredBitstream(String internalId) { From d6c76bc63905ae13f70dc59121e97426ca9e95f0 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Mon, 14 Jul 2025 12:42:30 +0200 Subject: [PATCH 631/632] Fix line length in DSBitstore log (cherry picked from commit dbf524c1120261f407cc77574642e3ee0e4ffe33) --- .../java/org/dspace/storage/bitstore/DSBitStoreService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java index 6589f99bc749..7743b93ca4ba 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/DSBitStoreService.java @@ -253,7 +253,9 @@ protected File getFile(Bitstream bitstream) throws IOException { File bitstreamFile = new File(bufFilename.toString()); Path normalizedPath = bitstreamFile.toPath().normalize(); if (!normalizedPath.startsWith(baseDir.getAbsolutePath())) { - log.error("Bitstream path outside of assetstore root requested: bitstream={}, path={}, assetstore={}", bitstream.getID(), normalizedPath, baseDir.getAbsolutePath()); + log.error("Bitstream path outside of assetstore root requested:" + + "bitstream={}, path={}, assetstore={}", + bitstream.getID(), normalizedPath, baseDir.getAbsolutePath()); throw new IOException("Illegal bitstream path constructed"); } return bitstreamFile; From 1743314da4f38f0539c03e71c798f53ca158bf1a Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 14 Jul 2025 14:43:33 -0500 Subject: [PATCH 632/632] [maven-release-plugin] prepare release dspace-8.2 --- dspace-api/pom.xml | 2 +- dspace-iiif/pom.xml | 2 +- dspace-oai/pom.xml | 2 +- dspace-rdf/pom.xml | 2 +- dspace-server-webapp/pom.xml | 2 +- dspace-services/pom.xml | 2 +- dspace-sword/pom.xml | 2 +- dspace-swordv2/pom.xml | 2 +- dspace/modules/additions/pom.xml | 2 +- dspace/modules/pom.xml | 2 +- dspace/modules/server-boot/pom.xml | 2 +- dspace/modules/server/pom.xml | 2 +- dspace/pom.xml | 2 +- pom.xml | 28 ++++++++++++++-------------- 14 files changed, 27 insertions(+), 27 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 7303df1fcef0..882f0b037c73 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -12,7 +12,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace-iiif/pom.xml b/dspace-iiif/pom.xml index 71b88d92ca9b..4a93ed41c006 100644 --- a/dspace-iiif/pom.xml +++ b/dspace-iiif/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 434e3fa2886a..8a9bd8aa4044 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -8,7 +8,7 @@ dspace-parent org.dspace - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index 4662433d49c1..f18177116b45 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 47afbfd1374e..e38e99a30cb2 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -14,7 +14,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index 973790ec435f..6d59839cdac8 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -9,7 +9,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index bdab97fee787..1866cd4c3a7b 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -15,7 +15,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 84e1e412b945..29e81f2edb30 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -13,7 +13,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace/modules/additions/pom.xml b/dspace/modules/additions/pom.xml index ec1153e1c9a5..e7c2073c73bf 100644 --- a/dspace/modules/additions/pom.xml +++ b/dspace/modules/additions/pom.xml @@ -17,7 +17,7 @@ org.dspace modules - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace/modules/pom.xml b/dspace/modules/pom.xml index 5394ccd3248a..1e9efb0401d1 100644 --- a/dspace/modules/pom.xml +++ b/dspace/modules/pom.xml @@ -11,7 +11,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 ../../pom.xml diff --git a/dspace/modules/server-boot/pom.xml b/dspace/modules/server-boot/pom.xml index 9d7251e78e2b..9aa952ec1290 100644 --- a/dspace/modules/server-boot/pom.xml +++ b/dspace/modules/server-boot/pom.xml @@ -11,7 +11,7 @@ modules org.dspace - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index 35c7f161e91b..a7399eee836a 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -7,7 +7,7 @@ modules org.dspace - 8.2-SNAPSHOT + 8.2 .. diff --git a/dspace/pom.xml b/dspace/pom.xml index 6690264d7c07..fd855be8b169 100644 --- a/dspace/pom.xml +++ b/dspace/pom.xml @@ -16,7 +16,7 @@ org.dspace dspace-parent - 8.2-SNAPSHOT + 8.2 ../pom.xml diff --git a/pom.xml b/pom.xml index e6f580426266..38980f32b111 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.dspace dspace-parent pom - 8.2-SNAPSHOT + 8.2 DSpace Parent Project DSpace open source software is a turnkey institutional repository application. @@ -1016,68 +1016,68 @@ org.dspace dspace-api - 8.2-SNAPSHOT + 8.2 org.dspace dspace-api test-jar - 8.2-SNAPSHOT + 8.2 test org.dspace.modules additions - 8.2-SNAPSHOT + 8.2 org.dspace.modules server classes - 8.2-SNAPSHOT + 8.2 org.dspace dspace-sword - 8.2-SNAPSHOT + 8.2 org.dspace dspace-swordv2 - 8.2-SNAPSHOT + 8.2 org.dspace dspace-oai - 8.2-SNAPSHOT + 8.2 org.dspace dspace-services - 8.2-SNAPSHOT + 8.2 org.dspace dspace-server-webapp test-jar - 8.2-SNAPSHOT + 8.2 test org.dspace dspace-rdf - 8.2-SNAPSHOT + 8.2 org.dspace dspace-iiif - 8.2-SNAPSHOT + 8.2 org.dspace dspace-server-webapp - 8.2-SNAPSHOT + 8.2 @@ -1910,7 +1910,7 @@ scm:git:git@github.com:DSpace/DSpace.git scm:git:git@github.com:DSpace/DSpace.git https://github.com/DSpace/DSpace - dspace-8_x + dspace-8.2