diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a2a0d6294f65..7d63f45982c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: # NOTE: Unit Tests include a retry for occasionally failing tests # - surefire.rerunFailingTestsCount => try again for flakey tests, and keep track of/report on number of retries - type: "Unit Tests" - java: 11 + java: 17 mvnflags: "-DskipUnitTests=false -Dsurefire.rerunFailingTestsCount=2" resultsdir: "**/target/surefire-reports/**" # NOTE: ITs skip all code validation checks, as they are already done by Unit Test job. @@ -34,7 +34,7 @@ jobs: # - xml.skip => Skip all XML/XSLT validation by xml-maven-plugin # - failsafe.rerunFailingTestsCount => try again for flakey tests, and keep track of/report on number of retries - type: "Integration Tests" - java: 11 + java: 17 mvnflags: "-DskipIntegrationTests=false -Denforcer.skip=true -Dcheckstyle.skip=true -Dlicense.skip=true -Dxml.skip=true -Dfailsafe.rerunFailingTestsCount=2" resultsdir: "**/target/failsafe-reports/**" # Do NOT exit immediately if one matrix job fails diff --git a/.github/workflows/codescan.yml b/.github/workflows/codescan.yml index 13bb0d2278ad..2a5abfceb1d8 100644 --- a/.github/workflows/codescan.yml +++ b/.github/workflows/codescan.yml @@ -41,7 +41,7 @@ jobs: - name: Install JDK uses: actions/setup-java@v3 with: - java-version: 11 + java-version: 17 distribution: 'temurin' # Initializes the CodeQL tools for scanning. diff --git a/.lgtm.yml b/.lgtm.yml deleted file mode 100644 index 132de8a6de5a..000000000000 --- a/.lgtm.yml +++ /dev/null @@ -1,9 +0,0 @@ -# LGTM Settings (https://lgtm.com/) -# For reference, see https://lgtm.com/help/lgtm/lgtm.yml-configuration-file -# or template at https://lgtm.com/static/downloads/lgtm.template.yml - -extraction: - java: - index: - # Specify the Java version required to build the project - java_version: 11 diff --git a/Dockerfile b/Dockerfile index 5bcd68376887..73697483aef8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,9 +3,9 @@ # # - note: default tag for branch: dspace/dspace: dspace/dspace:latest -# 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 +# 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 # Step 1 - Run Maven Build @@ -51,7 +51,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 tomcat:10-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 d54978375e54..19049735de32 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -3,9 +3,9 @@ # # - note: default tag for branch: dspace/dspace-cli: dspace/dspace-cli:latest -# 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 +# 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 # Step 1 - Run Maven Build diff --git a/Dockerfile.dependencies b/Dockerfile.dependencies index 6f72ab058536..c5b8cbdfb287 100644 --- a/Dockerfile.dependencies +++ b/Dockerfile.dependencies @@ -2,9 +2,9 @@ # The purpose of this image is to make the build for dspace/dspace run faster # -# 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 +# This Dockerfile uses JDK17 by default. +# To build with other versions, use "--build-arg JDK_VERSION=[value]" +ARG JDK_VERSION=17 # Step 1 - Run Maven Build FROM maven:3-openjdk-${JDK_VERSION}-slim as build diff --git a/Dockerfile.test b/Dockerfile.test index 6fcc4eda6be1..09d22432dcf5 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -5,9 +5,9 @@ # # This image is meant for TESTING/DEVELOPMENT ONLY as it deploys the old v6 REST API under HTTP (not HTTPS) -# 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 +# 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 # Step 1 - Run Maven Build @@ -50,7 +50,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 tomcat:10-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/dspace-api/pom.xml b/dspace-api/pom.xml index 0aafa5df73fb..e9544d3274fa 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -54,21 +54,21 @@ - org.hibernate + org.hibernate.orm hibernate-jpamodelgen ${hibernate.version} - javax.xml.bind - jaxb-api + jakarta.xml.bind + jakarta.xml.bind-api ${jaxb-api.version} - javax.annotation - javax.annotation-api - ${javax-annotation.version} + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation.version} @@ -177,7 +177,7 @@ org.codehaus.mojo jaxb2-maven-plugin - 2.5.0 + 3.1.0 workflow-curation @@ -265,7 +265,7 @@ - ${agnostic.build.dir}/testing/dspace/ + ${agnostic.build.dir}/testing/dspace true ${agnostic.build.dir}/testing/dspace/solr/ @@ -324,7 +324,7 @@ - ${agnostic.build.dir}/testing/dspace/ + ${agnostic.build.dir}/testing/dspace true ${agnostic.build.dir}/testing/dspace/solr/ @@ -342,18 +342,15 @@ log4j-api - org.hibernate + org.hibernate.orm hibernate-core - - - - org.javassist - javassist - - - org.hibernate + org.hibernate.orm + hibernate-jpamodelgen + + + org.hibernate.orm hibernate-jcache @@ -377,26 +374,16 @@ com.fasterxml.jackson.datatype jackson-datatype-jsr310 - 2.13.5 javax.cache cache-api - - org.hibernate - hibernate-jpamodelgen - org.hibernate.validator hibernate-validator-cdi ${hibernate-validator.version} - - org.hibernate.javax.persistence - hibernate-jpa-2.1-api - 1.0.2.Final - org.springframework @@ -407,30 +394,26 @@ net.handle handle + net.cnri cnri-servlet-container + runtime - + - org.ow2.asm - asm-commons - - - - org.bouncycastle - bcpkix-jdk15on - - - org.bouncycastle - bcprov-jdk15on + org.mortbay.jasper + apache-jsp - + + org.eclipse.jetty jetty-server + runtime org.dspace @@ -440,12 +423,6 @@ org.apache.jena apache-jena-libs pom - - - log4j - log4j - - commons-cli @@ -463,10 +440,6 @@ org.apache.commons commons-dbcp2 - - commons-fileupload - commons-fileupload - commons-io @@ -486,16 +459,20 @@ com.sun.mail - javax.mail + jakarta.mail - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api + + + jakarta.el + jakarta.el-api jaxen @@ -591,6 +568,13 @@ solr-core test ${solr.client.version} + + + + org.antlr + antlr4-runtime + + org.apache.lucene @@ -670,7 +654,12 @@ org.flywaydb flyway-core - 8.5.13 + ${flyway.version} + + + org.flywaydb + flyway-database-postgresql + ${flyway.version} @@ -706,23 +695,22 @@ - javax.inject - javax.inject - 1 - jar + jakarta.inject + jakarta.inject-api + 2.0.1 - javax.xml.bind - jaxb-api + jakarta.xml.bind + jakarta.xml.bind-api org.glassfish.jaxb jaxb-runtime - + org.glassfish.jersey.core jersey-client @@ -743,18 +731,16 @@ 1.12.261 + org.orcid - orcid-model - 3.0.2 + orcid-model-jakarta + 3.3.0 - javax.validation - validation-api - - - com.fasterxml.jackson.jaxrs - jackson-jaxrs-json-provider + com.fasterxml.jackson.jarkarta.rs + jackson-jakarta-rs-json-provider org.yaml @@ -765,8 +751,8 @@ javassist - io.swagger - swagger-jersey-jaxrs + io.swagger.core.v3 + swagger-jaxrs2-jakarta @@ -844,7 +830,17 @@ com.fasterxml.jackson.datatype - jackson-datatype-jsr310 + jackson-datatype-jsr310 + + + + javax.xml.bind + jaxb-api + + + + javax.servlet + javax.servlet-api @@ -865,7 +861,6 @@ - @@ -920,14 +915,9 @@ 2.2.14 - jakarta.xml.bind - jakarta.xml.bind-api - 2.3.3 - - - javax.validation - validation-api - 2.0.1.Final + jakarta.validation + jakarta.validation-api + 3.0.2 io.swagger diff --git a/dspace-api/src/main/java/org/dspace/alerts/SystemWideAlert.java b/dspace-api/src/main/java/org/dspace/alerts/SystemWideAlert.java index f56cbdcce9e9..432c633ea591 100644 --- a/dspace-api/src/main/java/org/dspace/alerts/SystemWideAlert.java +++ b/dspace-api/src/main/java/org/dspace/alerts/SystemWideAlert.java @@ -8,17 +8,17 @@ package org.dspace.alerts; import java.util.Date; -import javax.persistence.Cacheable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/alerts/dao/impl/SystemWideAlertDAOImpl.java b/dspace-api/src/main/java/org/dspace/alerts/dao/impl/SystemWideAlertDAOImpl.java index 13a0e0af236a..79dc1bcf27a3 100644 --- a/dspace-api/src/main/java/org/dspace/alerts/dao/impl/SystemWideAlertDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/alerts/dao/impl/SystemWideAlertDAOImpl.java @@ -9,10 +9,10 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.alerts.SystemWideAlert; import org.dspace.alerts.SystemWideAlert_; import org.dspace.alerts.dao.SystemWideAlertDAO; diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataImport.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataImport.java index af6976acb14a..dbec53eee9c4 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataImport.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataImport.java @@ -20,8 +20,8 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import org.apache.commons.cli.ParseException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/app/itemexport/ItemExportServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/itemexport/ItemExportServiceImpl.java index a884f9b07564..c91d25b3d44b 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemexport/ItemExportServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/itemexport/ItemExportServiceImpl.java @@ -31,8 +31,8 @@ import java.util.UUID; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.itemexport.service.ItemExportService; diff --git a/dspace-api/src/main/java/org/dspace/app/itemexport/service/ItemExportService.java b/dspace-api/src/main/java/org/dspace/app/itemexport/service/ItemExportService.java index 6ec1027709bb..cc53d952e79b 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemexport/service/ItemExportService.java +++ b/dspace-api/src/main/java/org/dspace/app/itemexport/service/ItemExportService.java @@ -11,8 +11,8 @@ import java.util.Date; import java.util.Iterator; import java.util.List; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.Context; 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 255f4bdcbb15..82e26b95e8cf 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 @@ -46,7 +46,6 @@ import java.util.UUID; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import javax.mail.MessagingException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -56,6 +55,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import jakarta.mail.MessagingException; import org.apache.commons.collections4.ComparatorUtils; import org.apache.commons.io.FileDeleteStrategy; import org.apache.commons.io.FileUtils; diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/service/ItemImportService.java b/dspace-api/src/main/java/org/dspace/app/itemimport/service/ItemImportService.java index e99ece31b9bb..90cb6f9b803a 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemimport/service/ItemImportService.java +++ b/dspace-api/src/main/java/org/dspace/app/itemimport/service/ItemImportService.java @@ -10,8 +10,8 @@ import java.io.File; import java.io.IOException; import java.util.List; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.dspace.app.itemimport.BatchUpload; import org.dspace.content.Collection; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageEntity.java b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageEntity.java index 5d96dd3f956c..27257455e0ce 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageEntity.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageEntity.java @@ -7,16 +7,17 @@ */ package org.dspace.app.ldn; +import java.lang.reflect.Field; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.content.DSpaceObject; import org.dspace.core.ReloadableEntity; @@ -34,6 +35,12 @@ public class LDNMessageEntity implements ReloadableEntity { * LDN messages interact with a fictitious queue. Scheduled tasks manage the queue. */ + /* + * Notification Type constants + */ + public static final String TYPE_INCOMING = "Incoming"; + public static final String TYPE_OUTGOING = "Outgoing"; + /** * Message must not be processed. */ @@ -69,6 +76,11 @@ public class LDNMessageEntity implements ReloadableEntity { */ public static final Integer QUEUE_STATUS_UNMAPPED_ACTION = 6; + /** + * Message queued for retry, it has to be elaborated. + */ + public static final Integer QUEUE_STATUS_QUEUED_FOR_RETRY = 7; + @Id private String id; @@ -76,7 +88,7 @@ public class LDNMessageEntity implements ReloadableEntity { @JoinColumn(name = "object", referencedColumnName = "uuid") private DSpaceObject object; - @Column(name = "message", nullable = false, columnDefinition = "text") + @Column(name = "message", columnDefinition = "text") private String message; @Column(name = "type") @@ -275,4 +287,33 @@ public void setSourceIp(String sourceIp) { public String toString() { return "LDNMessage id:" + this.getID() + " typed:" + this.getType(); } + + public static String getNotificationType(LDNMessageEntity ldnMessage) { + if (ldnMessage.getInReplyTo() != null || ldnMessage.getOrigin() != null) { + return TYPE_INCOMING; + } + return TYPE_OUTGOING; + } + + public static String getServiceNameForNotifyServ(NotifyServiceEntity serviceEntity) { + if (serviceEntity != null) { + return serviceEntity.getName(); + } + return "self"; + } + + public static String getQueueStatus(LDNMessageEntity ldnMessage) { + Class cl = LDNMessageEntity.class; + try { + for (Field f : cl.getDeclaredFields()) { + String fieldName = f.getName(); + if (fieldName.startsWith("QUEUE_") && (f.get(null) == ldnMessage.getQueueStatus())) { + return fieldName; + } + } + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + return null; + } } diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/NotifyPatternToTrigger.java b/dspace-api/src/main/java/org/dspace/app/ldn/NotifyPatternToTrigger.java index b393d8bedbc5..da23471a1c66 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/NotifyPatternToTrigger.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/NotifyPatternToTrigger.java @@ -7,16 +7,15 @@ */ package org.dspace.app.ldn; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.content.Item; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/NotifyServiceEntity.java b/dspace-api/src/main/java/org/dspace/app/ldn/NotifyServiceEntity.java index 206ed16fa00e..c939256b52ba 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/NotifyServiceEntity.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/NotifyServiceEntity.java @@ -9,15 +9,15 @@ import java.math.BigDecimal; import java.util.List; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.OneToMany; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.ReloadableEntity; /** diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/NotifyServiceInboundPattern.java b/dspace-api/src/main/java/org/dspace/app/ldn/NotifyServiceInboundPattern.java index 0c367d505131..329d6cb11cec 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/NotifyServiceInboundPattern.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/NotifyServiceInboundPattern.java @@ -7,16 +7,15 @@ */ package org.dspace.app.ldn; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.ReloadableEntity; /** diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/dao/LDNMessageDao.java b/dspace-api/src/main/java/org/dspace/app/ldn/dao/LDNMessageDao.java index c3f4907cce11..fcbb485acacc 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/dao/LDNMessageDao.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/dao/LDNMessageDao.java @@ -65,4 +65,12 @@ public List findAllMessagesByItem( */ public List findAllRelatedMessagesByItem( Context context, LDNMessageEntity msg, Item item, String... relatedTypes) throws SQLException; + + /** + * + * @param context + * @return the list of messages in need to be reprocessed - with queue_status as QUEUE_STATUS_QUEUED_FOR_RETRY + * @throws SQLException + */ + public List findMessagesToBeReprocessed(Context context) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/LDNMessageDaoImpl.java b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/LDNMessageDaoImpl.java index 0a0fe672fb0a..d811f6d39f34 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/LDNMessageDaoImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/LDNMessageDaoImpl.java @@ -12,12 +12,12 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Order; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; import org.apache.logging.log4j.Logger; import org.dspace.app.ldn.LDNMessageEntity; import org.dspace.app.ldn.LDNMessageEntity_; @@ -60,6 +60,29 @@ public List findOldestMessageToProcess(Context context, int ma return result; } + @Override + public List findMessagesToBeReprocessed(Context context) throws SQLException { + // looking for LDN Messages to be reprocessed message + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, LDNMessageEntity.class); + Root root = criteriaQuery.from(LDNMessageEntity.class); + criteriaQuery.select(root); + List andPredicates = new ArrayList<>(1); + andPredicates + .add(criteriaBuilder.equal(root.get(LDNMessageEntity_.queueStatus), + LDNMessageEntity.QUEUE_STATUS_QUEUED_FOR_RETRY)); + criteriaQuery.where(criteriaBuilder.and(andPredicates.toArray(new Predicate[] {}))); + List orderList = new LinkedList<>(); + orderList.add(criteriaBuilder.desc(root.get(LDNMessageEntity_.queueAttempts))); + orderList.add(criteriaBuilder.asc(root.get(LDNMessageEntity_.queueLastStartTime))); + criteriaQuery.orderBy(orderList); + List result = list(context, criteriaQuery, false, LDNMessageEntity.class, -1, -1); + if (result == null || result.isEmpty()) { + log.debug("No LDN messages found to be processed"); + } + return result; + } + @Override public List findProcessingTimedoutMessages(Context context, int max_attempts) throws SQLException { diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyPatternToTriggerDaoImpl.java b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyPatternToTriggerDaoImpl.java index 47c584518b14..53cbeabe005a 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyPatternToTriggerDaoImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyPatternToTriggerDaoImpl.java @@ -9,10 +9,10 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.app.ldn.NotifyPatternToTrigger; import org.dspace.app.ldn.NotifyPatternToTrigger_; import org.dspace.app.ldn.dao.NotifyPatternToTriggerDao; diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyServiceDaoImpl.java b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyServiceDaoImpl.java index cac804ef0c1f..bb4cf791da27 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyServiceDaoImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyServiceDaoImpl.java @@ -9,11 +9,11 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.dspace.app.ldn.NotifyServiceEntity; import org.dspace.app.ldn.NotifyServiceEntity_; import org.dspace.app.ldn.NotifyServiceInboundPattern; diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyServiceInboundPatternDaoImpl.java b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyServiceInboundPatternDaoImpl.java index 5168fd0bedf8..dc3dc1c74491 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyServiceInboundPatternDaoImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/dao/impl/NotifyServiceInboundPatternDaoImpl.java @@ -9,10 +9,10 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.app.ldn.NotifyServiceEntity; import org.dspace.app.ldn.NotifyServiceInboundPattern; import org.dspace.app.ldn.NotifyServiceInboundPattern_; diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/service/LDNMessageService.java b/dspace-api/src/main/java/org/dspace/app/ldn/service/LDNMessageService.java index c7d3f588881f..d200f0ce84ee 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/service/LDNMessageService.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/service/LDNMessageService.java @@ -139,9 +139,18 @@ public interface LDNMessageService { public void delete(Context context, LDNMessageEntity ldnMessage) throws SQLException; /** - * check if IP number is included in the configured ip-range on the Notify Service + * find the ldn messages to be reprocessed + * + * @param context the context + * @throws SQLException if something goes wrong + */ + public List findMessagesToBeReprocessed(Context context) throws SQLException; + + /** + * check if IP number is included in the configured ip-range on the Notify + * Service * - * @param origin the Notify Service entity + * @param origin the Notify Service entity * @param sourceIp the ip to evaluate */ public boolean isValidIp(NotifyServiceEntity origin, String sourceIp); diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/service/NotifyService.java b/dspace-api/src/main/java/org/dspace/app/ldn/service/NotifyService.java index 6ff4c34780c5..e6ac0d63b438 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/service/NotifyService.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/service/NotifyService.java @@ -43,10 +43,11 @@ public interface NotifyService { * create new notifyServiceEntity * * @param context the context + * @param name name of the service * @return the created NotifyServiceEntity * @throws SQLException if database error */ - public NotifyServiceEntity create(Context context) throws SQLException; + public NotifyServiceEntity create(Context context, String name) throws SQLException; /** * update the provided notifyServiceEntity diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/service/impl/LDNMessageServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/ldn/service/impl/LDNMessageServiceImpl.java index b69ecec6a142..193d8cebaf52 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/service/impl/LDNMessageServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/service/impl/LDNMessageServiceImpl.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.JsonSyntaxException; import org.apache.commons.lang.time.DateUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; @@ -38,7 +39,10 @@ import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.service.ItemService; +import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableLDNNotification; +import org.dspace.event.Event; import org.dspace.handle.service.HandleService; import org.dspace.services.ConfigurationService; import org.springframework.beans.factory.annotation.Autowired; @@ -65,6 +69,7 @@ public class LDNMessageServiceImpl implements LDNMessageService { private LDNRouter ldnRouter; private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(LDNMessageServiceImpl.class); + private static final String LDN_ID_PREFIX = "urn:uuid:"; protected LDNMessageServiceImpl() { @@ -72,6 +77,12 @@ protected LDNMessageServiceImpl() { @Override public LDNMessageEntity find(Context context, String id) throws SQLException { + + if (id == null) { + return null; + } + + id = id.startsWith(LDN_ID_PREFIX) ? id : LDN_ID_PREFIX + id; return ldnMessageDao.findByID(context, LDNMessageEntity.class, id); } @@ -171,11 +182,19 @@ private long ipToLong(InetAddress ip) { @Override public void update(Context context, LDNMessageEntity ldnMessage) throws SQLException { + // move the queue_status from UNTRUSTED to QUEUED if origin is a known NotifyService if (ldnMessage.getOrigin() != null && LDNMessageEntity.QUEUE_STATUS_UNTRUSTED.compareTo(ldnMessage.getQueueStatus()) == 0) { ldnMessage.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_QUEUED); } ldnMessageDao.save(context, ldnMessage); + UUID notificationUUID = UUID.fromString(ldnMessage.getID().replace(LDN_ID_PREFIX, "")); + ArrayList identifiersList = new ArrayList(); + identifiersList.add(ldnMessage.getID()); + context.addEvent( + new Event(Event.MODIFY, Constants.LDN_MESSAGE, + notificationUUID, + IndexableLDNNotification.TYPE, identifiersList)); } private DSpaceObject findDspaceObjectByUrl(Context context, String url) throws SQLException { @@ -210,6 +229,13 @@ public List findOldestMessagesToProcess(Context context) throw return result; } + @Override + public List findMessagesToBeReprocessed(Context context) throws SQLException { + List result = null; + result = ldnMessageDao.findMessagesToBeReprocessed(context); + return result; + } + @Override public List findProcessingTimedoutMessages(Context context) throws SQLException { List result = null; @@ -225,9 +251,10 @@ public int extractAndProcessMessageFromQueue(Context context) throws SQLExceptio if (timeoutInMinutes == 0) { timeoutInMinutes = 60; } - List msgs = null; + List msgs = new ArrayList(); try { - msgs = findOldestMessagesToProcess(context); + msgs.addAll(findOldestMessagesToProcess(context)); + msgs.addAll(findMessagesToBeReprocessed(context)); if (msgs != null && msgs.size() > 0) { LDNMessageEntity msg = null; LDNProcessor processor = null; @@ -253,9 +280,14 @@ public int extractAndProcessMessageFromQueue(Context context) throws SQLExceptio processor.process(context, notification); msg.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_PROCESSED); result = 1; + } catch (JsonSyntaxException jse) { + result = -1; + log.error("Unable to read JSON notification from LdnMessage " + msg, jse); + msg.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_FAILED); } catch (Exception e) { result = -1; log.error(e); + msg.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_FAILED); } finally { msg.setQueueAttempts(msg.getQueueAttempts() + 1); update(context, msg); diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/service/impl/NotifyServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/ldn/service/impl/NotifyServiceImpl.java index d2289fd77a1c..87be008371aa 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/service/impl/NotifyServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/service/impl/NotifyServiceImpl.java @@ -37,8 +37,9 @@ public NotifyServiceEntity find(Context context, Integer id) throws SQLException } @Override - public NotifyServiceEntity create(Context context) throws SQLException { + public NotifyServiceEntity create(Context context, String name) throws SQLException { NotifyServiceEntity notifyServiceEntity = new NotifyServiceEntity(); + notifyServiceEntity.setName(name); return notifyServiceDao.create(context, notifyServiceEntity); } diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItem.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItem.java index cdefd1298c6e..bf2bfb4d60b2 100644 --- a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItem.java +++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItem.java @@ -8,19 +8,19 @@ package org.dspace.app.requestitem; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.content.Bitstream; import org.dspace.content.Item; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemEmailNotifier.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemEmailNotifier.java index 6499c45a7830..c489fb4b3ff0 100644 --- a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemEmailNotifier.java +++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemEmailNotifier.java @@ -11,11 +11,11 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; -import javax.annotation.ManagedBean; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.mail.MessagingException; +import jakarta.annotation.ManagedBean; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; +import jakarta.mail.MessagingException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.requestitem.service.RequestItemService; diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java index 008174ded88c..c76bd50d1910 100644 --- a/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java @@ -9,11 +9,11 @@ import java.sql.SQLException; import java.util.Iterator; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.app.requestitem.RequestItem; import org.dspace.app.requestitem.RequestItem_; import org.dspace.app.requestitem.dao.RequestItemDAO; @@ -44,8 +44,12 @@ public RequestItem findByToken(Context context, String token) throws SQLExceptio } @Override public Iterator findByItem(Context context, Item item) throws SQLException { - Query query = createQuery(context, "FROM RequestItem WHERE item_id= :uuid"); - query.setParameter("uuid", item.getID()); + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RequestItem.class); + Root requestItemRoot = criteriaQuery.from(RequestItem.class); + criteriaQuery.select(requestItemRoot); + criteriaQuery.where(criteriaBuilder.equal(requestItemRoot.get(RequestItem_.item), item)); + Query query = createQuery(context, criteriaQuery); return iterate(query); } } 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 ead725e842c4..9ee5ca55cc6d 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 @@ -12,8 +12,8 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; @@ -93,7 +93,7 @@ private void init() { * @param query ISSN string to pass in an "issn equals" API query * @return SHERPAResponse containing an error or journal policies */ - @Cacheable(key = "#query", cacheNames = "sherpa.searchByJournalISSN") + @Cacheable(key = "#query", condition = "#query != null", cacheNames = "sherpa.searchByJournalISSN") public SHERPAResponse searchByJournalISSN(String query) { return performRequest("publication", "issn", "equals", query, 0, 1); } diff --git a/dspace-api/src/main/java/org/dspace/app/suggestion/SuggestionServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/suggestion/SuggestionServiceImpl.java index 66773fbc128d..57fe42806b12 100644 --- a/dspace-api/src/main/java/org/dspace/app/suggestion/SuggestionServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/suggestion/SuggestionServiceImpl.java @@ -13,8 +13,8 @@ import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.apache.logging.log4j.Logger; import org.dspace.core.Context; import org.springframework.stereotype.Service; diff --git a/dspace-api/src/main/java/org/dspace/app/util/AuthorizeUtil.java b/dspace-api/src/main/java/org/dspace/app/util/AuthorizeUtil.java index b498b693956a..6400820546ce 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/AuthorizeUtil.java +++ b/dspace-api/src/main/java/org/dspace/app/util/AuthorizeUtil.java @@ -9,8 +9,8 @@ import java.sql.SQLException; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.Logger; import org.dspace.authenticate.factory.AuthenticateServiceFactory; import org.dspace.authorize.AuthorizeConfiguration; 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 c5093d3320a8..dd88390cb856 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 @@ -13,8 +13,8 @@ import java.util.Optional; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/app/util/DSpaceContextListener.java b/dspace-api/src/main/java/org/dspace/app/util/DSpaceContextListener.java index b0289ec4a4e1..51d78ccaba5c 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DSpaceContextListener.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DSpaceContextListener.java @@ -13,9 +13,9 @@ import java.sql.Driver; import java.sql.DriverManager; import java.util.Enumeration; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; import org.apache.logging.log4j.Logger; /** diff --git a/dspace-api/src/main/java/org/dspace/app/util/DSpaceWebappListener.java b/dspace-api/src/main/java/org/dspace/app/util/DSpaceWebappListener.java index c2817169b21e..32c4ff9c1c71 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DSpaceWebappListener.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DSpaceWebappListener.java @@ -8,8 +8,9 @@ package org.dspace.app.util; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; + +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; /** * Class that registers the web application upon startup of the application. diff --git a/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java b/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java index 28d39d911b95..db45d42e495e 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java @@ -13,7 +13,7 @@ import org.apache.commons.lang3.BooleanUtils; import org.dspace.content.InProgressSubmission; import org.dspace.content.WorkspaceItem; -import org.hibernate.proxy.HibernateProxyHelper; +import org.dspace.core.HibernateProxyHelper; /** * Class representing configuration for a single step within an Item Submission diff --git a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java index c1402499c444..2ab99e54d2e1 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java @@ -13,7 +13,6 @@ import java.util.Date; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; import com.rometools.modules.itunes.EntryInformation; import com.rometools.modules.itunes.EntryInformationImpl; @@ -35,6 +34,7 @@ import com.rometools.rome.feed.synd.SyndPersonImpl; import com.rometools.rome.io.FeedException; import com.rometools.rome.io.SyndFeedOutput; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/app/util/Util.java b/dspace-api/src/main/java/org/dspace/app/util/Util.java index 3bc828d6c496..a084e60b634e 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/Util.java +++ b/dspace-api/src/main/java/org/dspace/app/util/Util.java @@ -20,8 +20,8 @@ import java.util.Properties; import java.util.Set; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/app/util/WebApp.java b/dspace-api/src/main/java/org/dspace/app/util/WebApp.java index 2f42c1459f63..c2fc133f41c6 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/WebApp.java +++ b/dspace-api/src/main/java/org/dspace/app/util/WebApp.java @@ -8,16 +8,16 @@ package org.dspace.app.util; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationMethod.java b/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationMethod.java index 500ee04a979b..d316cb636f87 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationMethod.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationMethod.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.List; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationServiceImpl.java b/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationServiceImpl.java index a1e096dc4d64..2b07f73c489c 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationServiceImpl.java @@ -13,8 +13,8 @@ import java.util.Date; import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.authenticate.service.AuthenticationService; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/IPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/IPAuthentication.java index 0c2be211a532..db71ec1c2ff1 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/IPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/IPAuthentication.java @@ -14,9 +14,9 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.Logger; import org.dspace.core.Context; import org.dspace.core.LogHelper; 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..b791df15b5c0 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -29,9 +29,9 @@ import javax.naming.ldap.LdapContext; import javax.naming.ldap.StartTlsRequest; import javax.naming.ldap.StartTlsResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +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.authenticate.factory.AuthenticateServiceFactory; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/OidcAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/OidcAuthentication.java index 5d4635d48ef5..c7ac1ff55748 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/OidcAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/OidcAuthentication.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.List; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/OidcAuthenticationBean.java b/dspace-api/src/main/java/org/dspace/authenticate/OidcAuthenticationBean.java index c628f0dce27d..61cbca1e5ed7 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/OidcAuthenticationBean.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/OidcAuthenticationBean.java @@ -20,9 +20,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthentication.java index 3e9ff6638a61..932d963307f6 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthentication.java @@ -10,9 +10,9 @@ import java.sql.SQLException; import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.authenticate.factory.AuthenticateServiceFactory; import org.dspace.core.Context; import org.dspace.eperson.EPerson; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java b/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java index 6804ad9160dd..590bbf6cf0ef 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java @@ -18,9 +18,9 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/PasswordAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/PasswordAuthentication.java index 6d1ca862d307..8e030305c957 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/PasswordAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/PasswordAuthentication.java @@ -11,9 +11,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java index 791634a7dc25..24d8266012d4 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java @@ -20,9 +20,9 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/X509Authentication.java b/dspace-api/src/main/java/org/dspace/authenticate/X509Authentication.java index 12dc5feda583..55843c710760 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/X509Authentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/X509Authentication.java @@ -25,10 +25,10 @@ import java.util.Enumeration; import java.util.List; import java.util.StringTokenizer; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import org.apache.commons.lang3.ArrayUtils; import org.apache.logging.log4j.Logger; import org.dspace.authenticate.factory.AuthenticateServiceFactory; @@ -505,7 +505,7 @@ public int authenticate(Context context, String username, String password, X509Certificate[] certs = null; if (request != null) { certs = (X509Certificate[]) request - .getAttribute("javax.servlet.request.X509Certificate"); + .getAttribute("jakarta.servlet.request.X509Certificate"); } if ((certs == null) || (certs.length == 0)) { 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 ddab01e8cb5d..68fffd3fb264 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 @@ -14,10 +14,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import javax.annotation.PostConstruct; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.PostConstruct; import org.apache.commons.io.IOUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; diff --git a/dspace-api/src/main/java/org/dspace/authenticate/service/AuthenticationService.java b/dspace-api/src/main/java/org/dspace/authenticate/service/AuthenticationService.java index e955302ec3d7..45ad8932daec 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/service/AuthenticationService.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/service/AuthenticationService.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.authenticate.AuthenticationMethod; import org.dspace.core.Context; import org.dspace.eperson.EPerson; diff --git a/dspace-api/src/main/java/org/dspace/authority/AuthoritySolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/authority/AuthoritySolrServiceImpl.java index ca5b4a11b543..2ab2bbf90266 100644 --- a/dspace-api/src/main/java/org/dspace/authority/AuthoritySolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authority/AuthoritySolrServiceImpl.java @@ -11,9 +11,9 @@ import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; -import javax.inject.Named; +import jakarta.inject.Inject; +import jakarta.inject.Named; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.solr.client.solrj.SolrClient; 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 beff6fdc48e8..c303c0ba9dba 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java @@ -697,7 +697,7 @@ public ResourcePolicy createOrModifyPolicy(ResourcePolicy policy, Context contex if (!duplicates.isEmpty()) { policy = duplicates.get(0); } - } else { + } else if (group != null) { // if an identical policy (same Action and same Group) is already in place modify it... policyTemp = findByTypeGroupAction(context, dso, group, action); } diff --git a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java index c781400bae45..68a59d46ae2f 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java +++ b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java @@ -9,29 +9,28 @@ import java.util.Date; import java.util.Objects; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.Lob; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.apache.solr.common.StringUtils; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; -import org.hibernate.annotations.Type; -import org.hibernate.proxy.HibernateProxyHelper; +import org.hibernate.Length; /** * Database entity representation of the ResourcePolicy table @@ -99,9 +98,7 @@ public class ResourcePolicy implements ReloadableEntity { @Column(name = "rptype", length = 30) private String rptype; - @Lob - @Type(type = "org.hibernate.type.TextType") - @Column(name = "rpdescription") + @Column(name = "rpdescription", length = Length.LONG32) private String rpdescription; /** diff --git a/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java b/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java index 26b6bb1d7345..3b09f9cf300b 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java @@ -8,16 +8,19 @@ package org.dspace.authorize.dao.impl; import java.sql.SQLException; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.UUID; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Order; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import org.apache.commons.collections.CollectionUtils; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy_; import org.dspace.authorize.dao.ResourcePolicyDAO; @@ -153,16 +156,30 @@ public List findByTypeGroupActionExceptId(Context context, DSpac public List findByEPersonGroupTypeIdAction(Context context, EPerson e, List groups, int action, int type_id) throws SQLException { + // If groups and eperson are empty, return immediately + if (CollectionUtils.isEmpty(groups) && e == null) { + return Collections.emptyList(); + } + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, ResourcePolicy.class); Root resourcePolicyRoot = criteriaQuery.from(ResourcePolicy.class); criteriaQuery.select(resourcePolicyRoot); + + // Determine which predicate to use to match EPerson or Group(s) based on which were specified in params + Predicate compareEpersonOrGroups = + (CollectionUtils.isNotEmpty(groups) && e != null) ? + // Both are non-empty, so check both via an OR clause + criteriaBuilder.or(criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.eperson), e), + resourcePolicyRoot.get(ResourcePolicy_.epersonGroup).in(groups)) : + // Otherwise only check one based on which is non-empty + (e != null ? criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.eperson), e) : + resourcePolicyRoot.get(ResourcePolicy_.epersonGroup).in(groups)); + criteriaQuery.where( criteriaBuilder.and(criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.resourceTypeId), type_id), criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.actionId), action), - criteriaBuilder - .or(criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.eperson), e), - (resourcePolicyRoot.get(ResourcePolicy_.epersonGroup).in(groups))) + compareEpersonOrGroups ) ); return list(context, criteriaQuery, false, ResourcePolicy.class, 1, -1); @@ -286,8 +303,8 @@ public List findByEPerson(Context context, EPerson ePerson, int @Override public int countByEPerson(Context context, EPerson ePerson) throws SQLException { Query query = createQuery(context, - "SELECT count(*) FROM " + ResourcePolicy.class.getSimpleName() + " WHERE eperson_id = (:epersonUuid) "); - query.setParameter("epersonUuid", ePerson.getID()); + "SELECT count(*) FROM " + ResourcePolicy.class.getSimpleName() + " WHERE eperson = :eperson "); + query.setParameter("eperson", ePerson); return count(query); } @@ -307,9 +324,9 @@ public List findByEPersonAndResourceUuid(Context context, EPerso @Override public int countByEPersonAndResourceUuid(Context context, EPerson eperson, UUID resourceUuid) throws SQLException { Query query = createQuery(context, "SELECT count(*) FROM " + ResourcePolicy.class.getSimpleName() - + " WHERE eperson_id = (:epersonUuid) AND dspace_object = (:resourceUuid) "); + + " WHERE eperson = :eperson AND dSpaceObject.id = :resourceUuid "); query.setParameter("resourceUuid", resourceUuid); - query.setParameter("epersonUuid", eperson.getID()); + query.setParameter("eperson", eperson); return count(query); } @@ -329,7 +346,7 @@ public List findByResouceUuidAndActionId(Context context, UUID r @Override public int countByResouceUuidAndActionId(Context context, UUID resourceUuid, int actionId) throws SQLException { Query query = createQuery(context, "SELECT count(*) FROM " + ResourcePolicy.class.getSimpleName() - + " WHERE dspace_object = (:resourceUuid) AND action_id = (:actionId) "); + + " WHERE dSpaceObject.id = :resourceUuid AND actionId = :actionId "); query.setParameter("resourceUuid", resourceUuid); query.setParameter("actionId", actionId); return count(query); @@ -349,7 +366,7 @@ public List findByResouceUuid(Context context, UUID resourceUuid @Override public int countByResourceUuid(Context context, UUID resourceUuid) throws SQLException { Query query = createQuery(context, "SELECT count(*) FROM " + ResourcePolicy.class.getSimpleName() - + " WHERE dspace_object = (:resourceUuid) "); + + " WHERE dSpaceObject.id = :resourceUuid "); query.setParameter("resourceUuid", resourceUuid); return count(query); } @@ -367,8 +384,8 @@ public List findByGroup(Context context, Group group, int offset @Override public int countResourcePolicyByGroup(Context context, Group group) throws SQLException { Query query = createQuery(context, "SELECT count(*) " + "FROM " + ResourcePolicy.class.getSimpleName() - + " WHERE epersongroup_id = (:groupUuid) "); - query.setParameter("groupUuid", group.getID()); + + " WHERE epersonGroup = :group "); + query.setParameter("group", group); return count(query); } @@ -388,9 +405,9 @@ public List findByGroupAndResourceUuid(Context context, Group gr @Override public int countByGroupAndResourceUuid(Context context, Group group, UUID resourceUuid) throws SQLException { Query query = createQuery(context, "SELECT count(*) FROM " + ResourcePolicy.class.getSimpleName() - + " WHERE dspace_object = (:resourceUuid) AND epersongroup_id = (:groupUuid) "); + + " WHERE dSpaceObject.id = :resourceUuid AND epersonGroup = :group "); query.setParameter("resourceUuid", resourceUuid); - query.setParameter("groupUuid", group.getID()); + query.setParameter("group", group); return count(query); } diff --git a/dspace-api/src/main/java/org/dspace/checker/ChecksumHistory.java b/dspace-api/src/main/java/org/dspace/checker/ChecksumHistory.java index 63779cda02fb..521bf546a4f2 100644 --- a/dspace-api/src/main/java/org/dspace/checker/ChecksumHistory.java +++ b/dspace-api/src/main/java/org/dspace/checker/ChecksumHistory.java @@ -8,19 +8,19 @@ package org.dspace.checker; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.content.Bitstream; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/checker/ChecksumResult.java b/dspace-api/src/main/java/org/dspace/checker/ChecksumResult.java index 57fcdb8e365e..a63488077703 100644 --- a/dspace-api/src/main/java/org/dspace/checker/ChecksumResult.java +++ b/dspace-api/src/main/java/org/dspace/checker/ChecksumResult.java @@ -8,12 +8,13 @@ package org.dspace.checker; import java.io.Serializable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Id; -import javax.persistence.Table; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Id; +import jakarta.persistence.Table; /** * Database entity representation of the checksum_results table diff --git a/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java b/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java index b291232e8b55..50ef4baa98e3 100644 --- a/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java +++ b/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java @@ -13,8 +13,8 @@ import java.sql.SQLException; import java.util.Date; import java.util.GregorianCalendar; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; @@ -63,7 +63,7 @@ public DailyReportEmailer() { * @throws MessagingException if message cannot be sent. */ public void sendReport(File attachment, int numberOfBitstreams) - throws IOException, javax.mail.MessagingException { + throws IOException, jakarta.mail.MessagingException { if (numberOfBitstreams > 0) { ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); diff --git a/dspace-api/src/main/java/org/dspace/checker/MostRecentChecksum.java b/dspace-api/src/main/java/org/dspace/checker/MostRecentChecksum.java index eff8a8be1cde..5cb1851e7c4f 100644 --- a/dspace-api/src/main/java/org/dspace/checker/MostRecentChecksum.java +++ b/dspace-api/src/main/java/org/dspace/checker/MostRecentChecksum.java @@ -9,16 +9,16 @@ import java.io.Serializable; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; +import jakarta.persistence.Transient; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.dspace.content.Bitstream; diff --git a/dspace-api/src/main/java/org/dspace/checker/dao/impl/ChecksumHistoryDAOImpl.java b/dspace-api/src/main/java/org/dspace/checker/dao/impl/ChecksumHistoryDAOImpl.java index 328d4a717eb1..44c594d0eb32 100644 --- a/dspace-api/src/main/java/org/dspace/checker/dao/impl/ChecksumHistoryDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/checker/dao/impl/ChecksumHistoryDAOImpl.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.Date; -import javax.persistence.Query; -import javax.persistence.TemporalType; +import jakarta.persistence.Query; +import jakarta.persistence.TemporalType; import org.dspace.checker.ChecksumHistory; import org.dspace.checker.ChecksumResultCode; import org.dspace.checker.dao.ChecksumHistoryDAO; diff --git a/dspace-api/src/main/java/org/dspace/checker/dao/impl/ChecksumResultDAOImpl.java b/dspace-api/src/main/java/org/dspace/checker/dao/impl/ChecksumResultDAOImpl.java index 7552c6d5bb8f..ac882e971dfe 100644 --- a/dspace-api/src/main/java/org/dspace/checker/dao/impl/ChecksumResultDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/checker/dao/impl/ChecksumResultDAOImpl.java @@ -8,10 +8,10 @@ package org.dspace.checker.dao.impl; import java.sql.SQLException; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.checker.ChecksumResult; import org.dspace.checker.ChecksumResultCode; import org.dspace.checker.ChecksumResult_; diff --git a/dspace-api/src/main/java/org/dspace/checker/dao/impl/MostRecentChecksumDAOImpl.java b/dspace-api/src/main/java/org/dspace/checker/dao/impl/MostRecentChecksumDAOImpl.java index a31e02cbab4a..669621aeeb58 100644 --- a/dspace-api/src/main/java/org/dspace/checker/dao/impl/MostRecentChecksumDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/checker/dao/impl/MostRecentChecksumDAOImpl.java @@ -11,14 +11,14 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Root; -import javax.persistence.criteria.Subquery; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Order; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Subquery; import org.dspace.checker.ChecksumHistory; import org.dspace.checker.ChecksumHistory_; import org.dspace.checker.ChecksumResult; diff --git a/dspace-api/src/main/java/org/dspace/content/Bitstream.java b/dspace-api/src/main/java/org/dspace/content/Bitstream.java index 5485735a2816..3fdb6316b210 100644 --- a/dspace-api/src/main/java/org/dspace/content/Bitstream.java +++ b/dspace-api/src/main/java/org/dspace/content/Bitstream.java @@ -11,21 +11,21 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BitstreamService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.hibernate.proxy.HibernateProxyHelper; +import org.dspace.core.HibernateProxyHelper; /** * Class representing bitstreams stored in the DSpace system. diff --git a/dspace-api/src/main/java/org/dspace/content/BitstreamFormat.java b/dspace-api/src/main/java/org/dspace/content/BitstreamFormat.java index 6d64ee3073e9..4dacea0952a5 100644 --- a/dspace-api/src/main/java/org/dspace/content/BitstreamFormat.java +++ b/dspace-api/src/main/java/org/dspace/content/BitstreamFormat.java @@ -11,27 +11,28 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.persistence.CollectionTable; -import javax.persistence.Column; -import javax.persistence.ElementCollection; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BitstreamFormatService; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CollectionId; -import org.hibernate.annotations.Type; -import org.hibernate.proxy.HibernateProxyHelper; +import org.hibernate.annotations.CollectionIdJavaType; +import org.hibernate.type.descriptor.java.IntegerJavaType; /** * Class representing a particular bitstream format. @@ -55,8 +56,6 @@ public class BitstreamFormat implements Serializable, ReloadableEntity @Column(name = "short_description", length = 128, unique = true) private String shortDescription; - // @Column(name="description") -// @Lob //Generates a TEXT or LONGTEXT data type @Column(name = "description", columnDefinition = "text") private String description; @@ -73,10 +72,10 @@ public class BitstreamFormat implements Serializable, ReloadableEntity @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "fileextension", joinColumns = @JoinColumn(name = "bitstream_format_id")) @CollectionId( - columns = @Column(name = "file_extension_id"), - type = @Type(type = "integer"), + column = @Column(name = "file_extension_id"), generator = "fileextension_seq" ) + @CollectionIdJavaType(IntegerJavaType.class) @SequenceGenerator(name = "fileextension_seq", sequenceName = "fileextension_seq", allocationSize = 1) @Column(name = "extension") @Cascade( {org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) diff --git a/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java index e23e5ce2c825..bd56ad465163 100644 --- a/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java @@ -14,8 +14,8 @@ import java.util.List; import java.util.UUID; import java.util.regex.Pattern; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/content/Bundle.java b/dspace-api/src/main/java/org/dspace/content/Bundle.java index e5cbdb6ff244..b6fd269f8fc4 100644 --- a/dspace-api/src/main/java/org/dspace/content/Bundle.java +++ b/dspace-api/src/main/java/org/dspace/content/Bundle.java @@ -10,22 +10,22 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.OneToOne; -import javax.persistence.OrderColumn; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.OrderColumn; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BundleService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.hibernate.proxy.HibernateProxyHelper; +import org.dspace.core.HibernateProxyHelper; /** * Class representing bundles of bitstreams stored in the DSpace system diff --git a/dspace-api/src/main/java/org/dspace/content/CacheableDSpaceObject.java b/dspace-api/src/main/java/org/dspace/content/CacheableDSpaceObject.java new file mode 100644 index 000000000000..fa6ec7676a32 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/content/CacheableDSpaceObject.java @@ -0,0 +1,20 @@ +/** + * 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.content; + +import jakarta.persistence.Cacheable; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +/** + * Abstract class for DSpaceObjects which are safe to cache in Hibernate's second level cache. + * See hibernate-ehcache-config.xml for caching configurations for each DSpaceObject which extends this class. + */ +@Cacheable +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy") +public abstract class CacheableDSpaceObject extends DSpaceObject { +} 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 a13c19d46cf8..17a6b1eb9420 100644 --- a/dspace-api/src/main/java/org/dspace/content/Collection.java +++ b/dspace-api/src/main/java/org/dspace/content/Collection.java @@ -15,19 +15,18 @@ import java.util.List; import java.util.Set; import java.util.UUID; -import javax.annotation.Nonnull; -import javax.persistence.Cacheable; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.OneToOne; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.annotation.Nonnull; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.dspace.authorize.AuthorizeException; import org.dspace.browse.ItemCountException; import org.dspace.content.comparator.NameAscendingComparator; @@ -35,9 +34,8 @@ import org.dspace.content.service.CollectionService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.eperson.Group; -import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.proxy.HibernateProxyHelper; /** * Class representing a collection. @@ -54,9 +52,7 @@ */ @Entity @Table(name = "collection") -@Cacheable -@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy") -public class Collection extends DSpaceObject implements DSpaceObjectLegacySupport { +public class Collection extends CacheableDSpaceObject implements DSpaceObjectLegacySupport { @Column(name = "collection_id", insertable = false, updatable = false) private Integer legacyId; diff --git a/dspace-api/src/main/java/org/dspace/content/Community.java b/dspace-api/src/main/java/org/dspace/content/Community.java index d82e08bab72e..4c417361655c 100644 --- a/dspace-api/src/main/java/org/dspace/content/Community.java +++ b/dspace-api/src/main/java/org/dspace/content/Community.java @@ -12,18 +12,17 @@ import java.util.List; import java.util.Set; import java.util.UUID; -import javax.persistence.Cacheable; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.OneToOne; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.dspace.browse.ItemCountException; import org.dspace.content.comparator.NameAscendingComparator; @@ -31,9 +30,9 @@ import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.eperson.Group; -import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.proxy.HibernateProxyHelper; + /** * Class representing a community @@ -46,9 +45,7 @@ */ @Entity @Table(name = "community") -@Cacheable -@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy") -public class Community extends DSpaceObject implements DSpaceObjectLegacySupport { +public class Community extends CacheableDSpaceObject implements DSpaceObjectLegacySupport { @Column(name = "community_id", insertable = false, updatable = false) private Integer legacyId; diff --git a/dspace-api/src/main/java/org/dspace/content/DSpaceObject.java b/dspace-api/src/main/java/org/dspace/content/DSpaceObject.java index 59217a109f66..b659035dc650 100644 --- a/dspace-api/src/main/java/org/dspace/content/DSpaceObject.java +++ b/dspace-api/src/main/java/org/dspace/content/DSpaceObject.java @@ -11,19 +11,19 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.persistence.OneToMany; -import javax.persistence.OrderBy; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OrderBy; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.apache.commons.collections4.CollectionUtils; import org.dspace.authorize.ResourcePolicy; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/content/DuplicateDetectionServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/DuplicateDetectionServiceImpl.java new file mode 100644 index 000000000000..9f52b7b63ac3 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/content/DuplicateDetectionServiceImpl.java @@ -0,0 +1,362 @@ +/** + * 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.content; + +import static java.util.Comparator.comparing; +import static java.util.Comparator.naturalOrder; + +import java.sql.SQLException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.dspace.app.itemupdate.MetadataUtilities; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.service.AuthorizeService; +import org.dspace.content.service.DuplicateDetectionService; +import org.dspace.content.service.ItemService; +import org.dspace.content.service.MetadataFieldService; +import org.dspace.content.service.MetadataValueService; +import org.dspace.content.service.WorkspaceItemService; +import org.dspace.content.virtual.PotentialDuplicate; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.discovery.DiscoverQuery; +import org.dspace.discovery.DiscoverResult; +import org.dspace.discovery.IndexableObject; +import org.dspace.discovery.SearchService; +import org.dspace.discovery.SearchServiceException; +import org.dspace.discovery.SearchUtils; +import org.dspace.discovery.indexobject.IndexableItem; +import org.dspace.discovery.indexobject.IndexableWorkflowItem; +import org.dspace.discovery.indexobject.IndexableWorkspaceItem; +import org.dspace.eperson.service.GroupService; +import org.dspace.services.ConfigurationService; +import org.dspace.versioning.VersionHistory; +import org.dspace.versioning.service.VersionHistoryService; +import org.dspace.workflow.WorkflowItem; +import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Default implementation of DuplicateDetectionService. + * Duplicate Detection Service handles get, search and validation operations for duplicate detection. + * + * @author Kim Shepherd + */ +public class DuplicateDetectionServiceImpl implements DuplicateDetectionService { + + @Autowired + ConfigurationService configurationService; + @Autowired + VersionHistoryService versionHistoryService; + @Autowired + AuthorizeService authorizeService; + @Autowired + GroupService groupService; + @Autowired + MetadataFieldService metadataFieldService; + @Autowired + MetadataValueService metadataValueService; + @Autowired + XmlWorkflowItemService workflowItemService; + @Autowired + WorkspaceItemService workspaceItemService; + @Autowired + ItemService itemService; + + /** + * Get a list of PotentialDuplicate objects (wrappers with some metadata included for previewing) that + * are identified as potential duplicates of the given item + * + * @param context DSpace context + * @param item Item to check + * @return List of potential duplicates (empty if none found) + * @throws SearchServiceException if an error occurs performing the discovery search + */ + @Override + public List getPotentialDuplicates(Context context, Item item) + throws SearchServiceException { + // Instantiate a new list of potential duplicates + List potentialDuplicates = new LinkedList<>(); + + // Immediately return an empty if this feature is not configured + if (!configurationService.getBooleanProperty("duplicate.enable", false)) { + return potentialDuplicates; + } + + // Search duplicates of this item and get discovery search result + DiscoverResult discoverResult = searchDuplicates(context, item); + + // If the search result is valid, iterate results and validate / transform + if (discoverResult != null) { + for (IndexableObject result : discoverResult.getIndexableObjects()) { + if (result != null) { + try { + // Validate this result and check permissions to read the item + Optional potentialDuplicateOptional = + validateDuplicateResult(context, result, item); + if (potentialDuplicateOptional.isPresent()) { + // Add the potential duplicate to the list + potentialDuplicates.add(potentialDuplicateOptional.get()); + } + } catch (SQLException e) { + log.error("SQL Error obtaining duplicate result: " + e.getMessage()); + } catch (AuthorizeException e) { + log.error("Authorize Error obtaining duplicate result: " + e.getMessage()); + } + } + } + } + + // Return the list of potential duplicates + return potentialDuplicates; + } + + + + /** + * Validate an indexable object (returned by discovery search) to ensure it is permissible, readable and valid + * and can be added to a list of results. + * An Optional is returned, if it is empty then it was invalid or did not pass validation. + * + * @param context The DSpace context + * @param indexableObject The discovery search result + * @param original The original item (to compare IDs, submitters, etc) + * @return An Optional potential duplicate + * @throws SQLException + * @throws AuthorizeException + */ + @Override + public Optional validateDuplicateResult(Context context, IndexableObject indexableObject, + Item original) + throws SQLException, + AuthorizeException { + + Item resultItem = null; + PotentialDuplicate potentialDuplicate = null; + WorkspaceItem workspaceItem = null; + WorkflowItem workflowItem = null; + + // Inspect the indexable object, and extract the DSpace item depending on + // what submission / archived state it is in + if (indexableObject instanceof IndexableWorkspaceItem) { + workspaceItem = ((IndexableWorkspaceItem) indexableObject).getIndexedObject(); + // Only process workspace items that belong to the submitter + if (workspaceItem != null && workspaceItem.getSubmitter() != null + && workspaceItem.getSubmitter().equals(context.getCurrentUser())) { + resultItem = workspaceItem.getItem(); + } + } + if (indexableObject instanceof IndexableWorkflowItem) { + workflowItem = ((IndexableWorkflowItem) indexableObject).getIndexedObject(); + if (workflowItem != null) { + resultItem = workflowItem.getItem(); + } + } + if (indexableObject instanceof IndexableItem) { + resultItem = ((IndexableItem) indexableObject).getIndexedObject(); + // Attempt resolution of workflow or workspace items, tested later + workflowItem = workflowItemService.findByItem(context, resultItem); + workspaceItem = workspaceItemService.findByItem(context, resultItem); + } + + // Result item must not be null, a template item, or actually identical to the original + if (resultItem == null) { + log.warn("skipping null item in duplicate search results"); + return Optional.empty(); + } else if (resultItem.getTemplateItemOf() != null) { + log.info("skipping template item in duplicate search results, item={}", resultItem.getID()); + return Optional.empty(); + } else if (resultItem.getID().equals(original.getID())) { + log.info("skipping a duplicate search result for the original item", resultItem.getID()); + return Optional.empty(); + } + + // If our item and the duplicate candidate share the same versionHistory, they are two different + // versions of the same item. + VersionHistory versionHistory = versionHistoryService.findByItem(context, original); + VersionHistory candiateVersionHistory = versionHistoryService.findByItem(context, resultItem); + // if the versionHistory is null, either versioning is switched off or the item doesn't have + // multiple versions + if (versionHistory != null && versionHistory.equals(candiateVersionHistory)) { + log.warn("skipping item that is just another version of this item"); + return Optional.empty(); + } + + // Construct new potential duplicate object + potentialDuplicate = new PotentialDuplicate(resultItem); + + // Get configured list of metadata fields to copy + List fields = new ArrayList<>(Arrays.asList( + configurationService.getArrayProperty("duplicate.preview.metadata.field", new String[]{}))); + + // Get item metadata and if it's configured for mapping, copy it across to the potential duplicate object + List metadata = resultItem.getCachedMetadata(); + + // Prepare a map of metadata to set on the potential duplicate object + for (MetadataValue metadatum : metadata) { + String fieldName = metadatum.getMetadataField().toString('.'); + if (fields.contains(fieldName)) { + potentialDuplicate.getMetadataValueList().add(metadatum); + } + } + + // Only if the current user is also the submitter of the item will we add this information + if (workspaceItem != null && workspaceItem.getSubmitter() != null + && workspaceItem.getSubmitter().equals(context.getCurrentUser())) { + potentialDuplicate.setWorkspaceItemId(workspaceItem.getID()); + return Optional.of(potentialDuplicate); + } + + // More authorisation checks + if (workflowItem != null) { + Collection c = workflowItem.getCollection(); + if (groupService.isMember(context, context.getCurrentUser(), c.getWorkflowStep1(context)) || + groupService.isMember(context, context.getCurrentUser(), c.getWorkflowStep2(context)) || + groupService.isMember(context, context.getCurrentUser(), c.getWorkflowStep3(context))) { + // Current user is a member of one of the workflow role groups + potentialDuplicate.setWorkflowItemId(workflowItem.getID()); + return Optional.of(potentialDuplicate); + } + } else if (resultItem.isArchived() && !resultItem.isWithdrawn() && resultItem.isDiscoverable()) { + // Not a workspace or workflow item, but is it archived, not withdrawn, and discoverable? + // Is it readable by the current user? + if (authorizeService.authorizeActionBoolean(context, resultItem, Constants.READ)) { + return Optional.of(potentialDuplicate); + } + } else if (authorizeService.isAdmin(context, resultItem)) { + // Admins can always read, return immediately + return Optional.of(potentialDuplicate); + } else { + log.info("Potential duplicate result is not readable by the current user, skipping item={}", + potentialDuplicate.getUuid()); + } + + // By default, return an empty result + return Optional.empty(); + } + + /** + * Search discovery for potential duplicates of a given item. The search uses levenshtein distance (configurable) + * and a single-term "comparison value" constructed out of the item title + * + * @param context DSpace context + * @param item The item to check + * @return DiscoverResult as a result of performing search. Null if invalid. + * + * @throws SearchServiceException if an error was encountered during the discovery search itself. + */ + @Override + public DiscoverResult searchDuplicates(Context context, Item item) throws SearchServiceException { + + // If the item is null or otherwise invalid (template, etc) then throw an appropriate error + if (item == null) { + throw new ResourceNotFoundException("Duplicate search error: item is null"); + } + if (item.getTemplateItemOf() != null) { + throw new IllegalArgumentException("Cannot get duplicates for template item"); + } + + // Build normalised comparison value + String comparisonValue = buildComparisonValue(context, item); + + // Construct query + if (StringUtils.isNotBlank(comparisonValue)) { + // Get search service + SearchService searchService = SearchUtils.getSearchService(); + + // Escape reserved solr characters + comparisonValue = searchService.escapeQueryChars(comparisonValue); + + // Construct discovery query based on comparison value + DiscoverQuery discoverQuery = new DiscoverQuery(); + discoverQuery.setQuery("(" + configurationService.getProperty("duplicate.comparison.solr.field", + "deduplication_keyword") + ":" + comparisonValue + "~" + + configurationService.getIntProperty("duplicate.comparison.distance", 0) + ")"); + // Add filter queries for the resource type + discoverQuery.addFilterQueries("(search.resourcetype:Item OR " + + "search.resourcetype:WorkspaceItem OR " + + "search.resourcetype:XmlWorkflowItem OR search.resourcetype:WorkflowItem)"); + // Skip this item itself so it isn't a false positive + discoverQuery.addFilterQueries("-search.resourceid:" + item.getID()); + + // Perform search and populate list with results, update total count integer + return searchService.search(context, discoverQuery); + } else { + log.warn("empty item comparison value, ignoring for duplicate search"); + } + + // Return null by default + return null; + + } + + /** + * Build a comparison value string made up of values of configured fields, used when indexing and querying + * items for deduplication + * @param context DSpace context + * @param item The DSpace item + * @return a constructed, normalised string + */ + @Override + public String buildComparisonValue(Context context, Item item) { + // Get configured fields to use for comparison values + String[] comparisonFields = configurationService.getArrayProperty("duplicate.comparison.metadata.field", + new String[]{"dc.title"}); + // Get all values, in order, for these fields + StringBuilder comparisonValueBuilder = new StringBuilder(); + String comparisonValue = null; + for (String field : comparisonFields) { + try { + // Get field components + String[] fieldParts = MetadataUtilities.parseCompoundForm(field); + // Get all values of this field + List metadataValues = itemService.getMetadata(item, + fieldParts[0], fieldParts[1], (fieldParts.length > 2 ? fieldParts[2] : null), Item.ANY); + // Sort metadata values by text value, so their 'position' in db doesn't matter for dedupe purposes + metadataValues.sort(comparing(MetadataValue::getValue, naturalOrder())); + for (MetadataValue metadataValue : metadataValues) { + // Add each found value to the string builder (null values interpreted as empty) + if (metadataValue != null) { + comparisonValueBuilder.append(metadataValue.getValue()); + } + } + } catch (ParseException e) { + // Log error and continue processing + log.error("Error parsing configured field for deduplication comparison: item={}, field={}", + item.getID(), field); + } catch (NullPointerException e) { + log.error("Null pointer encountered, probably during metadata value sort, when deduping:" + + "item={}, field={}", item.getID(), field); + } + } + + // Build string + comparisonValue = comparisonValueBuilder.toString(); + + // Normalise according to configuration + if (!StringUtils.isBlank(comparisonValue)) { + if (configurationService.getBooleanProperty("duplicate.comparison.normalise.lowercase")) { + comparisonValue = comparisonValue.toLowerCase(context.getCurrentLocale()); + } + if (configurationService.getBooleanProperty("duplicate.comparison.normalise.whitespace")) { + comparisonValue = comparisonValue.replaceAll("\\s+", ""); + } + } + + // Return comparison value + return comparisonValue; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/content/EntityType.java b/dspace-api/src/main/java/org/dspace/content/EntityType.java index 20ab758a0b76..720e0c492ca7 100644 --- a/dspace-api/src/main/java/org/dspace/content/EntityType.java +++ b/dspace-api/src/main/java/org/dspace/content/EntityType.java @@ -8,14 +8,14 @@ package org.dspace.content; import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/content/FeedbackServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/FeedbackServiceImpl.java index 7e34af132b0a..13f149f69f64 100644 --- a/dspace-api/src/main/java/org/dspace/content/FeedbackServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/FeedbackServiceImpl.java @@ -9,9 +9,9 @@ import java.io.IOException; import java.util.Date; import java.util.Objects; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.dspace.content.service.FeedbackService; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/content/Item.java b/dspace-api/src/main/java/org/dspace/content/Item.java index 547ff490b84b..5422528f84a3 100644 --- a/dspace-api/src/main/java/org/dspace/content/Item.java +++ b/dspace-api/src/main/java/org/dspace/content/Item.java @@ -14,27 +14,28 @@ import java.util.List; import java.util.Set; import java.util.UUID; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; +import jakarta.persistence.Transient; import org.dspace.content.comparator.NameAscendingComparator; 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.core.HibernateProxyHelper; import org.dspace.eperson.EPerson; -import org.hibernate.proxy.HibernateProxyHelper; + /** * Class representing an item in DSpace. 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 264685be7432..d60909d28771 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -97,7 +97,7 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It /** * log4j category */ - private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(Item.class); + private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(); @Autowired(required = true) protected ItemDAO itemDAO; @@ -1435,7 +1435,7 @@ public Iterator findByMetadataField(Context context, public List findByMetadataQuery(Context context, List queryPredicates, List collectionUuids, long offset, int limit) throws SQLException { - return itemDAO.findByMetadataQuery(context, queryPredicates, collectionUuids, "text_value ~ ?", + return itemDAO.findByMetadataQuery(context, queryPredicates, collectionUuids, "value ~ ?", offset, limit); } @@ -1444,7 +1444,7 @@ public List findByMetadataQuery(Context context, List quer public long countForMetadataQuery(Context context, List queryPredicates, List collectionUuids) throws SQLException { - return itemDAO.countForMetadataQuery(context, queryPredicates, collectionUuids, "text_value ~ ?"); + return itemDAO.countForMetadataQuery(context, queryPredicates, collectionUuids, "value ~ ?"); } @Override @@ -1742,6 +1742,8 @@ public List getMetadata(Item item, String schema, String element, */ @Override protected void moveSingleMetadataValue(Context context, Item dso, int place, MetadataValue rr) { + // If this is a (virtual) metadata value representing a relationship, + // then we must also update the corresponding Relationship with the new place if (rr instanceof RelationshipMetadataValue) { try { //Retrieve the applicable relationship @@ -1757,10 +1759,10 @@ protected void moveSingleMetadataValue(Context context, Item dso, int place, Met //should not occur, otherwise metadata can't be updated either log.error("An error occurred while moving " + rr.getAuthority() + " for item " + dso.getID(), e); } - } else { - //just move the metadata - rr.setPlace(place); } + + // Update the MetadataValue object with the new place setting + rr.setPlace(place); } @Override diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataField.java b/dspace-api/src/main/java/org/dspace/content/MetadataField.java index 8b767011999e..cbe90a374432 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataField.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataField.java @@ -7,23 +7,22 @@ */ package org.dspace.content; -import javax.persistence.Cacheable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.proxy.HibernateProxyHelper; /** @@ -58,8 +57,6 @@ public class MetadataField implements ReloadableEntity { @Column(name = "qualifier", length = 64) private String qualifier = null; - // @Column(name = "scope_note") -// @Lob @Column(name = "scope_note", columnDefinition = "text") private String scopeNote; diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataFieldName.java b/dspace-api/src/main/java/org/dspace/content/MetadataFieldName.java index 8d7f4b027733..32c08dab2b56 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataFieldName.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataFieldName.java @@ -8,7 +8,8 @@ package org.dspace.content; import java.util.Arrays; -import javax.annotation.Nonnull; + +import jakarta.annotation.Nonnull; /** * Simple immutable holder for the name of a metadata field. diff --git a/dspace-api/src/main/java/org/dspace/content/MetadataSchema.java b/dspace-api/src/main/java/org/dspace/content/MetadataSchema.java index f60e5e1604cf..b9a4665e6672 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataSchema.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataSchema.java @@ -7,19 +7,18 @@ */ package org.dspace.content; -import javax.persistence.Cacheable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.proxy.HibernateProxyHelper; /** * Class representing a schema in DSpace. 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 31479e620618..279bdd67c243 100644 --- a/dspace-api/src/main/java/org/dspace/content/MetadataValue.java +++ b/dspace-api/src/main/java/org/dspace/content/MetadataValue.java @@ -7,24 +7,22 @@ */ package org.dspace.content; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.Lob; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Transient; - +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; -import org.hibernate.annotations.Type; -import org.hibernate.proxy.HibernateProxyHelper; +import org.hibernate.Length; /** * Database access class representing a Dublin Core metadata value. @@ -59,9 +57,7 @@ public class MetadataValue implements ReloadableEntity { /** * The value of the field */ - @Lob - @Type(type = "org.hibernate.type.TextType") - @Column(name = "text_value") + @Column(name = "text_value", length = Length.LONG32) private String value; /** diff --git a/dspace-api/src/main/java/org/dspace/content/PredefinedUUIDGenerator.java b/dspace-api/src/main/java/org/dspace/content/PredefinedUUIDGenerator.java index aa4a8ea5429c..15d302ec6152 100644 --- a/dspace-api/src/main/java/org/dspace/content/PredefinedUUIDGenerator.java +++ b/dspace-api/src/main/java/org/dspace/content/PredefinedUUIDGenerator.java @@ -7,7 +7,6 @@ */ package org.dspace.content; -import java.io.Serializable; import java.util.UUID; import org.hibernate.engine.spi.SharedSessionContractImplementor; @@ -21,7 +20,7 @@ public class PredefinedUUIDGenerator extends UUIDGenerator { @Override - public Serializable generate(SharedSessionContractImplementor session, Object object) { + public Object generate(SharedSessionContractImplementor session, Object object) { if (object instanceof DSpaceObject) { UUID uuid = ((DSpaceObject) object).getPredefinedUUID(); if (uuid != null) { diff --git a/dspace-api/src/main/java/org/dspace/content/QAEventProcessed.java b/dspace-api/src/main/java/org/dspace/content/QAEventProcessed.java index 3631a2ff68c6..fcca5b45703a 100644 --- a/dspace-api/src/main/java/org/dspace/content/QAEventProcessed.java +++ b/dspace-api/src/main/java/org/dspace/content/QAEventProcessed.java @@ -9,15 +9,15 @@ import java.io.Serializable; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.eperson.EPerson; /** diff --git a/dspace-api/src/main/java/org/dspace/content/Relationship.java b/dspace-api/src/main/java/org/dspace/content/Relationship.java index 77c418a23dea..05e4b0071861 100644 --- a/dspace-api/src/main/java/org/dspace/content/Relationship.java +++ b/dspace-api/src/main/java/org/dspace/content/Relationship.java @@ -7,19 +7,20 @@ */ package org.dspace.content; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; /** * This class represents a relationship @@ -96,6 +97,7 @@ public class Relationship implements ReloadableEntity { * This column affects what version of an item appears on search pages or the relationship listings of other items. */ @Column(name = "latest_version_status") + @JdbcTypeCode(SqlTypes.INTEGER) private LatestVersionStatus latestVersionStatus = LatestVersionStatus.BOTH; /** diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipType.java b/dspace-api/src/main/java/org/dspace/content/RelationshipType.java index 5e6941052b83..ba5f0531e97e 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipType.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipType.java @@ -7,20 +7,21 @@ */ package org.dspace.content; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; /** * Class representing a RelationshipType @@ -118,6 +119,7 @@ public class RelationshipType implements ReloadableEntity { * The value indicating whether relationships of this type should be ignored on the right/left/neither. */ @Column(name = "tilted") + @JdbcTypeCode(SqlTypes.INTEGER) private Tilted tilted; /** diff --git a/dspace-api/src/main/java/org/dspace/content/Site.java b/dspace-api/src/main/java/org/dspace/content/Site.java index 0bdab6ffe564..904c1d3e6b86 100644 --- a/dspace-api/src/main/java/org/dspace/content/Site.java +++ b/dspace-api/src/main/java/org/dspace/content/Site.java @@ -7,28 +7,23 @@ */ package org.dspace.content; -import javax.persistence.Cacheable; -import javax.persistence.Entity; -import javax.persistence.Table; -import javax.persistence.Transient; - +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.SiteService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; -import org.hibernate.annotations.CacheConcurrencyStrategy; /** * Represents the root of the DSpace Archive. * By default, the handle suffix "0" represents the Site, e.g. "1721.1/0" */ @Entity -@Cacheable -@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) @Table(name = "site") -public class Site extends DSpaceObject { +public class Site extends CacheableDSpaceObject { @Transient private transient SiteService siteService; diff --git a/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java b/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java index a4c880173bf7..355e18269494 100644 --- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java +++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java @@ -8,23 +8,23 @@ package org.dspace.content; import java.io.Serializable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.eperson.EPerson; import org.dspace.workflow.WorkflowItem; -import org.hibernate.proxy.HibernateProxyHelper; /** * Class representing an item in the process of being submitted by a user 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 b6e7372af184..b78f6b9f7de8 100644 --- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java @@ -96,11 +96,18 @@ public WorkspaceItem find(Context context, int id) throws SQLException { @Override public WorkspaceItem create(Context context, Collection collection, boolean template) throws AuthorizeException, SQLException { - return create(context, collection, null, template); + return create(context, collection, null, template, false); } @Override - public WorkspaceItem create(Context context, Collection collection, UUID uuid, boolean template) + public WorkspaceItem create(Context context, Collection collection, boolean template, boolean isNewVersion) + throws AuthorizeException, SQLException { + return create(context, collection, null, template, isNewVersion); + } + + @Override + public WorkspaceItem create(Context context, Collection collection, UUID uuid, boolean template, + boolean isNewVersion) throws AuthorizeException, SQLException { // Check the user has permission to ADD to the collection authorizeService.authorizeAction(context, collection, Constants.ADD); @@ -174,8 +181,10 @@ public WorkspaceItem create(Context context, Collection collection, UUID uuid, b // If configured, register identifiers (eg handle, DOI) now. This is typically used with the Show Identifiers // submission step which previews minted handles and DOIs during the submission process. Default: false + // Additional check needed: if we are creating a new version of an existing item we skip the identifier + // generation here, as this will be performed when the new version is created in VersioningServiceImpl if (DSpaceServicesFactory.getInstance().getConfigurationService() - .getBooleanProperty("identifiers.submission.register", false)) { + .getBooleanProperty("identifiers.submission.register", false) && !isNewVersion) { try { // Get map of filters to use for identifier types, while the item is in progress Map, Filter> filters = FilterUtils.getIdentifierFilters(true); diff --git a/dspace-api/src/main/java/org/dspace/content/dao/ItemDAO.java b/dspace-api/src/main/java/org/dspace/content/dao/ItemDAO.java index 92dc0fb237c9..417c768882fa 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/ItemDAO.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/ItemDAO.java @@ -88,7 +88,7 @@ Iterator findByMetadataField(Context context, MetadataField metadataField, * @param collectionUuids UUIDs of the collections to search. * If none are provided, the entire repository will be searched. * @param regexClause Syntactic expression used to query the database using a regular expression - * (e.g.: "text_value ~ ?") + * (e.g.: "value ~ ?") * @param offset The offset for the query * @param limit Maximum number of items to return * @return A list containing the items that match the provided criteria diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamDAOImpl.java index 276ea2b3430a..25f102f6def4 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamDAOImpl.java @@ -13,16 +13,21 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.dspace.content.Bitstream; import org.dspace.content.Bitstream_; +import org.dspace.content.Bundle; +import org.dspace.content.Bundle_; import org.dspace.content.Collection; +import org.dspace.content.Collection_; import org.dspace.content.Community; import org.dspace.content.Item; +import org.dspace.content.Item_; import org.dspace.content.dao.BitstreamDAO; import org.dspace.core.AbstractHibernateDSODAO; import org.dspace.core.Constants; @@ -78,14 +83,21 @@ public List findBitstreamsWithNoRecentChecksum(Context context) throw @Override public Iterator findByCommunity(Context context, Community community) throws SQLException { - Query query = createQuery(context, "select b.id from Bitstream b " + - "join b.bundles bitBundles " + - "join bitBundles.items item " + - "join item.collections itemColl " + - "join itemColl.communities community " + - "WHERE :community IN community"); - - query.setParameter("community", community); + // Select UUID of all bitstreams, joining from Bitstream -> Bundle -> Item -> Collection -> Community + // to find all that exist under the given community. + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(UUID.class); + Root bitstreamRoot = criteriaQuery.from(Bitstream.class); + criteriaQuery.select(bitstreamRoot.get(Bitstream_.id)); + // Joins from Bitstream -> Bundle -> Item -> Collection + Join joinBundle = bitstreamRoot.join(Bitstream_.bundles); + Join joinItem = joinBundle.join(Bundle_.items); + Join joinCollection = joinItem.join(Item_.collections); + // Where "community" is a member of the list of Communities linked by the collection(s) + criteriaQuery.where(criteriaBuilder.isMember(community, joinCollection.get(Collection_.COMMUNITIES))); + + // Transform into a query object to execute + Query query = createQuery(context, criteriaQuery); @SuppressWarnings("unchecked") List uuids = query.getResultList(); return new UUIDIterator(context, uuids, Bitstream.class, this); @@ -93,13 +105,20 @@ public Iterator findByCommunity(Context context, Community community) @Override public Iterator findByCollection(Context context, Collection collection) throws SQLException { - Query query = createQuery(context, "select b.id from Bitstream b " + - "join b.bundles bitBundles " + - "join bitBundles.items item " + - "join item.collections c " + - "WHERE :collection IN c"); - - query.setParameter("collection", collection); + // Select UUID of all bitstreams, joining from Bitstream -> Bundle -> Item -> Collection + // to find all that exist under the given collection. + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(UUID.class); + Root bitstreamRoot = criteriaQuery.from(Bitstream.class); + criteriaQuery.select(bitstreamRoot.get(Bitstream_.id)); + // Joins from Bitstream -> Bundle -> Item + Join joinBundle = bitstreamRoot.join(Bitstream_.bundles); + Join joinItem = joinBundle.join(Bundle_.items); + // Where "collection" is a member of the list of Collections linked by the item(s) + criteriaQuery.where(criteriaBuilder.isMember(collection, joinItem.get(Item_.collections))); + + // Transform into a query object to execute + Query query = createQuery(context, criteriaQuery); @SuppressWarnings("unchecked") List uuids = query.getResultList(); return new UUIDIterator(context, uuids, Bitstream.class, this); @@ -107,12 +126,19 @@ public Iterator findByCollection(Context context, Collection collecti @Override public Iterator findByItem(Context context, Item item) throws SQLException { - Query query = createQuery(context, "select b.id from Bitstream b " + - "join b.bundles bitBundles " + - "join bitBundles.items item " + - "WHERE :item IN item"); - - query.setParameter("item", item); + // Select UUID of all bitstreams, joining from Bitstream -> Bundle -> Item + // to find all that exist under the given item. + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(UUID.class); + Root bitstreamRoot = criteriaQuery.from(Bitstream.class); + criteriaQuery.select(bitstreamRoot.get(Bitstream_.id)); + // Join from Bitstream -> Bundle + Join joinBundle = bitstreamRoot.join(Bitstream_.bundles); + // Where "item" is a member of the list of Items linked by the bundle(s) + criteriaQuery.where(criteriaBuilder.isMember(item, joinBundle.get(Bundle_.items))); + + // Transform into a query object to execute + Query query = createQuery(context, criteriaQuery); @SuppressWarnings("unchecked") List uuids = query.getResultList(); return new UUIDIterator(context, uuids, Bitstream.class, this); diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamFormatDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamFormatDAOImpl.java index 4d9283bbec4d..eaf58fbb887a 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamFormatDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/BitstreamFormatDAOImpl.java @@ -10,11 +10,11 @@ import java.sql.SQLException; import java.util.LinkedList; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.BitstreamFormat; import org.dspace.content.BitstreamFormat_; import org.dspace.content.dao.BitstreamFormatDAO; @@ -119,7 +119,7 @@ public List findNonInternal(Context context) throws SQLExceptio ); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.desc(bitstreamFormatRoot.get(BitstreamFormat_.supportLevel))); orderList.add(criteriaBuilder.asc(bitstreamFormatRoot.get(BitstreamFormat_.shortDescription))); criteriaQuery.orderBy(orderList); @@ -142,13 +142,10 @@ public List findByFileExtension(Context context, String extensi public List findAll(Context context, Class clazz) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, BitstreamFormat.class); + CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, BitstreamFormat.class); Root bitstreamFormatRoot = criteriaQuery.from(BitstreamFormat.class); criteriaQuery.select(bitstreamFormatRoot); - - List orderList = new LinkedList<>(); - orderList.add(criteriaBuilder.asc(bitstreamFormatRoot.get(BitstreamFormat_.id))); - criteriaQuery.orderBy(orderList); + criteriaQuery.orderBy(criteriaBuilder.asc(bitstreamFormatRoot.get(BitstreamFormat_.id))); return list(context, criteriaQuery, false, BitstreamFormat.class, -1, -1); } diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/CollectionDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/CollectionDAOImpl.java index c0ef6ea42fce..5ff8ce531850 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/CollectionDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/CollectionDAOImpl.java @@ -12,13 +12,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy_; import org.dspace.content.Collection; @@ -71,12 +71,12 @@ public List findAll(Context context, MetadataField order, Integer li query.append("SELECT c" + " FROM Collection c" + " left join c.metadata title on title.metadataField = :sortField and" + - " title.dSpaceObject = c.id and" + + " title.dSpaceObject = c and" + " title.place = (select min(internal.place) " + "from c.metadata internal " + "where internal.metadataField = :sortField and" + - " internal.dSpaceObject = c.id)" + - " ORDER BY LOWER(title.value)"); + " internal.dSpaceObject = c)" + + " ORDER BY LOWER(CAST(title.value as string))"); Query hibernateQuery = createQuery(context, query.toString()); if (offset != null) { hibernateQuery.setFirstResult(offset); diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/CommunityDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/CommunityDAOImpl.java index 7a3750485151..5712b898598e 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/CommunityDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/CommunityDAOImpl.java @@ -10,13 +10,13 @@ import java.sql.SQLException; import java.util.LinkedList; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy_; import org.dspace.content.Community; @@ -68,12 +68,12 @@ public List findAll(Context context, MetadataField sortField, Integer queryBuilder.append("SELECT c" + " FROM Community c" + " left join c.metadata title on title.metadataField = :sortField and" + - " title.dSpaceObject = c.id and" + + " title.dSpaceObject = c and" + " title.place = (select min(internal.place) " + "from c.metadata internal " + "where internal.metadataField = :sortField and" + - " internal.dSpaceObject = c.id)" + - " ORDER BY LOWER(title.value)"); + " internal.dSpaceObject = c)" + + " ORDER BY LOWER(CAST(title.value as string))"); Query query = createQuery(context, queryBuilder.toString()); if (offset != null) { query.setFirstResult(offset); @@ -108,13 +108,13 @@ public List findAllNoParent(Context context, MetadataField sortField) queryBuilder.append("SELECT c" + " FROM Community c" + " left join c.metadata title on title.metadataField = :sortField and" + - " title.dSpaceObject = c.id and" + + " title.dSpaceObject = c and" + " title.place = (select min(internal.place) " + "from c.metadata internal " + "where internal.metadataField = :sortField and" + - " internal.dSpaceObject = c.id)" + + " internal.dSpaceObject = c)" + " WHERE c.parentCommunities IS EMPTY " + - " ORDER BY LOWER(title.value)"); + " ORDER BY LOWER(CAST(title.value as string))"); Query query = createQuery(context, queryBuilder.toString()); query.setParameter("sortField", sortField); query.setHint("org.hibernate.cacheable", Boolean.TRUE); diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/EntityTypeDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/EntityTypeDAOImpl.java index 489f4cd0667d..32af7ed35c31 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/EntityTypeDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/EntityTypeDAOImpl.java @@ -10,11 +10,11 @@ import java.sql.SQLException; import java.util.LinkedList; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Order; +import jakarta.persistence.criteria.Root; import org.dspace.content.EntityType; import org.dspace.content.EntityType_; import org.dspace.content.dao.EntityTypeDAO; @@ -59,9 +59,9 @@ public List getEntityTypesByNames(Context context, List name @Override public int countEntityTypesByNames(Context context, List names) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, EntityType.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root entityTypeRoot = criteriaQuery.from(EntityType.class); - criteriaQuery.select(entityTypeRoot); + criteriaQuery.select(criteriaBuilder.count(entityTypeRoot)); criteriaQuery.where(entityTypeRoot.get(EntityType_.LABEL).in(names)); return count(context, criteriaQuery, criteriaBuilder, entityTypeRoot); } 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 0a36fdeb2ab0..94d2bb80c447 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 @@ -14,15 +14,15 @@ import java.util.Iterator; import java.util.List; import java.util.UUID; -import javax.persistence.Query; -import javax.persistence.TemporalType; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaBuilder.In; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; -import javax.persistence.criteria.Subquery; +import jakarta.persistence.Query; +import jakarta.persistence.TemporalType; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaBuilder.In; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Subquery; import org.apache.logging.log4j.Logger; import org.dspace.content.Collection; import org.dspace.content.DSpaceObject_; @@ -111,7 +111,7 @@ public Iterator findAll(Context context, boolean archived, queryStr.append(" AND discoverable = :discoverable"); if (lastModified != null) { - queryStr.append(" AND last_modified > :last_modified"); + queryStr.append(" AND lastModified > :last_modified"); } queryStr.append(" ORDER BY i.id"); @@ -203,7 +203,6 @@ public List findByMetadataQuery(Context context, List quer queryPredicates, collectionUuids, regexClause); criteriaQuery.where(criteriaBuilder.and(predicates.stream().toArray(Predicate[]::new))); criteriaQuery.orderBy(criteriaBuilder.asc(itemRoot.get(DSpaceObject_.id))); - criteriaQuery.groupBy(itemRoot.get(DSpaceObject_.id)); try { return list(context, criteriaQuery, false, Item.class, limit, (int) offset); } catch (Exception e) { @@ -217,7 +216,7 @@ public long countForMetadataQuery(Context context, List queryPre List collectionUuids, String regexClause) throws SQLException { // Build the query infrastructure CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Item.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); // Select Root itemRoot = criteriaQuery.from(Item.class); // Apply the selected predicates @@ -266,7 +265,7 @@ private List toPredicates(CriteriaBuilder criteriaBuilder, Criter Subquery mvQuery = query.subquery(MetadataValue.class); Root mvRoot = mvQuery.from(MetadataValue.class); mvPredicates.add(criteriaBuilder.equal( - mvRoot.get(MetadataValue_.D_SPACE_OBJECT), root.get(DSpaceObject_.ID))); + mvRoot.get(MetadataValue_.D_SPACE_OBJECT), root)); if (!predicate.getFields().isEmpty()) { In inFields = criteriaBuilder.in(mvRoot.get(MetadataValue_.METADATA_FIELD)); @@ -309,11 +308,18 @@ public Iterator findByAuthorityValue(Context context, MetadataField metada @Override public Iterator findArchivedByCollection(Context context, Collection collection, Integer limit, Integer offset) throws SQLException { - Query query = createQuery(context, - "select i.id from Item i join i.collections c " + - "WHERE :collection IN c AND i.inArchive=:in_archive ORDER BY i.id"); - query.setParameter("collection", collection); - query.setParameter("in_archive", true); + // Select UUID of all items which have this "collection" in their list of collections and are in_archive + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(UUID.class); + Root itemRoot = criteriaQuery.from(Item.class); + criteriaQuery.select(itemRoot.get(Item_.id)); + criteriaQuery.where(criteriaBuilder.and( + criteriaBuilder.isTrue((itemRoot.get(Item_.inArchive))), + criteriaBuilder.isMember(collection, itemRoot.get(Item_.collections)))); + criteriaQuery.orderBy(criteriaBuilder.asc(itemRoot.get((Item_.id)))); + + // Transform into a query object to execute + Query query = createQuery(context, criteriaQuery); if (offset != null) { query.setFirstResult(offset); } @@ -337,16 +343,15 @@ public Iterator findArchivedByCollectionExcludingOwning(Context context, C criteriaBuilder.isMember(collection, itemRoot.get(Item_.collections)), criteriaBuilder.isTrue(itemRoot.get(Item_.inArchive)))); criteriaQuery.orderBy(criteriaBuilder.asc(itemRoot.get(DSpaceObject_.id))); - criteriaQuery.groupBy(itemRoot.get(DSpaceObject_.id)); return list(context, criteriaQuery, false, Item.class, limit, offset).iterator(); } @Override public int countArchivedByCollectionExcludingOwning(Context context, Collection collection) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Item.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root itemRoot = criteriaQuery.from(Item.class); - criteriaQuery.select(itemRoot); + criteriaQuery.select(criteriaBuilder.count(itemRoot)); criteriaQuery.where(criteriaBuilder.and( criteriaBuilder.notEqual(itemRoot.get(Item_.owningCollection), collection), criteriaBuilder.isMember(collection, itemRoot.get(Item_.collections)), @@ -356,9 +361,16 @@ public int countArchivedByCollectionExcludingOwning(Context context, Collection @Override public Iterator findAllByCollection(Context context, Collection collection) throws SQLException { - Query query = createQuery(context, - "select i.id from Item i join i.collections c WHERE :collection IN c ORDER BY i.id"); - query.setParameter("collection", collection); + // Select UUID of all items which have this "collection" in their list of collections + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(UUID.class); + Root itemRoot = criteriaQuery.from(Item.class); + criteriaQuery.select(itemRoot.get(Item_.id)); + criteriaQuery.where(criteriaBuilder.isMember(collection, itemRoot.get(Item_.collections))); + criteriaQuery.orderBy(criteriaBuilder.asc(itemRoot.get((Item_.id)))); + + // Transform into a query object to execute + Query query = createQuery(context, criteriaQuery); @SuppressWarnings("unchecked") List uuids = query.getResultList(); return new UUIDIterator(context, uuids, Item.class, this); @@ -367,10 +379,16 @@ public Iterator findAllByCollection(Context context, Collection collection @Override public Iterator findAllByCollection(Context context, Collection collection, Integer limit, Integer offset) throws SQLException { - Query query = createQuery(context, - "select i.id from Item i join i.collections c WHERE :collection IN c ORDER BY i.id"); - query.setParameter("collection", collection); + // Build Query to select UUID of all items which have this "collection" in their list of collections. + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(UUID.class); + Root itemRoot = criteriaQuery.from(Item.class); + criteriaQuery.select(itemRoot.get(Item_.id)); + criteriaQuery.where(criteriaBuilder.isMember(collection, itemRoot.get(Item_.collections))); + criteriaQuery.orderBy(criteriaBuilder.asc(itemRoot.get((Item_.id)))); + // Transform into a query object to execute + Query query = createQuery(context, criteriaQuery); if (offset != null) { query.setFirstResult(offset); } @@ -385,14 +403,18 @@ public Iterator findAllByCollection(Context context, Collection collection @Override public int countItems(Context context, Collection collection, boolean includeArchived, boolean includeWithdrawn) throws SQLException { - Query query = createQuery(context, - "select count(i) from Item i join i.collections c " + - "WHERE :collection IN c AND i.inArchive=:in_archive AND i.withdrawn=:withdrawn"); - query.setParameter("collection", collection); - query.setParameter("in_archive", includeArchived); - query.setParameter("withdrawn", includeWithdrawn); - - return count(query); + // Build query to select all Items have this "collection" in their list of collections + // AND also have the inArchive or isWithdrawn set as specified + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); + Root itemRoot = criteriaQuery.from(Item.class); + criteriaQuery.select(criteriaBuilder.count(itemRoot)); + criteriaQuery.where(criteriaBuilder.and( + criteriaBuilder.equal(itemRoot.get(Item_.inArchive), includeArchived), + criteriaBuilder.equal(itemRoot.get(Item_.withdrawn), includeWithdrawn), + criteriaBuilder.isMember(collection, itemRoot.get(Item_.collections)))); + // Execute and return count + return count(context, criteriaQuery, criteriaBuilder, itemRoot); } @Override diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataFieldDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataFieldDAOImpl.java index e64aaa4dd29f..ddbde361d5ac 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataFieldDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataFieldDAOImpl.java @@ -12,12 +12,12 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.content.MetadataField; @@ -158,7 +158,7 @@ public List findAll(Context context, Class clazz) Join join = metadataFieldRoot.join("metadataSchema"); criteriaQuery.select(metadataFieldRoot); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(join.get(MetadataSchema_.name))); orderList.add(criteriaBuilder.asc(metadataFieldRoot.get(MetadataField_.element))); orderList.add(criteriaBuilder.asc(metadataFieldRoot.get(MetadataField_.qualifier))); diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataSchemaDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataSchemaDAOImpl.java index 71eb487b8395..4630bed90b16 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataSchemaDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataSchemaDAOImpl.java @@ -10,11 +10,11 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.MetadataSchema; import org.dspace.content.MetadataSchema_; import org.dspace.content.dao.MetadataSchemaDAO; @@ -63,7 +63,7 @@ public List findAll(Context context, Class clazz) throws SQLExce Root metadataSchemaRoot = criteriaQuery.from(MetadataSchema.class); criteriaQuery.select(metadataSchemaRoot); - List orderList = new ArrayList<>(); + List orderList = new ArrayList<>(); orderList.add(criteriaBuilder.asc(metadataSchemaRoot.get(MetadataSchema_.id))); criteriaQuery.orderBy(orderList); diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataValueDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataValueDAOImpl.java index f37ced9ab7d4..dc624c98c6aa 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataValueDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/MetadataValueDAOImpl.java @@ -10,12 +10,12 @@ import java.sql.SQLException; import java.util.Iterator; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.dspace.content.MetadataField; import org.dspace.content.MetadataField_; import org.dspace.content.MetadataValue; @@ -53,7 +53,7 @@ public Iterator findItemValuesByFieldAndValue(Context context, MetadataField metadataField, String value) throws SQLException { String queryString = "SELECT m from MetadataValue m " + - "join Item i on m.dSpaceObject = i.id where m.metadataField.id = :metadata_field_id " + + "join Item i on m.dSpaceObject = i where m.metadataField.id = :metadata_field_id " + "and m.value = :text_value"; Query query = createQuery(context, queryString); query.setParameter("metadata_field_id", metadataField.getID()); @@ -84,7 +84,7 @@ public void deleteByMetadataField(Context context, MetadataField metadataField) public MetadataValue getMinimum(Context context, int metadataFieldId) throws SQLException { String queryString = "SELECT m FROM MetadataValue m JOIN FETCH m.metadataField WHERE m.metadataField.id = " + - ":metadata_field_id ORDER BY text_value"; + ":metadata_field_id ORDER BY value"; Query query = createQuery(context, queryString); query.setParameter("metadata_field_id", metadataFieldId); query.setMaxResults(1); diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/ProcessDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/ProcessDAOImpl.java index d719b5006c14..829dd3280078 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/ProcessDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/ProcessDAOImpl.java @@ -14,11 +14,11 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; +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.StringUtils; import org.dspace.content.ProcessStatus; import org.dspace.content.dao.ProcessDAO; @@ -75,9 +75,9 @@ public List findAll(Context context, int limit, int offset) throws SQLE public int countRows(Context context) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root processRoot = criteriaQuery.from(Process.class); - criteriaQuery.select(processRoot); + criteriaQuery.select(criteriaBuilder.count(processRoot)); return count(context, criteriaQuery, criteriaBuilder, processRoot); @@ -143,9 +143,9 @@ public int countTotalWithParameters(Context context, ProcessQueryParameterContai throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root processRoot = criteriaQuery.from(Process.class); - criteriaQuery.select(processRoot); + criteriaQuery.select(criteriaBuilder.count(processRoot)); addProcessQueryParameters(processQueryParameterContainer, criteriaBuilder, criteriaQuery, processRoot); return count(context, criteriaQuery, criteriaBuilder, processRoot); @@ -178,7 +178,7 @@ public List findByUser(Context context, EPerson user, int limit, int of criteriaQuery.select(processRoot); criteriaQuery.where(criteriaBuilder.equal(processRoot.get(Process_.E_PERSON), user)); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.desc(processRoot.get(Process_.PROCESS_ID))); criteriaQuery.orderBy(orderList); @@ -188,10 +188,10 @@ public List findByUser(Context context, EPerson user, int limit, int of @Override public int countByUser(Context context, EPerson user) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root processRoot = criteriaQuery.from(Process.class); - criteriaQuery.select(processRoot); + criteriaQuery.select(criteriaBuilder.count(processRoot)); criteriaQuery.where(criteriaBuilder.equal(processRoot.get(Process_.E_PERSON), user)); return count(context, criteriaQuery, criteriaBuilder, processRoot); } diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipDAOImpl.java index e2f84bc1cb64..43bbc15c31b8 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipDAOImpl.java @@ -12,13 +12,13 @@ import java.util.List; import java.util.UUID; import java.util.stream.Collectors; -import javax.persistence.Query; -import javax.persistence.Tuple; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; import org.dspace.content.Item; import org.dspace.content.Item_; import org.dspace.content.Relationship; @@ -167,9 +167,9 @@ public int countByItem( Context context, Item item, boolean excludeTilted, boolean excludeNonLatest ) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root relationshipRoot = criteriaQuery.from(Relationship.class); - criteriaQuery.select(relationshipRoot); + criteriaQuery.select(criteriaBuilder.count(relationshipRoot)); criteriaQuery.where( criteriaBuilder.or( @@ -355,9 +355,9 @@ public List findByTypeName(Context context, String typeName, Integ public int countByRelationshipType(Context context, RelationshipType relationshipType) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root relationshipRoot = criteriaQuery.from(Relationship.class); - criteriaQuery.select(relationshipRoot); + criteriaQuery.select(criteriaBuilder.count(relationshipRoot)); criteriaQuery .where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType), relationshipType)); return count(context, criteriaQuery, criteriaBuilder, relationshipRoot); @@ -366,9 +366,9 @@ public int countByRelationshipType(Context context, RelationshipType relationshi @Override public int countRows(Context context) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root relationshipRoot = criteriaQuery.from(Relationship.class); - criteriaQuery.select(relationshipRoot); + criteriaQuery.select(criteriaBuilder.count(relationshipRoot)); return count(context, criteriaQuery, criteriaBuilder, relationshipRoot); } @@ -377,9 +377,9 @@ public int countByItemAndRelationshipType( Context context, Item item, RelationshipType relationshipType, boolean isLeft, boolean excludeNonLatest ) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root relationshipRoot = criteriaQuery.from(Relationship.class); - criteriaQuery.select(relationshipRoot); + criteriaQuery.select(criteriaBuilder.count(relationshipRoot)); if (isLeft) { criteriaQuery.where( @@ -407,8 +407,9 @@ public int countByTypeName(Context context, String typeName) ids.add(relationshipType.getID()); } CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root relationshipRoot = criteriaQuery.from(Relationship.class); + criteriaQuery.select(criteriaBuilder.count(relationshipRoot)); criteriaQuery.where(relationshipRoot.get(Relationship_.relationshipType).in(ids)); return count(context, criteriaQuery, criteriaBuilder, relationshipRoot); } @@ -417,14 +418,14 @@ public int countByTypeName(Context context, String typeName) public List findByItemAndRelationshipTypeAndList(Context context, UUID focusUUID, RelationshipType relationshipType, List items, boolean isLeft, int offset, int limit) throws SQLException { - String side = isLeft ? "left_id" : "right_id"; - String otherSide = !isLeft ? "left_id" : "right_id"; + String side = isLeft ? "leftItem.id" : "rightItem.id"; + String otherSide = !isLeft ? "leftItem.id" : "rightItem.id"; Query query = createQuery(context, "FROM " + Relationship.class.getSimpleName() + - " WHERE type_id = (:typeId) " + + " WHERE relationshipType = :type " + "AND " + side + " = (:focusUUID) " + "AND " + otherSide + " in (:list) " + "ORDER BY id"); - query.setParameter("typeId", relationshipType.getID()); + query.setParameter("type", relationshipType); query.setParameter("focusUUID", focusUUID); query.setParameter("list", items); return list(query, limit, offset); @@ -433,14 +434,14 @@ public List findByItemAndRelationshipTypeAndList(Context context, @Override public int countByItemAndRelationshipTypeAndList(Context context, UUID focusUUID, RelationshipType relationshipType, List items, boolean isLeft) throws SQLException { - String side = isLeft ? "left_id" : "right_id"; - String otherSide = !isLeft ? "left_id" : "right_id"; + String side = isLeft ? "leftItem.id" : "rightItem.id"; + String otherSide = !isLeft ? "leftItem.id" : "rightItem.id"; Query query = createQuery(context, "SELECT count(*) " + "FROM " + Relationship.class.getSimpleName() + - " WHERE type_id = (:typeId) " + + " WHERE relationshipType = :type " + "AND " + side + " = (:focusUUID) " + "AND " + otherSide + " in (:list)"); - query.setParameter("typeId", relationshipType.getID()); + query.setParameter("type", relationshipType); query.setParameter("focusUUID", focusUUID); query.setParameter("list", items); return count(query); diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipTypeDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipTypeDAOImpl.java index 7fff2a1f57da..7b0e33fd41d9 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipTypeDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipTypeDAOImpl.java @@ -10,10 +10,10 @@ import java.sql.SQLException; import java.util.LinkedList; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.EntityType; import org.dspace.content.RelationshipType; import org.dspace.content.RelationshipType_; @@ -93,7 +93,7 @@ public List findByEntityType(Context context, EntityType entit .equal(relationshipTypeRoot.get(RelationshipType_.rightType), entityType) ) ); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(relationshipTypeRoot.get(RelationshipType_.ID))); criteriaQuery.orderBy(orderList); return list(context, criteriaQuery, false, RelationshipType.class, limit, offset); @@ -128,9 +128,9 @@ public List findByEntityType(Context context, EntityType entit @Override public int countByEntityType(Context context, EntityType entityType) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root relationshipTypeRoot = criteriaQuery.from(RelationshipType.class); - criteriaQuery.select(relationshipTypeRoot); + criteriaQuery.select(criteriaBuilder.count(relationshipTypeRoot)); criteriaQuery.where(criteriaBuilder.or( criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftType), entityType), criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightType), entityType) diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/SiteDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/SiteDAOImpl.java index 8889909b1a49..ebaa78ae3788 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/SiteDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/SiteDAOImpl.java @@ -8,10 +8,10 @@ package org.dspace.content.dao.impl; import java.sql.SQLException; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.Site; import org.dspace.content.dao.SiteDAO; import org.dspace.core.AbstractHibernateDAO; diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/WorkspaceItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/WorkspaceItemDAOImpl.java index 138451365522..0862a81e8678 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/WorkspaceItemDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/WorkspaceItemDAOImpl.java @@ -12,11 +12,11 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.content.WorkspaceItem; @@ -88,7 +88,7 @@ public List findAll(Context context) throws SQLException { Root workspaceItemRoot = criteriaQuery.from(WorkspaceItem.class); criteriaQuery.select(workspaceItemRoot); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(workspaceItemRoot.get(WorkspaceItem_.workspaceItemId))); criteriaQuery.orderBy(orderList); @@ -103,7 +103,7 @@ public List findAll(Context context, Integer limit, Integer offse Root workspaceItemRoot = criteriaQuery.from(WorkspaceItem.class); criteriaQuery.select(workspaceItemRoot); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(workspaceItemRoot.get(WorkspaceItem_.workspaceItemId))); criteriaQuery.orderBy(orderList); diff --git a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java index 0b06b34038e1..3a897081f07c 100644 --- a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java +++ b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java @@ -20,6 +20,7 @@ import org.dspace.content.service.CommunityService; import org.dspace.content.service.DSpaceObjectLegacySupportService; import org.dspace.content.service.DSpaceObjectService; +import org.dspace.content.service.DuplicateDetectionService; import org.dspace.content.service.EntityService; import org.dspace.content.service.EntityTypeService; import org.dspace.content.service.InProgressSubmissionService; @@ -113,6 +114,13 @@ public InProgressSubmissionService getInProgressSubmissionService(InProgressSubm } } + /** + * Return the implementation of the DuplicateDetectionService interface + * + * @return the DuplicateDetectionService + */ + public abstract DuplicateDetectionService getDuplicateDetectionService(); + public DSpaceObjectService getDSpaceObjectService(T dso) { return getDSpaceObjectService(dso.getType()); } diff --git a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java index e970f0bdab12..3c3c2bf162bb 100644 --- a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java @@ -18,6 +18,7 @@ import org.dspace.content.service.CommunityService; import org.dspace.content.service.DSpaceObjectLegacySupportService; import org.dspace.content.service.DSpaceObjectService; +import org.dspace.content.service.DuplicateDetectionService; import org.dspace.content.service.EntityService; import org.dspace.content.service.EntityTypeService; import org.dspace.content.service.InstallItemService; @@ -81,6 +82,8 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory { private EntityTypeService entityTypeService; @Autowired(required = true) private EntityService entityService; + @Autowired(required = true) + private DuplicateDetectionService duplicateDetectionService; @Override public List> getDSpaceObjectServices() { @@ -181,4 +184,9 @@ public EntityService getEntityService() { public RelationshipMetadataService getRelationshipMetadataService() { return relationshipMetadataService; } + + @Override + public DuplicateDetectionService getDuplicateDetectionService() { + return duplicateDetectionService; + } } diff --git a/dspace-api/src/main/java/org/dspace/content/packager/PackageParameters.java b/dspace-api/src/main/java/org/dspace/content/packager/PackageParameters.java index b472a52c3bad..f2b95118675b 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/PackageParameters.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/PackageParameters.java @@ -9,7 +9,8 @@ import java.util.Enumeration; import java.util.Properties; -import javax.servlet.ServletRequest; + +import jakarta.servlet.ServletRequest; /** * Parameter list for SIP and DIP packagers. It's really just diff --git a/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java b/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java index 9e7d870076aa..9a8ae4606487 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java @@ -503,7 +503,7 @@ public static DSpaceObject createDSpaceObject(Context context, DSpaceObject pare wsi = workspaceItemService.create(context, (Collection)parent, params.useCollectionTemplate()); } else { wsi = workspaceItemService.create(context, (Collection)parent, - uuid, params.useCollectionTemplate()); + uuid, params.useCollectionTemplate(), false); } // Please note that we are returning an Item which is *NOT* yet in the Archive, diff --git a/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java b/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java index 8effabf28435..c22428f11a96 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java @@ -13,8 +13,8 @@ import java.util.Iterator; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.BitstreamFormat; diff --git a/dspace-api/src/main/java/org/dspace/content/service/DuplicateDetectionService.java b/dspace-api/src/main/java/org/dspace/content/service/DuplicateDetectionService.java new file mode 100644 index 000000000000..1f0d3495b1d6 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/content/service/DuplicateDetectionService.java @@ -0,0 +1,85 @@ +/** + * 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.content.service; + +import java.sql.SQLException; +import java.util.List; +import java.util.Optional; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DuplicateDetectionServiceImpl; +import org.dspace.content.Item; +import org.dspace.content.virtual.PotentialDuplicate; +import org.dspace.core.Context; +import org.dspace.discovery.DiscoverResult; +import org.dspace.discovery.IndexableObject; +import org.dspace.discovery.SearchServiceException; + +/** + * Duplicate Detection Service handles get, search and validation operations for duplicate detection. + * @see DuplicateDetectionServiceImpl for implementation details + * + * @author Kim Shepherd + */ +public interface DuplicateDetectionService { + + /** + * Logger + */ + Logger log = LogManager.getLogger(DuplicateDetectionService.class); + + /** + * Get a list of PotentialDuplicate objects (wrappers with some metadata included for previewing) that + * are identified as potential duplicates of the given item + * + * @param context DSpace context + * @param item Item to check + * @return List of potential duplicates (empty if none found) + * @throws SearchServiceException if an error occurs performing the discovery search + */ + List getPotentialDuplicates(Context context, Item item) + throws SearchServiceException; + + /** + * Validate an indexable object (returned by discovery search) to ensure it is permissible, readable and valid + * and can be added to a list of results. + * An Optional is returned, if it is empty then it was invalid or did not pass validation. + * + * @param context The DSpace context + * @param indexableObject The discovery search result + * @param original The original item (to compare IDs, submitters, etc) + * @return An Optional potential duplicate + * @throws SQLException + * @throws AuthorizeException + */ + Optional validateDuplicateResult(Context context, IndexableObject indexableObject, + Item original) throws SQLException, AuthorizeException; + + /** + * Search discovery for potential duplicates of a given item. The search uses levenshtein distance (configurable) + * and a single-term "comparison value" constructed out of the item title + * + * @param context DSpace context + * @param item The item to check + * @return DiscoverResult as a result of performing search. Null if invalid. + * + * @throws SearchServiceException if an error was encountered during the discovery search itself. + */ + DiscoverResult searchDuplicates(Context context, Item item) throws SearchServiceException; + + /** + * Build a comparison value string made up of values of configured fields, used when indexing and querying + * items for deduplication + * @param context DSpace context + * @param item The DSpace item + * @return a constructed, normalised string + */ + String buildComparisonValue(Context context, Item item); +} diff --git a/dspace-api/src/main/java/org/dspace/content/service/FeedbackService.java b/dspace-api/src/main/java/org/dspace/content/service/FeedbackService.java index d21afd678000..7eac0ee61dc2 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/FeedbackService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/FeedbackService.java @@ -7,9 +7,9 @@ */ package org.dspace.content.service; import java.io.IOException; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; /** diff --git a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java index c8df68e43498..8559bcc61402 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java @@ -56,6 +56,23 @@ public interface WorkspaceItemService extends InProgressSubmissionServicetrue, the workspace item starts as a copy + * of the collection's template item + * @param isNewVersion whether we are creating a new workspace item version of an existing item + * @return the newly created workspace item + * @throws SQLException if database error + * @throws AuthorizeException if authorization error + */ + public WorkspaceItem create(Context context, Collection collection, boolean template, boolean isNewVersion) + throws AuthorizeException, SQLException; + /** * Create a new workspace item, with a new ID. An Item is also created. The * submitter is the current user in the context. @@ -65,11 +82,13 @@ public WorkspaceItem create(Context context, Collection collection, boolean temp * @param uuid the preferred uuid of the new item (used if restoring an item and retaining old uuid) * @param template if true, the workspace item starts as a copy * of the collection's template item + * @param isNewVersion whether we are creating a new workspace item version of an existing item * @return the newly created workspace item * @throws SQLException if database error * @throws AuthorizeException if authorization error */ - public WorkspaceItem create(Context context, Collection collection, UUID uuid, boolean template) + public WorkspaceItem create(Context context, Collection collection, UUID uuid, boolean template, + boolean isNewVersion) throws AuthorizeException, SQLException; public WorkspaceItem create(Context c, WorkflowItem wfi) throws SQLException, AuthorizeException; diff --git a/dspace-api/src/main/java/org/dspace/content/virtual/PotentialDuplicate.java b/dspace-api/src/main/java/org/dspace/content/virtual/PotentialDuplicate.java new file mode 100644 index 000000000000..6c193bb28506 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/content/virtual/PotentialDuplicate.java @@ -0,0 +1,176 @@ +/** + * 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.content.virtual; + +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +import org.dspace.content.Item; +import org.dspace.content.MetadataValue; + +/** + * Model of potential duplicate item. Provides as little data as possible, but enough to be useful + * about the context / state of the duplicate, and metadata for preview purposes. + * This class lives in the virtual package because it is not stored, addressable data, it's a stub / preview + * based on an items' search result and metadata. + * + * @author Kim Shepherd + */ +public class PotentialDuplicate { + /** + * Title of duplicate object + */ + private String title; + /** + * UUID of duplicate object + */ + private UUID uuid; + /** + * Owning collection name (title) for duplicate item + */ + private String owningCollectionName; + /** + * Workspace item ID, if the duplicate is a workspace item + */ + private Integer workspaceItemId; + /** + * Workflow item ID, if the duplicate is a workflow item + */ + private Integer workflowItemId; + + /** + * List of configured metadata values copied across from the duplicate item + */ + private List metadataValueList; + + /** + * Default constructor + */ + public PotentialDuplicate() { + this.metadataValueList = new LinkedList<>(); + } + + /** + * Constructor that accepts an item and sets some values accordingly + * @param item the potential duplicate item + */ + public PotentialDuplicate(Item item) { + // Throw error if item is null + if (item == null) { + throw new NullPointerException("Null item passed to potential duplicate constructor"); + } + // Instantiate metadata value list + this.metadataValueList = new LinkedList<>(); + // Set title + this.title = item.getName(); + // Set UUID + this.uuid = item.getID(); + // Set owning collection name + if (item.getOwningCollection() != null) { + this.owningCollectionName = item.getOwningCollection().getName(); + } + } + + /** + * Get UUID of duplicate item + * @return UUID of duplicate item + */ + public UUID getUuid() { + return uuid; + } + + /** + * Set UUID of duplicate item + * @param uuid UUID of duplicate item + */ + public void setUuid(UUID uuid) { + this.uuid = uuid; + } + + /** + * Get title of duplicate item + * @return title of duplicate item + */ + public String getTitle() { + return title; + } + + /** + * Set title of duplicate item + * @param title of duplicate item + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * Get owning collection name (title) of duplicate item + * @return owning collection name (title) of duplicate item + */ + public String getOwningCollectionName() { + return owningCollectionName; + } + + /** + * Set owning collection name (title) of duplicate item + * @param owningCollectionName owning collection name (title) of duplicate item + */ + public void setOwningCollectionName(String owningCollectionName) { + this.owningCollectionName = owningCollectionName; + } + + /** + * Get workspace ID for duplicate item, if any + * @return workspace item ID or null + */ + public Integer getWorkspaceItemId() { + return workspaceItemId; + } + + /** + * Set workspace ID for duplicate item + * @param workspaceItemId workspace item ID + */ + public void setWorkspaceItemId(Integer workspaceItemId) { + this.workspaceItemId = workspaceItemId; + } + + /** + * Get workflow ID for duplicate item, if anh + * @return workflow item ID or null + */ + public Integer getWorkflowItemId() { + return workflowItemId; + } + + /** + * Set workflow ID for duplicate item + * @param workflowItemId workspace item ID + */ + public void setWorkflowItemId(Integer workflowItemId) { + this.workflowItemId = workflowItemId; + } + + /** + * Get metadata (sorted, field->value list) for duplicate item + * @return (sorted, field->value list) for duplicate item + */ + public List getMetadataValueList() { + return metadataValueList; + } + + /** + * Set metadata (sorted, field->value list) for duplicate item + * @param metadataValueList MetadataRest list of values mapped to field keys + */ + public void setMetadataValueList(List metadataValueList) { + this.metadataValueList = metadataValueList; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/contentreport/QueryOperator.java b/dspace-api/src/main/java/org/dspace/contentreport/QueryOperator.java index 1fb6e5fc0ffc..7cd8606f8348 100644 --- a/dspace-api/src/main/java/org/dspace/contentreport/QueryOperator.java +++ b/dspace-api/src/main/java/org/dspace/contentreport/QueryOperator.java @@ -8,13 +8,13 @@ package org.dspace.contentreport; import java.util.Arrays; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Path; -import javax.persistence.criteria.Predicate; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Predicate; import org.apache.commons.lang3.function.TriFunction; import org.dspace.content.MetadataValue; import org.dspace.content.MetadataValue_; diff --git a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java index 38923658f0dd..3658a3c92305 100644 --- a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java +++ b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDAO.java @@ -13,13 +13,13 @@ import java.util.Map; import java.util.UUID; import java.util.stream.Stream; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Root; import com.google.common.collect.AbstractIterator; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Root; import org.apache.commons.collections.CollectionUtils; import org.hibernate.Session; @@ -471,4 +471,15 @@ public List findByX(Context context, Class clazz, Map equals, return executeCriteriaQuery(context, criteria, cacheable, maxResults, offset); } + /** + * Create a Query object from a CriteriaQuery + * @param context current Context + * @param criteriaQuery CriteriaQuery built via CriteriaBuilder + * @return corresponding Query + * @throws SQLException if error occurs + */ + public Query createQuery(Context context, CriteriaQuery criteriaQuery) throws SQLException { + return this.getHibernateSession(context).createQuery(criteriaQuery); + } + } diff --git a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDSODAO.java b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDSODAO.java index e9c6b95b7f05..d72a4d619003 100644 --- a/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDSODAO.java +++ b/dspace-api/src/main/java/org/dspace/core/AbstractHibernateDSODAO.java @@ -10,10 +10,10 @@ import java.sql.SQLException; import java.util.Collection; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.ListUtils; import org.apache.commons.lang3.StringUtils; diff --git a/dspace-api/src/main/java/org/dspace/core/Constants.java b/dspace-api/src/main/java/org/dspace/core/Constants.java index f730ef6545f1..98bb1b7731a0 100644 --- a/dspace-api/src/main/java/org/dspace/core/Constants.java +++ b/dspace-api/src/main/java/org/dspace/core/Constants.java @@ -55,11 +55,16 @@ public class Constants { */ public static final int EPERSON = 7; + /** + * Type of LDN MESSAGE objects + */ + public static final int LDN_MESSAGE = 8; + /** * lets you look up type names from the type IDs */ public static final String[] typeText = { "BITSTREAM", "BUNDLE", "ITEM", "COLLECTION", "COMMUNITY", "SITE", "GROUP", - "EPERSON"}; + "EPERSON", "LDN_MESSAGE"}; /** * Special Bundle and Bitstream Names: 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 f6df740a53ef..b36275e83bfa 100644 --- a/dspace-api/src/main/java/org/dspace/core/Email.java +++ b/dspace-api/src/main/java/org/dspace/core/Email.java @@ -23,23 +23,23 @@ import java.util.Enumeration; import java.util.List; import java.util.Properties; -import javax.activation.DataHandler; -import javax.activation.DataSource; -import javax.activation.FileDataSource; -import javax.mail.Address; -import javax.mail.BodyPart; -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.Multipart; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.ContentType; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; -import javax.mail.internet.ParseException; +import jakarta.activation.DataHandler; +import jakarta.activation.DataSource; +import jakarta.activation.FileDataSource; +import jakarta.mail.Address; +import jakarta.mail.BodyPart; +import jakarta.mail.Message; +import jakarta.mail.MessagingException; +import jakarta.mail.Multipart; +import jakarta.mail.Session; +import jakarta.mail.Transport; +import jakarta.mail.internet.ContentType; +import jakarta.mail.internet.InternetAddress; +import jakarta.mail.internet.MimeBodyPart; +import jakarta.mail.internet.MimeMessage; +import jakarta.mail.internet.MimeMultipart; +import jakarta.mail.internet.ParseException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.velocity.Template; 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..a867849077a3 100644 --- a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java @@ -27,7 +27,6 @@ import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.proxy.HibernateProxyHelper; import org.hibernate.resource.transaction.spi.TransactionStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; diff --git a/dspace-api/src/main/java/org/dspace/core/HibernateProxyHelper.java b/dspace-api/src/main/java/org/dspace/core/HibernateProxyHelper.java new file mode 100644 index 000000000000..22f91a48aa7f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/HibernateProxyHelper.java @@ -0,0 +1,39 @@ +/** + * 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 org.hibernate.proxy.HibernateProxy; +import org.hibernate.proxy.LazyInitializer; + +/** + * Utility methods for working with Hibernate proxies. + * This class existed in Hibernate 5 but was removed from v6. + * https://github.com/hibernate/hibernate-orm/blob/5.6/hibernate-core/src/main/java/org/hibernate/proxy/HibernateProxyHelper.java + * We've copied it into DSpace to utilize the below utility method. + */ +public final class HibernateProxyHelper { + + /** + * Get the class of an instance or the underlying class + * of a proxy (without initializing the proxy!). It is + * almost always better to use the entity name! + */ + public static Class getClassWithoutInitializingProxy(Object object) { + if (object instanceof HibernateProxy) { + HibernateProxy proxy = (HibernateProxy) object; + LazyInitializer li = proxy.getHibernateLazyInitializer(); + return li.getPersistentClass(); + } else { + return object.getClass(); + } + } + + private HibernateProxyHelper() { + //cant instantiate + } +} diff --git a/dspace-api/src/main/java/org/dspace/core/LDN.java b/dspace-api/src/main/java/org/dspace/core/LDN.java index 283850eb1059..8ae5cddf5b4a 100644 --- a/dspace-api/src/main/java/org/dspace/core/LDN.java +++ b/dspace-api/src/main/java/org/dspace/core/LDN.java @@ -19,8 +19,8 @@ import java.util.Collections; import java.util.List; import java.util.Properties; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/core/LicenseServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/LicenseServiceImpl.java index 80bc0beac83a..766e72e94125 100644 --- a/dspace-api/src/main/java/org/dspace/core/LicenseServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/LicenseServiceImpl.java @@ -17,8 +17,8 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.core.service.LicenseService; diff --git a/dspace-api/src/main/java/org/dspace/discovery/FullTextContentStreams.java b/dspace-api/src/main/java/org/dspace/discovery/FullTextContentStreams.java index 21468def6866..58abf18698a1 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/FullTextContentStreams.java +++ b/dspace-api/src/main/java/org/dspace/discovery/FullTextContentStreams.java @@ -20,10 +20,10 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.List; -import javax.annotation.Nullable; import com.google.common.base.Function; import com.google.common.collect.Iterables; +import jakarta.annotation.Nullable; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java b/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java index 80602ac80459..611200e62a5d 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java @@ -73,17 +73,22 @@ public void consume(Context ctx, Event event) throws Exception { int st = event.getSubjectType(); if (!(st == Constants.ITEM || st == Constants.BUNDLE - || st == Constants.COLLECTION || st == Constants.COMMUNITY || st == Constants.SITE)) { + || st == Constants.COLLECTION || st == Constants.COMMUNITY || st == Constants.SITE + || st == Constants.LDN_MESSAGE)) { log .warn("IndexConsumer should not have been given this kind of Subject in an event, skipping: " + event.toString()); return; } - DSpaceObject subject = event.getSubject(ctx); - - DSpaceObject object = event.getObject(ctx); - + DSpaceObject subject = null; + DSpaceObject object = null; + try { + subject = event.getSubject(ctx); + object = event.getObject(ctx); + } catch (Exception e) { + log.warn("Could not find the related DSpace Object for event subject: " + st); + } // If event subject is a Bundle and event was Add or Remove, // transform the event to be a Modify on the owning Item. @@ -110,7 +115,7 @@ public void consume(Context ctx, Event event) throws Exception { case Event.MODIFY: case Event.MODIFY_METADATA: if (subject == null) { - if (st == Constants.SITE) { + if (st == Constants.SITE || st == Constants.LDN_MESSAGE) { // Update the indexable objects of type in event.detail of objects with ids in event.identifiers for (String id : event.getIdentifiers()) { IndexFactory indexableObjectService = IndexObjectFactoryFactory.getInstance(). 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 f31feab6123a..6304f39a8ca9 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java @@ -8,8 +8,8 @@ package org.dspace.discovery; import java.io.IOException; -import javax.inject.Named; +import jakarta.inject.Named; import org.apache.commons.validator.routines.UrlValidator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; 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..a0c1188d7132 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -30,8 +30,8 @@ import java.util.Optional; import java.util.TimeZone; import java.util.UUID; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.Transformer; diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexComparisonPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexComparisonPlugin.java new file mode 100644 index 000000000000..001d1c51a4dd --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexComparisonPlugin.java @@ -0,0 +1,95 @@ +/** + * 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.discovery; + +import org.apache.logging.log4j.Logger; +import org.apache.solr.common.SolrInputDocument; +import org.apache.tika.utils.StringUtils; +import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; +import org.dspace.content.service.DuplicateDetectionService; +import org.dspace.content.service.ItemService; +import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableItem; +import org.dspace.discovery.indexobject.IndexableWorkflowItem; +import org.dspace.discovery.indexobject.IndexableWorkspaceItem; +import org.dspace.services.ConfigurationService; +import org.dspace.workflow.WorkflowItem; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Indexes special normalised values used for comparing items, to be used in e.g. basic duplicate detection + * + * @author Kim Shepherd + */ +public class SolrServiceIndexComparisonPlugin implements SolrServiceIndexPlugin { + + @Autowired + ConfigurationService configurationService; + @Autowired + ItemService itemService; + @Autowired + DuplicateDetectionService duplicateDetectionService; + + private static final Logger log = org.apache.logging.log4j.LogManager + .getLogger(SolrServiceIndexComparisonPlugin.class); + + /** + * Index the normalised name of the item to a solr field + * + * @param context DSpace context + * @param idxObj the indexable item + * @param document the Solr document + */ + @Override + public void additionalIndex(Context context, IndexableObject idxObj, SolrInputDocument document) { + // Immediately return if this feature is not configured + if (!configurationService.getBooleanProperty("duplicate.enable", false)) { + return; + } + // Otherwise, continue with item indexing. Handle items, workflow items, and workspace items + if (idxObj instanceof IndexableItem) { + indexItemComparisonValue(context, ((IndexableItem) idxObj).getIndexedObject(), document); + } else if (idxObj instanceof IndexableWorkspaceItem) { + WorkspaceItem workspaceItem = ((IndexableWorkspaceItem) idxObj).getIndexedObject(); + if (workspaceItem != null) { + Item item = workspaceItem.getItem(); + if (item != null) { + indexItemComparisonValue(context, item, document); + } + } + } else if (idxObj instanceof IndexableWorkflowItem) { + WorkflowItem workflowItem = ((IndexableWorkflowItem) idxObj).getIndexedObject(); + if (workflowItem != null) { + Item item = workflowItem.getItem(); + if (item != null) { + indexItemComparisonValue(context, item, document); + } + } + } + } + + /** + * Add the actual comparison value field to the given solr doc + * + * @param context DSpace context + * @param item DSpace item + * @param document Solr document + */ + private void indexItemComparisonValue(Context context, Item item, SolrInputDocument document) { + if (item != null) { + // Build normalised comparison value and add to the document + String comparisonValue = duplicateDetectionService.buildComparisonValue(context, item); + if (!StringUtils.isBlank(comparisonValue)) { + // Add the field to the document + document.addField(configurationService.getProperty("duplicate.comparison.solr.field", + "deduplication_keyword"), comparisonValue); + } + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortConfiguration.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortConfiguration.java index cd1a4eecb8d4..066e3c73e9ee 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortConfiguration.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.List; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableLDNNotification.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableLDNNotification.java new file mode 100644 index 000000000000..86d600b6c97e --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableLDNNotification.java @@ -0,0 +1,53 @@ +/** + * 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.discovery.indexobject; + +import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.discovery.IndexableObject; + +/** + * {@link LDNMessageEntity} implementation for the {@link IndexableObject} + * + * @author Stefano Maffei at 4science.com + */ +public class IndexableLDNNotification extends AbstractIndexableObject { + + private LDNMessageEntity ldnMessage; + public static final String TYPE = LDNMessageEntity.class.getSimpleName(); + + public IndexableLDNNotification(LDNMessageEntity ldnMessage) { + super(); + this.ldnMessage = ldnMessage; + } + + @Override + public String getType() { + return getTypeText(); + } + + @Override + public String getID() { + return ldnMessage.getID(); + } + + @Override + public LDNMessageEntity getIndexedObject() { + return ldnMessage; + } + + @Override + public void setIndexedObject(LDNMessageEntity object) { + this.ldnMessage = object; + } + + @Override + public String getTypeText() { + return TYPE; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/LDNMessageEntityIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/LDNMessageEntityIndexFactoryImpl.java new file mode 100644 index 000000000000..7752ae58627f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/LDNMessageEntityIndexFactoryImpl.java @@ -0,0 +1,157 @@ +/** + * 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.discovery.indexobject; + +import static org.apache.commons.lang3.time.DateFormatUtils.format; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import org.apache.solr.common.SolrInputDocument; +import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.app.ldn.NotifyServiceEntity; +import org.dspace.app.ldn.service.LDNMessageService; +import org.dspace.content.Item; +import org.dspace.content.service.ItemService; +import org.dspace.core.Context; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Factory implementation implementation for the + * {@link IndexableLDNNotification} + * + * @author Stefano Maffei at 4science.com + */ +public class LDNMessageEntityIndexFactoryImpl extends IndexFactoryImpl { + + @Autowired(required = true) + private LDNMessageService ldnMessageService; + @Autowired(required = true) + private ItemService itemService; + + @Override + public Iterator findAll(Context context) throws SQLException { + final Iterator ldnNotifications = ldnMessageService.findAll(context).iterator(); + return new Iterator<>() { + @Override + public boolean hasNext() { + return ldnNotifications.hasNext(); + } + + @Override + public IndexableLDNNotification next() { + return new IndexableLDNNotification(ldnNotifications.next()); + } + }; + } + + @Override + public String getType() { + return IndexableLDNNotification.TYPE; + } + + @Override + public Optional findIndexableObject(Context context, String id) throws SQLException { + final LDNMessageEntity ldnMessage = ldnMessageService.find(context, id); + return ldnMessage == null ? Optional.empty() : Optional.of(new IndexableLDNNotification(ldnMessage)); + } + + @Override + public boolean supports(Object object) { + return object instanceof LDNMessageEntity; + } + + @Override + public List getIndexableObjects(Context context, LDNMessageEntity object) + throws SQLException { + return Arrays.asList(new IndexableLDNNotification(object)); + } + + @Override + public SolrInputDocument buildDocument(Context context, IndexableLDNNotification indexableObject) + throws SQLException, IOException { + // Add the ID's, types and call the SolrServiceIndexPlugins + final SolrInputDocument doc = super.buildDocument(context, indexableObject); + final LDNMessageEntity ldnMessage = indexableObject.getIndexedObject(); + // add schema, element, qualifier and full fieldName + doc.addField("notification_id", ldnMessage.getID()); + doc.addField("queue_status_i", ldnMessage.getQueueStatus()); + doc.addField("queue_status_s", LDNMessageEntity.getQueueStatus(ldnMessage)); + addFacetIndex(doc, "queue_status", String.valueOf(ldnMessage.getQueueStatus()), + LDNMessageEntity.getQueueStatus(ldnMessage)); + if (ldnMessage.getObject() != null && ldnMessage.getObject().getID() != null) { + Item item = itemService.findByIdOrLegacyId(context, ldnMessage.getObject().getID().toString()); + if (item != null) { + addFacetIndex(doc, "object", item.getID().toString(), itemService.getMetadata(item, "dc.title")); + addFacetIndex(doc, "relateditem", item.getID().toString(), itemService.getMetadata(item, "dc.title")); + } + } + if (ldnMessage.getContext() != null && ldnMessage.getContext().getID() != null) { + Item item = itemService.findByIdOrLegacyId(context, ldnMessage.getContext().getID().toString()); + if (item != null) { + addFacetIndex(doc, "context", item.getID().toString(), itemService.getMetadata(item, "dc.title")); + addFacetIndex(doc, "relateditem", item.getID().toString(), itemService.getMetadata(item, "dc.title")); + } + } + NotifyServiceEntity origin = ldnMessage.getOrigin(); + if (origin != null) { + addFacetIndex(doc, "origin", String.valueOf(origin.getID()), + LDNMessageEntity.getServiceNameForNotifyServ(origin)); + addFacetIndex(doc, "ldn_service", String.valueOf(origin.getID()), + LDNMessageEntity.getServiceNameForNotifyServ(origin)); + } + NotifyServiceEntity target = ldnMessage.getTarget(); + if (target != null) { + addFacetIndex(doc, "target", String.valueOf(target.getID()), + LDNMessageEntity.getServiceNameForNotifyServ(target)); + addFacetIndex(doc, "ldn_service", String.valueOf(target.getID()), + LDNMessageEntity.getServiceNameForNotifyServ(target)); + } + if (ldnMessage.getInReplyTo() != null) { + doc.addField("in_reply_to", ldnMessage.getInReplyTo().getID()); + } + doc.addField("message", ldnMessage.getMessage()); + doc.addField("type", ldnMessage.getType()); + addFacetIndex(doc, "activity_stream_type", ldnMessage.getActivityStreamType(), + ldnMessage.getActivityStreamType()); + addFacetIndex(doc, "coar_notify_type", ldnMessage.getCoarNotifyType(), ldnMessage.getCoarNotifyType()); + doc.addField("queue_attempts", ldnMessage.getQueueAttempts()); + doc.addField("queue_attempts_sort", ldnMessage.getQueueAttempts()); + + indexDateFieldForFacet(doc, ldnMessage.getQueueLastStartTime()); + + doc.addField("queue_timeout", ldnMessage.getQueueTimeout()); + String notificationType = LDNMessageEntity.getNotificationType(ldnMessage); + addFacetIndex(doc, "notification_type", notificationType, notificationType); + + return doc; + } + + private void indexDateFieldForFacet(SolrInputDocument doc, Date queueLastStartTime) { + if (queueLastStartTime != null) { + String value = format(queueLastStartTime, "yyyy-MM-dd"); + addFacetIndex(doc, "queue_last_start_time", value, value); + doc.addField("queue_last_start_time", value); + doc.addField("queue_last_start_time_dt", queueLastStartTime); + doc.addField("queue_last_start_time_min", value); + doc.addField("queue_last_start_time_min_sort", value); + doc.addField("queue_last_start_time_max", value); + doc.addField("queue_last_start_time_max_sort", value); + doc.addField("queue_last_start_time.year", + Integer.parseInt(format(queueLastStartTime, "yyyy"))); + doc.addField("queue_last_start_time.year_sort", + Integer.parseInt(format(queueLastStartTime, "yyyy"))); + } + } + +} diff --git a/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java index 3d4eab125f92..4fb95962b2e6 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java @@ -10,8 +10,8 @@ import java.io.IOException; import java.sql.SQLException; import java.util.Locale; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.authenticate.service.AuthenticationService; @@ -73,7 +73,7 @@ protected AccountServiceImpl() { * @param email Email address to send the registration email to * @throws java.sql.SQLException passed through. * @throws java.io.IOException passed through. - * @throws javax.mail.MessagingException passed through. + * @throws jakarta.mail.MessagingException passed through. * @throws org.dspace.authorize.AuthorizeException passed through. */ @Override @@ -105,7 +105,7 @@ public void sendRegistrationInfo(Context context, String email) * @param email Email address to send the forgot-password email to * @throws java.sql.SQLException passed through. * @throws java.io.IOException passed through. - * @throws javax.mail.MessagingException passed through. + * @throws jakarta.mail.MessagingException passed through. * @throws org.dspace.authorize.AuthorizeException passed through. */ @Override 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 0ab66aea5c2e..b213675b163e 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/CaptchaServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/CaptchaServiceImpl.java @@ -14,9 +14,9 @@ import java.util.List; import java.util.Objects; import java.util.regex.Pattern; -import javax.annotation.PostConstruct; 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; diff --git a/dspace-api/src/main/java/org/dspace/eperson/EPerson.java b/dspace-api/src/main/java/org/dspace/eperson/EPerson.java index da83a1cafd37..996fc96e3aa8 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/EPerson.java +++ b/dspace-api/src/main/java/org/dspace/eperson/EPerson.java @@ -11,27 +11,25 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import javax.persistence.Cacheable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.ManyToMany; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; +import jakarta.persistence.Transient; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.dspace.content.DSpaceObject; +import org.dspace.content.CacheableDSpaceObject; import org.dspace.content.DSpaceObjectLegacySupport; import org.dspace.content.Item; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.eperson.factory.EPersonServiceFactory; import org.dspace.eperson.service.EPersonService; -import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.proxy.HibernateProxyHelper; /** * Class representing an e-person. @@ -39,10 +37,8 @@ * @author David Stuve */ @Entity -@Cacheable -@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy") @Table(name = "eperson") -public class EPerson extends DSpaceObject implements DSpaceObjectLegacySupport { +public class EPerson extends CacheableDSpaceObject implements DSpaceObjectLegacySupport { @Column(name = "eperson_id", insertable = false, updatable = false) private Integer legacyId; diff --git a/dspace-api/src/main/java/org/dspace/eperson/EPersonConsumer.java b/dspace-api/src/main/java/org/dspace/eperson/EPersonConsumer.java index feefe65717df..8679d74b2421 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/EPersonConsumer.java +++ b/dspace-api/src/main/java/org/dspace/eperson/EPersonConsumer.java @@ -10,8 +10,8 @@ import java.io.IOException; import java.util.Date; import java.util.UUID; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.core.Constants; diff --git a/dspace-api/src/main/java/org/dspace/eperson/Group.java b/dspace-api/src/main/java/org/dspace/eperson/Group.java index 67655e0e0aaf..24b44b8149a4 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/Group.java +++ b/dspace-api/src/main/java/org/dspace/eperson/Group.java @@ -10,23 +10,21 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.persistence.Cacheable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import org.apache.commons.lang3.StringUtils; -import org.dspace.content.DSpaceObject; +import org.dspace.content.CacheableDSpaceObject; import org.dspace.content.DSpaceObjectLegacySupport; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.proxy.HibernateProxyHelper; +import org.dspace.core.HibernateProxyHelper; /** * Class representing a group of e-people. @@ -34,10 +32,8 @@ * @author David Stuve */ @Entity -@Cacheable -@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy") @Table(name = "epersongroup") -public class Group extends DSpaceObject implements DSpaceObjectLegacySupport { +public class Group extends CacheableDSpaceObject implements DSpaceObjectLegacySupport { @Transient public static final String ANONYMOUS = "Anonymous"; 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..a1c12371f5ff 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java +++ b/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java @@ -8,14 +8,14 @@ package org.dspace.eperson; import java.io.Serializable; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import org.hibernate.proxy.HibernateProxyHelper; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import org.dspace.core.HibernateProxyHelper; /** * Database entity representation of the group2groupcache table diff --git a/dspace-api/src/main/java/org/dspace/eperson/RegistrationData.java b/dspace-api/src/main/java/org/dspace/eperson/RegistrationData.java index f4f41bdff2eb..0d0c5e7db851 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/RegistrationData.java +++ b/dspace-api/src/main/java/org/dspace/eperson/RegistrationData.java @@ -8,16 +8,16 @@ package org.dspace.eperson; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/eperson/Subscription.java b/dspace-api/src/main/java/org/dspace/eperson/Subscription.java index 5db63740f477..0f473a5a750d 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/Subscription.java +++ b/dspace-api/src/main/java/org/dspace/eperson/Subscription.java @@ -9,19 +9,19 @@ import java.util.ArrayList; import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/eperson/SubscriptionParameter.java b/dspace-api/src/main/java/org/dspace/eperson/SubscriptionParameter.java index 7526535d7fcd..8d372966b10a 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/SubscriptionParameter.java +++ b/dspace-api/src/main/java/org/dspace/eperson/SubscriptionParameter.java @@ -7,16 +7,15 @@ */ package org.dspace.eperson; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.ReloadableEntity; /** diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/EPersonDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/EPersonDAOImpl.java index 87d6c5869b09..7d8e0720c45f 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/EPersonDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/EPersonDAOImpl.java @@ -15,11 +15,11 @@ 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.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.ListUtils; import org.apache.commons.lang3.StringUtils; 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..1cd359188ca3 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 @@ -10,12 +10,12 @@ import java.sql.SQLException; import java.util.LinkedList; import java.util.List; -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 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.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.Group; diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/GroupDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/GroupDAOImpl.java index 6aea9ecd8d67..abd9fc830fa4 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/GroupDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/GroupDAOImpl.java @@ -11,8 +11,8 @@ import java.util.Collections; import java.util.List; import java.util.UUID; -import javax.persistence.Query; +import jakarta.persistence.Query; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.dspace.content.MetadataField; diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/RegistrationDataDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/RegistrationDataDAOImpl.java index 4a15dcc86796..63e87400ce36 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/RegistrationDataDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/RegistrationDataDAOImpl.java @@ -8,11 +8,11 @@ package org.dspace.eperson.dao.impl; import java.sql.SQLException; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.RegistrationData; diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionDAOImpl.java index 6c36211f310c..d3d4748728ce 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionDAOImpl.java @@ -11,12 +11,12 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.dspace.content.DSpaceObject; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; @@ -44,11 +44,12 @@ protected SubscriptionDAOImpl() { public List findByEPerson(Context context, EPerson eperson, Integer limit, Integer offset) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - javax.persistence.criteria.CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class); + jakarta.persistence.criteria.CriteriaQuery criteriaQuery = + getCriteriaQuery(criteriaBuilder, Subscription.class); Root subscriptionRoot = criteriaQuery.from(Subscription.class); criteriaQuery.select(subscriptionRoot); criteriaQuery.where(criteriaBuilder.equal(subscriptionRoot.get(Subscription_.ePerson), eperson)); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.dSpaceObject))); criteriaQuery.orderBy(orderList); return list(context, criteriaQuery, false, Subscription.class, limit, offset); @@ -59,7 +60,7 @@ public List findByEPersonAndDso(Context context, EPerson eperson, DSpaceObject dSpaceObject, Integer limit, Integer offset) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - javax.persistence.criteria.CriteriaQuery criteriaQuery = + jakarta.persistence.criteria.CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class); Root subscriptionRoot = criteriaQuery.from(Subscription.class); criteriaQuery.select(subscriptionRoot); @@ -67,7 +68,7 @@ public List findByEPersonAndDso(Context context, EPerson eperson, subscriptionRoot.get(Subscription_.ePerson), eperson), criteriaBuilder.equal(subscriptionRoot.get(Subscription_.dSpaceObject), dSpaceObject) )); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.dSpaceObject))); criteriaQuery.orderBy(orderList); return list(context, criteriaQuery, false, Subscription.class, limit, offset); @@ -104,7 +105,7 @@ public void deleteByDSOAndEPerson(Context context, DSpaceObject dSpaceObject, EP public List findAllOrderedByIDAndResourceType(Context context, String resourceType, Integer limit, Integer offset) throws SQLException { String hqlQuery = "select s from Subscription s join %s dso " + - "ON dso.id = s.dSpaceObject ORDER BY subscription_id"; + "ON dso = s.dSpaceObject ORDER BY s.id"; if (resourceType != null) { hqlQuery = String.format(hqlQuery, resourceType); } @@ -125,7 +126,7 @@ public List findAllOrderedByDSO(Context context, Integer limit, In CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class); Root subscriptionRoot = criteriaQuery.from(Subscription.class); criteriaQuery.select(subscriptionRoot); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.dSpaceObject))); criteriaQuery.orderBy(orderList); return list(context, criteriaQuery, false, Subscription.class, limit, offset); @@ -145,7 +146,7 @@ public List findAllSubscriptionsBySubscriptionTypeAndFrequency(Con criteriaBuilder.equal(childJoin.get(SubscriptionParameter_.name), "frequency"), criteriaBuilder.equal(childJoin.get(SubscriptionParameter_.value), frequencyValue) )); - List orderList = new ArrayList<>(1); + List orderList = new ArrayList<>(1); orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.ePerson))); orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.id))); criteriaQuery.orderBy(orderList); diff --git a/dspace-api/src/main/java/org/dspace/eperson/service/AccountService.java b/dspace-api/src/main/java/org/dspace/eperson/service/AccountService.java index c8ecb0cc67d4..637b81c41da2 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/service/AccountService.java +++ b/dspace-api/src/main/java/org/dspace/eperson/service/AccountService.java @@ -9,8 +9,8 @@ import java.io.IOException; import java.sql.SQLException; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; import org.dspace.eperson.EPerson; diff --git a/dspace-api/src/main/java/org/dspace/eperson/service/EPersonService.java b/dspace-api/src/main/java/org/dspace/eperson/service/EPersonService.java index 2afec161a672..b3583155f354 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/service/EPersonService.java +++ b/dspace-api/src/main/java/org/dspace/eperson/service/EPersonService.java @@ -13,8 +13,8 @@ import java.util.Date; import java.util.List; import java.util.Set; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Item; import org.dspace.content.MetadataFieldName; diff --git a/dspace-api/src/main/java/org/dspace/event/Event.java b/dspace-api/src/main/java/org/dspace/event/Event.java index af8b2d45713f..a673cd985274 100644 --- a/dspace-api/src/main/java/org/dspace/event/Event.java +++ b/dspace-api/src/main/java/org/dspace/event/Event.java @@ -104,8 +104,10 @@ public class Event implements Serializable { protected static final int EPERSON = 1 << Constants.EPERSON; // 7 + protected static final int LDN_MESSAGE = 1 << Constants.LDN_MESSAGE; // 8 + protected static final int ALL_OBJECTS_MASK = BITSTREAM | BUNDLE | ITEM - | COLLECTION | COMMUNITY | SITE | GROUP | EPERSON; + | COLLECTION | COMMUNITY | SITE | GROUP | EPERSON | LDN_MESSAGE; protected static Map objTypeToMask = new HashMap(); @@ -135,6 +137,9 @@ public class Event implements Serializable { objTypeToMask.put(Constants.EPERSON, EPERSON); objMaskToType.put(EPERSON, Constants.EPERSON); + + objTypeToMask.put(Constants.LDN_MESSAGE, LDN_MESSAGE); + objMaskToType.put(LDN_MESSAGE, Constants.LDN_MESSAGE); } /** ---------- Event Fields ------------- * */ 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 c96fad1de01c..27688df6c758 100644 --- a/dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java +++ b/dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java @@ -16,7 +16,6 @@ import java.util.ArrayList; import java.util.Base64; import java.util.List; -import javax.xml.bind.JAXBException; import eu.openaire.jaxb.helper.OpenAIREHandler; import eu.openaire.jaxb.model.Response; @@ -278,7 +277,7 @@ public Response search(String path, int page, int size) { if (result != null) { try { return OpenAIREHandler.unmarshal(result); - } catch (JAXBException e) { + } catch (Exception e) { log.error("Error extracting result from request: " + queryString); getGotError(e, path); } diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidPublicationDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidPublicationDataProvider.java index 9a4f9c9b423c..05dabe0a5bdc 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidPublicationDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidPublicationDataProvider.java @@ -485,7 +485,7 @@ private boolean doesNotContains(ExternalDataObject externalDataObject, Metadatum private boolean hasRole(Contributor contributor, ContributorRole role) { ContributorAttributes attributes = contributor.getContributorAttributes(); - return attributes != null ? role.equals(attributes.getContributorRole()) : false; + return attributes != null ? role.value().equals(attributes.getContributorRole()) : false; } private Optional getContributorName(Contributor contributor) { 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 756b8654f285..578db6c56749 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 @@ -9,13 +9,13 @@ import java.io.InputStream; import java.net.URISyntaxException; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Unmarshaller; import org.xml.sax.SAXException; /** diff --git a/dspace-api/src/main/java/org/dspace/google/GoogleAsyncEventListener.java b/dspace-api/src/main/java/org/dspace/google/GoogleAsyncEventListener.java index c1c59acf4a63..68c492d1a9a0 100644 --- a/dspace-api/src/main/java/org/dspace/google/GoogleAsyncEventListener.java +++ b/dspace-api/src/main/java/org/dspace/google/GoogleAsyncEventListener.java @@ -13,9 +13,9 @@ import java.util.List; import java.util.UUID; import java.util.stream.Collectors; -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.collections.Buffer; import org.apache.commons.collections.BufferUtils; import org.apache.commons.collections.buffer.CircularFifoBuffer; diff --git a/dspace-api/src/main/java/org/dspace/google/GoogleRecorderEventListener.java b/dspace-api/src/main/java/org/dspace/google/GoogleRecorderEventListener.java index 4159661b1ced..fb4e9c04de5b 100644 --- a/dspace-api/src/main/java/org/dspace/google/GoogleRecorderEventListener.java +++ b/dspace-api/src/main/java/org/dspace/google/GoogleRecorderEventListener.java @@ -13,8 +13,8 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; diff --git a/dspace-api/src/main/java/org/dspace/handle/Handle.java b/dspace-api/src/main/java/org/dspace/handle/Handle.java index c35511353a3a..29182ad56c89 100644 --- a/dspace-api/src/main/java/org/dspace/handle/Handle.java +++ b/dspace-api/src/main/java/org/dspace/handle/Handle.java @@ -7,17 +7,16 @@ */ package org.dspace.handle; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.dspace.content.DSpaceObject; diff --git a/dspace-api/src/main/java/org/dspace/handle/dao/impl/HandleDAOImpl.java b/dspace-api/src/main/java/org/dspace/handle/dao/impl/HandleDAOImpl.java index 71bb798ae387..495f1f05a446 100644 --- a/dspace-api/src/main/java/org/dspace/handle/dao/impl/HandleDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/handle/dao/impl/HandleDAOImpl.java @@ -13,11 +13,11 @@ import java.sql.SQLException; import java.util.Collections; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.DSpaceObject; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; @@ -91,10 +91,9 @@ public List findByPrefix(Context context, String prefix) throws SQLExcep @Override public long countHandlesByPrefix(Context context, String prefix) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); - CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Handle.class); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root handleRoot = criteriaQuery.from(Handle.class); - criteriaQuery.select(handleRoot); criteriaQuery.where(criteriaBuilder.like(handleRoot.get(Handle_.handle), prefix + "%")); return countLong(context, criteriaQuery, criteriaBuilder, handleRoot); } @@ -137,7 +136,7 @@ public Long execute(Connection connection) throws SQLException { // Find the next value in our sequence (based on DB dialect) try (PreparedStatement preparedStatement = connection - .prepareStatement(dialect.getSequenceNextValString(HANDLE_SEQUENCE))) { + .prepareStatement("SELECT nextval('" + HANDLE_SEQUENCE + "')")) { // Execute query and return results try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { diff --git a/dspace-api/src/main/java/org/dspace/harvest/HarvestedCollection.java b/dspace-api/src/main/java/org/dspace/harvest/HarvestedCollection.java index 9fe2bed67d32..dc65ce254222 100644 --- a/dspace-api/src/main/java/org/dspace/harvest/HarvestedCollection.java +++ b/dspace-api/src/main/java/org/dspace/harvest/HarvestedCollection.java @@ -8,20 +8,20 @@ package org.dspace.harvest; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; +import jakarta.persistence.Transient; import org.dspace.content.Collection; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/harvest/HarvestedItem.java b/dspace-api/src/main/java/org/dspace/harvest/HarvestedItem.java index 343347136bc3..943543f405de 100644 --- a/dspace-api/src/main/java/org/dspace/harvest/HarvestedItem.java +++ b/dspace-api/src/main/java/org/dspace/harvest/HarvestedItem.java @@ -8,19 +8,19 @@ package org.dspace.harvest; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/harvest/dao/impl/HarvestedCollectionDAOImpl.java b/dspace-api/src/main/java/org/dspace/harvest/dao/impl/HarvestedCollectionDAOImpl.java index 95a0bdf2163e..ab942a74ef07 100644 --- a/dspace-api/src/main/java/org/dspace/harvest/dao/impl/HarvestedCollectionDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/harvest/dao/impl/HarvestedCollectionDAOImpl.java @@ -11,11 +11,11 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; import org.dspace.content.Collection; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; @@ -46,7 +46,7 @@ public HarvestedCollection findByStatusAndMinimalTypeOrderByLastHarvestedDesc(Co Root harvestedCollectionRoot = criteriaQuery.from(HarvestedCollection.class); criteriaQuery.select(harvestedCollectionRoot); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.desc(harvestedCollectionRoot.get(HarvestedCollection_.lastHarvested))); criteriaQuery.orderBy(orderList); @@ -61,7 +61,7 @@ public HarvestedCollection findByStatusAndMinimalTypeOrderByLastHarvestedAsc(Con Root harvestedCollectionRoot = criteriaQuery.from(HarvestedCollection.class); criteriaQuery.select(harvestedCollectionRoot); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(harvestedCollectionRoot.get(HarvestedCollection_.lastHarvested))); criteriaQuery.orderBy(orderList); @@ -138,7 +138,7 @@ public HarvestedCollection findByCollection(Context context, Collection collecti ) ); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.asc(harvestedCollectionRoot.get(HarvestedCollection_.lastHarvested))); criteriaQuery.orderBy(orderList); @@ -150,11 +150,10 @@ public HarvestedCollection findByCollection(Context context, Collection collecti @Override public int count(Context context) throws SQLException { - CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); - Root harvestedCollectionRoot = criteriaQuery.from(HarvestedCollection.class); + criteriaQuery.select(criteriaBuilder.count(harvestedCollectionRoot)); return count(context, criteriaQuery, criteriaBuilder, harvestedCollectionRoot); } diff --git a/dspace-api/src/main/java/org/dspace/harvest/dao/impl/HarvestedItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/harvest/dao/impl/HarvestedItemDAOImpl.java index 9e9838be6c1c..bb7ff0ee7cc4 100644 --- a/dspace-api/src/main/java/org/dspace/harvest/dao/impl/HarvestedItemDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/harvest/dao/impl/HarvestedItemDAOImpl.java @@ -8,11 +8,11 @@ package org.dspace.harvest.dao.impl; import java.sql.SQLException; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.content.Item_; diff --git a/dspace-api/src/main/java/org/dspace/health/Report.java b/dspace-api/src/main/java/org/dspace/health/Report.java index ebb2ffd688c0..d083a45b13d1 100644 --- a/dspace-api/src/main/java/org/dspace/health/Report.java +++ b/dspace-api/src/main/java/org/dspace/health/Report.java @@ -15,8 +15,8 @@ import java.util.List; import java.util.Map.Entry; import java.util.StringTokenizer; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOI.java b/dspace-api/src/main/java/org/dspace/identifier/DOI.java index e99472e45c78..2e699e990fc1 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/DOI.java +++ b/dspace-api/src/main/java/org/dspace/identifier/DOI.java @@ -8,17 +8,16 @@ package org.dspace.identifier; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/identifier/HandleIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/HandleIdentifierProvider.java index 82358362da85..54ab9f90a633 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/HandleIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/HandleIdentifierProvider.java @@ -27,7 +27,6 @@ import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; /** * The old DSpace handle identifier service, used to create handles or retrieve objects based on their handle @@ -36,7 +35,6 @@ * @author Mark Diggory (markd at atmire dot com) * @author Ben Bosman (ben at atmire dot com) */ -@Component public class HandleIdentifierProvider extends IdentifierProvider { /** * log4j category diff --git a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java index 4f9efd220695..1678fb423a8f 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java @@ -37,7 +37,6 @@ import org.dspace.versioning.service.VersioningService; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; /** * @author Fabio Bolognesi (fabio at atmire dot com) @@ -45,7 +44,6 @@ * @author Ben Bosman (ben at atmire dot com) * @author Pascal-Nicolas Becker (dspace at pascal dash becker dot de) */ -@Component public class VersionedHandleIdentifierProvider extends IdentifierProvider implements InitializingBean { /** * log4j category 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 9993f78b4dd5..51458b4ad6e3 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java +++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java @@ -32,14 +32,12 @@ import org.dspace.versioning.service.VersioningService; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; /** * @author Fabio Bolognesi (fabio at atmire dot com) * @author Mark Diggory (markd at atmire dot com) * @author Ben Bosman (ben at atmire dot com) */ -@Component public class VersionedHandleIdentifierProviderWithCanonicalHandles extends IdentifierProvider implements InitializingBean { /** diff --git a/dspace-api/src/main/java/org/dspace/identifier/dao/impl/DOIDAOImpl.java b/dspace-api/src/main/java/org/dspace/identifier/dao/impl/DOIDAOImpl.java index 784fec1d8894..b045061a5fb9 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/dao/impl/DOIDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/identifier/dao/impl/DOIDAOImpl.java @@ -10,11 +10,11 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; import org.dspace.content.DSpaceObject; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; 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..78507a0edf13 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 @@ -17,8 +17,8 @@ import java.util.List; import java.util.Locale; import java.util.UUID; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; 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 4c253b0502f7..1bb7e9269596 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 @@ -16,8 +16,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSFieldMapping.java index e7d2d3398b6f..0f05e9bb4cc0 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.ads; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 8fbe4ef2cf57..4c72c46732b7 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 @@ -17,11 +17,11 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; -import javax.el.MethodNotFoundException; 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; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/arxiv/metadatamapping/ArXivFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/arxiv/metadatamapping/ArXivFieldMapping.java index 272b14901514..48e7df89b387 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/arxiv/metadatamapping/ArXivFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/arxiv/metadatamapping/ArXivFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.arxiv.metadatamapping; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 96689e62ba75..a1df4a7f40c1 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 @@ -14,14 +14,14 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; -import javax.el.MethodNotFoundException; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Invocation; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; +import jakarta.el.MethodNotFoundException; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Invocation; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java index 0014088c8650..7dcc8d64c784 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java @@ -16,8 +16,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.exception.FileSourceException; import org.dspace.importer.external.service.components.AbstractPlainMetadataSource; import org.dspace.importer.external.service.components.dto.PlainMetadataKeyValueItem; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiFieldMapping.java index f266ff3d8512..aad756fbb06e 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.cinii; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 587ad5b25838..66572f9a3d16 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 @@ -19,8 +19,8 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.Callable; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpException; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefFieldMapping.java index 5e879b4d266e..81571ed7bb5e 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.crossref; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 71b088ff162b..6338cd95a3a4 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 @@ -16,11 +16,11 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.Callable; -import javax.el.MethodNotFoundException; 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; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteFieldMapping.java index f8540307b916..a67b73480dfa 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.datacite; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 a11f2bc2471d..2f723c24df4c 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 @@ -13,11 +13,11 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import javax.el.MethodNotFoundException; 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; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoFieldMapping.java index 64ec53ffb92b..955550ce0fe5 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/epo/service/EpoFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.epo.service; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/EpoIdMetadataContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/EpoIdMetadataContributor.java index e32f45a4d5f3..64d2deaca3b3 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/EpoIdMetadataContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/EpoIdMetadataContributor.java @@ -13,8 +13,8 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.dspace.importer.external.metadatamapping.MetadataFieldConfig; @@ -28,7 +28,7 @@ import org.jdom2.filter.Filters; import org.jdom2.xpath.XPathExpression; import org.jdom2.xpath.XPathFactory; -import org.springframework.beans.factory.annotation.Required; +import org.springframework.beans.factory.annotation.Autowired; /** * Custom MetadataContributor to manage Epo ID. @@ -77,6 +77,7 @@ public MetadataFieldMapping> getMetadataFi * * @param metadataFieldMapping the new mapping. */ + @Override public void setMetadataFieldMapping( MetadataFieldMapping> metadataFieldMapping) { this.metadataFieldMapping = metadataFieldMapping; @@ -95,7 +96,8 @@ public void setPrefixToNamespaceMapping(Map prefixToNamespaceMap protected Map prefixToNamespaceMapping; /** - * Initialize EpoIdMetadataContributor with a query, prefixToNamespaceMapping and MetadataFieldConfig + * Initialize EpoIdMetadataContributor with all required fields: a query, prefixToNamespaceMapping + * and MetadataFieldConfig * * @param query query string * @param prefixToNamespaceMapping metadata prefix to namespace mapping @@ -113,7 +115,6 @@ public EpoIdMetadataContributor(String query, Map prefixToNamesp * Empty constructor for EpoIdMetadataContributor */ public EpoIdMetadataContributor() { - } protected String query; @@ -132,7 +133,7 @@ public MetadataFieldConfig getField() { * * @param field MetadataFieldConfig used while retrieving MetadatumDTO */ - @Required + @Autowired(required = true) public void setField(MetadataFieldConfig field) { this.field = field; } @@ -146,7 +147,11 @@ public String getQuery() { return query; } - @Required + /** + * Setting the query + * @param query query used + */ + @Autowired(required = true) public void setQuery(String query) { this.query = query; } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleXpathMetadatumContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleXpathMetadatumContributor.java index 05f8647d7867..3fa32376990c 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleXpathMetadatumContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleXpathMetadatumContributor.java @@ -12,8 +12,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.apache.logging.log4j.Logger; import org.dspace.importer.external.metadatamapping.MetadataFieldConfig; import org.dspace.importer.external.metadatamapping.MetadataFieldMapping; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/WosAttribute2ValueContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/WosAttribute2ValueContributor.java index 66e16f7ae866..9c10218a99bd 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/WosAttribute2ValueContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/WosAttribute2ValueContributor.java @@ -12,8 +12,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/openaire/metadatamapping/OpenAIREPublicationFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/openaire/metadatamapping/OpenAIREPublicationFieldMapping.java index d58ffc8ca9d5..cf326fb63d71 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/openaire/metadatamapping/OpenAIREPublicationFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/openaire/metadatamapping/OpenAIREPublicationFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.openaire.metadatamapping; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 0e59c9eb0e42..7a0a92564f72 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 @@ -14,13 +14,13 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; -import javax.el.MethodNotFoundException; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Invocation; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Response; +import jakarta.el.MethodNotFoundException; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Invocation; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Response; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.datamodel.Query; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedFieldMapping.java index 2d315377669a..0d4dcf0c1e72 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmed/metadatamapping/PubmedFieldMapping.java @@ -9,8 +9,8 @@ package org.dspace.importer.external.pubmed.metadatamapping; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** diff --git a/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeFieldMapping.java index 8c8e23fe989a..35d10af58443 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/pubmedeurope/PubmedEuropeFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.pubmedeurope; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 92d7d9fbd3fe..5aae8ca8cf50 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 @@ -17,8 +17,8 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.Callable; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpException; import org.apache.http.client.ClientProtocolException; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/ris/service/RisImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/ris/service/RisImportMetadataSourceServiceImpl.java index 1f460c19e697..e4e027016e13 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/ris/service/RisImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/ris/service/RisImportMetadataSourceServiceImpl.java @@ -17,8 +17,8 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.exception.FileSourceException; import org.dspace.importer.external.service.components.AbstractPlainMetadataSource; import org.dspace.importer.external.service.components.dto.PlainMetadataKeyValueItem; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/ror/service/RorFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/ror/service/RorFieldMapping.java index d7caeffdbaf2..3096a92f95dd 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/ror/service/RorFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/ror/service/RorFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.ror.service; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; 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 59063271f365..aa11ac0bb710 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 @@ -15,11 +15,11 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; -import javax.el.MethodNotFoundException; 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; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloFieldMapping.java index 0d7183a1f058..f8c4f93a1757 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloFieldMapping.java @@ -7,8 +7,8 @@ */ package org.dspace.importer.external.scielo.service; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 4f83ffe978f7..ce0c20435ecf 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 @@ -20,9 +20,9 @@ import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.el.MethodNotFoundException; -import javax.ws.rs.BadRequestException; +import jakarta.el.MethodNotFoundException; +import jakarta.ws.rs.BadRequestException; import org.apache.commons.collections4.CollectionUtils; import org.apache.http.client.utils.URIBuilder; import org.dspace.content.Item; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusFieldMapping.java index c8143339b483..93e9753c42d5 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/scopus/service/ScopusFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.scopus.service; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; 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 944d467e3156..7c9e53f9ec0c 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 @@ -21,8 +21,8 @@ import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.lang3.StringUtils; import org.dspace.content.Item; import org.dspace.importer.external.datamodel.ImportRecord; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractRemoteMetadataSource.java b/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractRemoteMetadataSource.java index 29801433e3b3..83b5d4eaab25 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractRemoteMetadataSource.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractRemoteMetadataSource.java @@ -14,8 +14,8 @@ import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.locks.ReentrantLock; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.apache.logging.log4j.Logger; import org.dspace.importer.external.exception.MetadataSourceException; import org.dspace.importer.external.exception.SourceExceptionHandler; 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 a4f90fa5ba61..8933569a060f 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 @@ -15,11 +15,11 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.Callable; -import javax.el.MethodNotFoundException; 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; diff --git a/dspace-api/src/main/java/org/dspace/importer/external/vufind/metadatamapping/VuFindFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/vufind/metadatamapping/VuFindFieldMapping.java index b14927a14ccc..d96265372f31 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/vufind/metadatamapping/VuFindFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/vufind/metadatamapping/VuFindFieldMapping.java @@ -8,8 +8,8 @@ package org.dspace.importer.external.vufind.metadatamapping; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** diff --git a/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSFieldMapping.java index be4acfbcea8c..6cf58fdd7bc9 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSFieldMapping.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/wos/service/WOSFieldMapping.java @@ -7,8 +7,8 @@ */ package org.dspace.importer.external.wos.service; import java.util.Map; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping; /** 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 f550b659952b..c7b5aaa49e27 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 @@ -21,8 +21,8 @@ import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; diff --git a/dspace-api/src/main/java/org/dspace/orcid/OrcidHistory.java b/dspace-api/src/main/java/org/dspace/orcid/OrcidHistory.java index 07a79384c77c..4665fe4428be 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/OrcidHistory.java +++ b/dspace-api/src/main/java/org/dspace/orcid/OrcidHistory.java @@ -8,24 +8,23 @@ package org.dspace.orcid; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.Lob; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.content.Item; import org.dspace.core.ReloadableEntity; -import org.hibernate.annotations.Type; +import org.hibernate.Length; /** * The ORCID history entity that it contains information relating to an attempt @@ -79,18 +78,14 @@ public class OrcidHistory implements ReloadableEntity { /** * A description of the synchronized resource. */ - @Lob - @Type(type = "org.hibernate.type.TextType") - @Column(name = "description") + @Column(name = "description", length = Length.LONG32) private String description; /** * The signature of the synchronized metadata. This is used when the entity is * the owner itself. */ - @Lob - @Type(type = "org.hibernate.type.TextType") - @Column(name = "metadata") + @Column(name = "metadata", length = Length.LONG32) private String metadata; /** @@ -103,9 +98,7 @@ public class OrcidHistory implements ReloadableEntity { /** * The response message incoming from ORCID. */ - @Lob - @Type(type = "org.hibernate.type.TextType") - @Column(name = "response_message") + @Column(name = "response_message", length = Length.LONG32) private String responseMessage; /** diff --git a/dspace-api/src/main/java/org/dspace/orcid/OrcidQueue.java b/dspace-api/src/main/java/org/dspace/orcid/OrcidQueue.java index 65b66cd20c3e..dfcb531401d7 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/OrcidQueue.java +++ b/dspace-api/src/main/java/org/dspace/orcid/OrcidQueue.java @@ -11,22 +11,21 @@ import static org.apache.commons.lang3.StringUtils.isNotEmpty; import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.Lob; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.content.Item; import org.dspace.core.ReloadableEntity; -import org.hibernate.annotations.Type; +import org.hibernate.Length; /** * Entity that model a record on the ORCID synchronization queue. Each record in @@ -64,9 +63,7 @@ public class OrcidQueue implements ReloadableEntity { /** * A description of the resource to be synchronized. */ - @Lob - @Type(type = "org.hibernate.type.TextType") - @Column(name = "description") + @Column(name = "description", length = Length.LONG32) private String description; /** @@ -87,9 +84,7 @@ public class OrcidQueue implements ReloadableEntity { * The signature of the metadata to be synchronized. This is used when the * entity is the owner itself. */ - @Lob - @Column(name = "metadata") - @Type(type = "org.hibernate.type.TextType") + @Column(name = "metadata", length = Length.LONG32) private String metadata; /** diff --git a/dspace-api/src/main/java/org/dspace/orcid/OrcidToken.java b/dspace-api/src/main/java/org/dspace/orcid/OrcidToken.java index def289daf41e..3e54a68a23ec 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/OrcidToken.java +++ b/dspace-api/src/main/java/org/dspace/orcid/OrcidToken.java @@ -7,17 +7,16 @@ */ package org.dspace.orcid; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.content.Item; import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; 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..8356167692e3 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 @@ -21,14 +21,14 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; import org.apache.commons.io.IOUtils; import org.apache.http.Header; import org.apache.http.HttpEntity; diff --git a/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidHistoryDAOImpl.java b/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidHistoryDAOImpl.java index 0b2c7099ffac..fe300751d1dd 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidHistoryDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidHistoryDAOImpl.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.persistence.Query; +import jakarta.persistence.Query; import org.dspace.content.Item; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; 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..c8e48e3f17d6 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 @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.persistence.Query; +import jakarta.persistence.Query; import org.dspace.content.Item; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidTokenDAOImpl.java b/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidTokenDAOImpl.java index 01b03fc35455..f94f5ad3a44f 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidTokenDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/dao/impl/OrcidTokenDAOImpl.java @@ -8,8 +8,8 @@ package org.dspace.orcid.dao.impl; import java.sql.SQLException; -import javax.persistence.Query; +import jakarta.persistence.Query; import org.dspace.content.Item; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/orcid/model/factory/impl/OrcidCommonObjectFactoryImpl.java b/dspace-api/src/main/java/org/dspace/orcid/model/factory/impl/OrcidCommonObjectFactoryImpl.java index 2f47aa53d69d..1195d27c4fda 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/model/factory/impl/OrcidCommonObjectFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/model/factory/impl/OrcidCommonObjectFactoryImpl.java @@ -172,7 +172,7 @@ public Optional createCountry(Context context, MetadataValue metadataVa private ContributorAttributes getContributorAttributes(MetadataValue metadataValue, ContributorRole role) { ContributorAttributes attributes = new ContributorAttributes(); - attributes.setContributorRole(role != null ? role : null); + attributes.setContributorRole(role != null ? role.value() : null); attributes.setContributorSequence(metadataValue.getPlace() == 0 ? FIRST : ADDITIONAL); return attributes; } @@ -191,7 +191,7 @@ private OrganizationAddress createOrganizationAddress(Item organizationItem) { private FundingContributorAttributes getFundingContributorAttributes(MetadataValue metadataValue, FundingContributorRole role) { FundingContributorAttributes attributes = new FundingContributorAttributes(); - attributes.setContributorRole(role != null ? role : null); + attributes.setContributorRole(role != null ? role.value() : null); return attributes; } diff --git a/dspace-api/src/main/java/org/dspace/profile/ResearcherProfileServiceImpl.java b/dspace-api/src/main/java/org/dspace/profile/ResearcherProfileServiceImpl.java index 639601df976d..5de1ffa4ac93 100644 --- a/dspace-api/src/main/java/org/dspace/profile/ResearcherProfileServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/profile/ResearcherProfileServiceImpl.java @@ -23,8 +23,8 @@ import java.util.List; import java.util.Optional; import java.util.UUID; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; diff --git a/dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDAOImpl.java b/dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDAOImpl.java index ac9b96045e42..2dbc47692010 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDAOImpl.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.Date; import java.util.List; -import javax.persistence.Query; +import jakarta.persistence.Query; import org.dspace.content.Item; import org.dspace.content.QAEventProcessed; import org.dspace.core.AbstractHibernateDAO; diff --git a/dspace-api/src/main/java/org/dspace/rdf/RDFConsumer.java b/dspace-api/src/main/java/org/dspace/rdf/RDFConsumer.java index 34ab572d1b16..62208be6d9cc 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/RDFConsumer.java +++ b/dspace-api/src/main/java/org/dspace/rdf/RDFConsumer.java @@ -16,7 +16,7 @@ import java.util.NoSuchElementException; import java.util.UUID; -import com.hp.hpl.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Model; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; diff --git a/dspace-api/src/main/java/org/dspace/rdf/RDFUtil.java b/dspace-api/src/main/java/org/dspace/rdf/RDFUtil.java index 1e9744aec5c5..ef381febe701 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/RDFUtil.java +++ b/dspace-api/src/main/java/org/dspace/rdf/RDFUtil.java @@ -12,8 +12,8 @@ import java.util.List; import java.util.UUID; -import com.hp.hpl.jena.rdf.model.Model; import org.apache.commons.lang3.StringUtils; +import org.apache.jena.rdf.model.Model; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.factory.AuthorizeServiceFactory; diff --git a/dspace-api/src/main/java/org/dspace/rdf/RDFizer.java b/dspace-api/src/main/java/org/dspace/rdf/RDFizer.java index ac4e341c5e75..980aaa4b11fa 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/RDFizer.java +++ b/dspace-api/src/main/java/org/dspace/rdf/RDFizer.java @@ -16,7 +16,6 @@ import java.util.UUID; import java.util.concurrent.CopyOnWriteArraySet; -import com.hp.hpl.jena.rdf.model.Model; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; @@ -25,6 +24,7 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.lang3.StringUtils; +import org.apache.jena.rdf.model.Model; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/ConverterPlugin.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/ConverterPlugin.java index f0ad88c5827d..fa00374f9dd0 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/ConverterPlugin.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/ConverterPlugin.java @@ -10,7 +10,7 @@ import java.sql.SQLException; -import com.hp.hpl.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Model; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/DMRM.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/DMRM.java index 0d0f955e0ad3..f253e4025b6a 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/DMRM.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/DMRM.java @@ -8,10 +8,10 @@ package org.dspace.rdf.conversion; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.Property; -import com.hp.hpl.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.Resource; /** * Schema for DSpace Metadata RDF Mappings. diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/MetadataConverterPlugin.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/MetadataConverterPlugin.java index 72ba03d99d27..c9e55cba1924 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/MetadataConverterPlugin.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/MetadataConverterPlugin.java @@ -15,17 +15,17 @@ import java.util.Iterator; import java.util.List; -import com.hp.hpl.jena.rdf.model.InfModel; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.ResIterator; -import com.hp.hpl.jena.reasoner.Reasoner; -import com.hp.hpl.jena.reasoner.ReasonerRegistry; -import com.hp.hpl.jena.reasoner.ValidityReport; -import com.hp.hpl.jena.util.FileManager; -import com.hp.hpl.jena.util.FileUtils; -import com.hp.hpl.jena.vocabulary.RDF; import org.apache.commons.lang3.StringUtils; +import org.apache.jena.rdf.model.InfModel; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.ResIterator; +import org.apache.jena.reasoner.Reasoner; +import org.apache.jena.reasoner.ReasonerRegistry; +import org.apache.jena.reasoner.ValidityReport; +import org.apache.jena.util.FileManager; +import org.apache.jena.util.FileUtils; +import org.apache.jena.vocabulary.RDF; import org.apache.logging.log4j.Logger; import org.dspace.app.util.factory.UtilServiceFactory; import org.dspace.authorize.AuthorizeException; diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/MetadataRDFMapping.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/MetadataRDFMapping.java index 6286f3b87a66..5b801d699af8 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/MetadataRDFMapping.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/MetadataRDFMapping.java @@ -14,15 +14,15 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -import com.hp.hpl.jena.rdf.model.Literal; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.Property; -import com.hp.hpl.jena.rdf.model.RDFNode; -import com.hp.hpl.jena.rdf.model.Resource; -import com.hp.hpl.jena.rdf.model.Statement; -import com.hp.hpl.jena.rdf.model.StmtIterator; -import com.hp.hpl.jena.vocabulary.RDF; import org.apache.commons.lang3.StringUtils; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.vocabulary.RDF; import org.apache.logging.log4j.Logger; /** diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/RDFConverter.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/RDFConverter.java index d8e71856a1b3..7617355db667 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/RDFConverter.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/RDFConverter.java @@ -10,7 +10,7 @@ import java.sql.SQLException; -import com.hp.hpl.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Model; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/RDFConverterImpl.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/RDFConverterImpl.java index 93a9b6211d57..0842bf5e40c8 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/RDFConverterImpl.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/RDFConverterImpl.java @@ -11,8 +11,8 @@ import java.sql.SQLException; import java.util.List; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/SimpleDSORelationsConverterPlugin.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/SimpleDSORelationsConverterPlugin.java index 63382a7c26b0..4665625702dd 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/SimpleDSORelationsConverterPlugin.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/SimpleDSORelationsConverterPlugin.java @@ -14,11 +14,11 @@ import java.util.Iterator; import java.util.List; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.util.FileManager; -import com.hp.hpl.jena.util.FileUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.util.FileManager; +import org.apache.jena.util.FileUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.util.Util; import org.dspace.content.Bitstream; diff --git a/dspace-api/src/main/java/org/dspace/rdf/conversion/StaticDSOConverterPlugin.java b/dspace-api/src/main/java/org/dspace/rdf/conversion/StaticDSOConverterPlugin.java index f86af753e690..f18074a1bdfe 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/conversion/StaticDSOConverterPlugin.java +++ b/dspace-api/src/main/java/org/dspace/rdf/conversion/StaticDSOConverterPlugin.java @@ -12,10 +12,10 @@ import java.io.InputStream; import java.sql.SQLException; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.util.FileManager; -import com.hp.hpl.jena.util.FileUtils; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.util.FileManager; +import org.apache.jena.util.FileUtils; import org.apache.logging.log4j.Logger; import org.dspace.content.DSpaceObject; import org.dspace.content.factory.ContentServiceFactory; diff --git a/dspace-api/src/main/java/org/dspace/rdf/negotiation/NegotiationFilter.java b/dspace-api/src/main/java/org/dspace/rdf/negotiation/NegotiationFilter.java index 998f57ca4feb..d210803ba793 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/negotiation/NegotiationFilter.java +++ b/dspace-api/src/main/java/org/dspace/rdf/negotiation/NegotiationFilter.java @@ -10,15 +10,15 @@ import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.Logger; import org.dspace.rdf.RDFUtil; import org.dspace.services.factory.DSpaceServicesFactory; diff --git a/dspace-api/src/main/java/org/dspace/rdf/negotiation/Negotiator.java b/dspace-api/src/main/java/org/dspace/rdf/negotiation/Negotiator.java index d011d305b166..8d1105a5252b 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/negotiation/Negotiator.java +++ b/dspace-api/src/main/java/org/dspace/rdf/negotiation/Negotiator.java @@ -12,8 +12,8 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.commons.validator.routines.UrlValidator; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorage.java b/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorage.java index 31294323c745..52bee26d76f3 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorage.java +++ b/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorage.java @@ -10,7 +10,7 @@ import java.util.List; -import com.hp.hpl.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Model; /** * @author Pascal-Nicolas Becker (dspace -at- pascal -hyphen- becker -dot- de) diff --git a/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorageImpl.java b/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorageImpl.java index fd84db5d5f2d..2ea5c3c88082 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorageImpl.java +++ b/dspace-api/src/main/java/org/dspace/rdf/storage/RDFStorageImpl.java @@ -12,24 +12,15 @@ import java.util.Collections; import java.util.List; -import com.hp.hpl.jena.graph.Graph; -import com.hp.hpl.jena.graph.Node; -import com.hp.hpl.jena.graph.NodeFactory; -import com.hp.hpl.jena.query.Dataset; -import com.hp.hpl.jena.query.DatasetFactory; -import com.hp.hpl.jena.query.QueryExecution; -import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QuerySolution; -import com.hp.hpl.jena.query.ResultSet; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.sparql.core.DatasetGraph; -import com.hp.hpl.jena.update.GraphStore; -import com.hp.hpl.jena.update.GraphStoreFactory; import org.apache.commons.lang3.StringUtils; -import org.apache.jena.atlas.web.auth.HttpAuthenticator; -import org.apache.jena.atlas.web.auth.SimpleAuthenticator; -import org.apache.jena.web.DatasetGraphAccessor; -import org.apache.jena.web.DatasetGraphAccessorHTTP; +import org.apache.jena.http.auth.AuthEnv; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdfconnection.RDFConnection; +import org.apache.jena.rdfconnection.RDFConnectionRemote; +import org.apache.jena.sparql.exec.http.QueryExecutionHTTP; import org.apache.logging.log4j.Logger; import org.dspace.rdf.RDFUtil; import org.dspace.services.ConfigurationService; @@ -47,48 +38,35 @@ public class RDFStorageImpl @Override public void store(String uri, Model model) { - Node graphNode = NodeFactory.createURI(uri); - DatasetGraphAccessor accessor = this.getAccessor(); - Dataset ds = DatasetFactory.create(model); - DatasetGraph dsg = ds.asDatasetGraph(); - Graph g = dsg.getDefaultGraph(); - accessor.httpPut(graphNode, g); + RDFConnection connection = this.getConnection(); + connection.put(uri, model); } @Override public Model load(String uri) { - Node graphNode = NodeFactory.createURI(uri); - DatasetGraphAccessor accessor = this.getAccessor(); - Graph g = accessor.httpGet(graphNode); - if (g == null || g.isEmpty()) { - return null; - } - GraphStore gs = GraphStoreFactory.create(g); - Dataset ds = gs.toDataset(); - Model m = ds.getDefaultModel(); - return m; + RDFConnection connection = this.getConnection(); + return connection.fetch(uri); } - protected DatasetGraphAccessor getAccessor() { - DatasetGraphAccessor accessor; + protected RDFConnection getConnection() { + RDFConnection connection; if (configurationService.hasProperty(RDFUtil.STORAGE_GRAPHSTORE_LOGIN_KEY) && configurationService.hasProperty(RDFUtil.STORAGE_GRAPHSTORE_PASSWORD_KEY)) { - HttpAuthenticator httpAuthenticator = new SimpleAuthenticator( - configurationService.getProperty(RDFUtil.STORAGE_GRAPHSTORE_LOGIN_KEY), - configurationService.getProperty(RDFUtil.STORAGE_GRAPHSTORE_PASSWORD_KEY).toCharArray()); - accessor = new DatasetGraphAccessorHTTP(getGraphStoreEndpoint(), - httpAuthenticator); + AuthEnv.get() + .registerUsernamePassword(getGraphStoreEndpoint(), + configurationService.getProperty(RDFUtil.STORAGE_GRAPHSTORE_LOGIN_KEY), + configurationService.getProperty(RDFUtil.STORAGE_GRAPHSTORE_PASSWORD_KEY)); } else { log.debug("Did not found credential to use for our connection to the " + "Graph Store HTTP endpoint, trying to connect unauthenticated."); - accessor = new DatasetGraphAccessorHTTP(getGraphStoreEndpoint()); } - return accessor; + connection = RDFConnectionRemote.service(getGraphStoreEndpoint()).build(); + return connection; } @Override public void delete(String uri) { - this.getAccessor().httpDelete(NodeFactory.createURI(uri)); + this.getConnection().delete(uri); } @Override @@ -97,34 +75,30 @@ public void deleteAll() { this.delete(graph); } // clean default graph: - this.getAccessor().httpDelete(); + this.getConnection().delete(); } @Override public List getAllStoredGraphs() { String queryString = "SELECT DISTINCT ?g WHERE { GRAPH ?g { ?s ?p ?o } }"; - QueryExecution qexec; if (configurationService.hasProperty(RDFUtil.STORAGE_SPARQL_LOGIN_KEY) && configurationService.hasProperty(RDFUtil.STORAGE_SPARQL_PASSWORD_KEY)) { - HttpAuthenticator httpAuthenticator = new SimpleAuthenticator( - configurationService.getProperty(RDFUtil.STORAGE_SPARQL_LOGIN_KEY), - configurationService.getProperty(RDFUtil.STORAGE_GRAPHSTORE_PASSWORD_KEY).toCharArray()); - qexec = QueryExecutionFactory.sparqlService(getSparqlEndpoint(), - queryString, httpAuthenticator); - } else { - qexec = QueryExecutionFactory.sparqlService(getSparqlEndpoint(), - queryString); + AuthEnv.get() + .registerUsernamePassword(getSparqlEndpoint(), + configurationService.getProperty(RDFUtil.STORAGE_SPARQL_LOGIN_KEY), + configurationService.getProperty(RDFUtil.STORAGE_GRAPHSTORE_PASSWORD_KEY)); } - ResultSet rs = qexec.execSelect(); - List graphs = Collections.synchronizedList(new ArrayList()); - while (rs.hasNext()) { - QuerySolution solution = rs.next(); - if (solution.contains("g")) { - graphs.add(solution.get("g").asResource().getURI()); + List graphs = Collections.synchronizedList(new ArrayList<>()); + try (QueryExecution qexec = QueryExecutionHTTP.service(getSparqlEndpoint()).queryString(queryString).build()) { + ResultSet rs = qexec.execSelect(); + while (rs.hasNext()) { + QuerySolution solution = rs.next(); + if (solution.contains("g")) { + graphs.add(solution.get("g").asResource().getURI()); + } } } - qexec.close(); return graphs; } diff --git a/dspace-api/src/main/java/org/dspace/scripts/Process.java b/dspace-api/src/main/java/org/dspace/scripts/Process.java index eab3ba460c09..ead5296e998b 100644 --- a/dspace-api/src/main/java/org/dspace/scripts/Process.java +++ b/dspace-api/src/main/java/org/dspace/scripts/Process.java @@ -10,25 +10,24 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.Lob; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.dspace.content.Bitstream; @@ -36,7 +35,7 @@ import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; -import org.hibernate.annotations.Type; +import org.hibernate.Length; /** * This class is the DB Entity representation of the Process object to be stored in the Database @@ -70,9 +69,7 @@ public class Process implements ReloadableEntity { @Enumerated(EnumType.STRING) private ProcessStatus processStatus; - @Lob - @Type(type = "org.hibernate.type.TextType") - @Column(name = "parameters") + @Column(name = "parameters", length = Length.LONG32) private String parameters; @ManyToMany(fetch = FetchType.LAZY) diff --git a/dspace-api/src/main/java/org/dspace/service/ClientInfoService.java b/dspace-api/src/main/java/org/dspace/service/ClientInfoService.java index ef92afab940b..9b28dce142d2 100644 --- a/dspace-api/src/main/java/org/dspace/service/ClientInfoService.java +++ b/dspace-api/src/main/java/org/dspace/service/ClientInfoService.java @@ -7,7 +7,7 @@ */ package org.dspace.service; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; /** * Service that can be used to retrieve information about DSpace clients diff --git a/dspace-api/src/main/java/org/dspace/service/impl/ClientInfoServiceImpl.java b/dspace-api/src/main/java/org/dspace/service/impl/ClientInfoServiceImpl.java index 3157e95f6bed..edff457ac5c4 100644 --- a/dspace-api/src/main/java/org/dspace/service/impl/ClientInfoServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/service/impl/ClientInfoServiceImpl.java @@ -10,9 +10,9 @@ import static org.apache.commons.lang3.StringUtils.ordinalIndexOf; import java.net.Inet4Address; -import javax.servlet.http.HttpServletRequest; import com.google.common.net.InetAddresses; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; 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 c5f7c46b586e..31a8ed12c138 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 @@ -8,11 +8,11 @@ package org.dspace.service.impl; import java.util.concurrent.TimeUnit; -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Singleton; import org.apache.http.HeaderElement; import org.apache.http.HeaderElementIterator; import org.apache.http.HttpResponse; 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 5f976bbfd94b..d384aff75591 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerServiceImpl.java @@ -37,13 +37,13 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import javax.servlet.http.HttpServletRequest; import com.maxmind.geoip2.DatabaseReader; import com.maxmind.geoip2.exception.GeoIp2Exception; import com.maxmind.geoip2.model.CityResponse; import com.opencsv.CSVReader; import com.opencsv.CSVWriter; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; diff --git a/dspace-api/src/main/java/org/dspace/statistics/SolrStatisticsCore.java b/dspace-api/src/main/java/org/dspace/statistics/SolrStatisticsCore.java index 9ad72cbf313b..66bc51ab48ec 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/SolrStatisticsCore.java +++ b/dspace-api/src/main/java/org/dspace/statistics/SolrStatisticsCore.java @@ -9,8 +9,7 @@ import static org.apache.logging.log4j.LogManager.getLogger; -import javax.inject.Named; - +import jakarta.inject.Named; import org.apache.logging.log4j.Logger; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.impl.HttpSolrClient; diff --git a/dspace-api/src/main/java/org/dspace/statistics/export/OpenURLTracker.java b/dspace-api/src/main/java/org/dspace/statistics/export/OpenURLTracker.java index b853f255e841..47809ad2309b 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/export/OpenURLTracker.java +++ b/dspace-api/src/main/java/org/dspace/statistics/export/OpenURLTracker.java @@ -8,18 +8,19 @@ package org.dspace.statistics.export; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; +import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; -import org.hibernate.proxy.HibernateProxyHelper; + /** * Class that represents an OpenURLTracker which tracks a failed transmission to IRUS diff --git a/dspace-api/src/main/java/org/dspace/statistics/export/processor/BitstreamEventProcessor.java b/dspace-api/src/main/java/org/dspace/statistics/export/processor/BitstreamEventProcessor.java index 85cb7bc14c14..41cf655dbcd5 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/export/processor/BitstreamEventProcessor.java +++ b/dspace-api/src/main/java/org/dspace/statistics/export/processor/BitstreamEventProcessor.java @@ -11,8 +11,8 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Item; diff --git a/dspace-api/src/main/java/org/dspace/statistics/export/processor/ExportEventProcessor.java b/dspace-api/src/main/java/org/dspace/statistics/export/processor/ExportEventProcessor.java index 609298779d34..434de459bad9 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/export/processor/ExportEventProcessor.java +++ b/dspace-api/src/main/java/org/dspace/statistics/export/processor/ExportEventProcessor.java @@ -15,8 +15,8 @@ import java.util.Arrays; import java.util.Date; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.codec.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.dspace.content.DCDate; diff --git a/dspace-api/src/main/java/org/dspace/statistics/export/processor/ItemEventProcessor.java b/dspace-api/src/main/java/org/dspace/statistics/export/processor/ItemEventProcessor.java index 92adb67546ef..76ea30245dd7 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/export/processor/ItemEventProcessor.java +++ b/dspace-api/src/main/java/org/dspace/statistics/export/processor/ItemEventProcessor.java @@ -11,14 +11,13 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; - /** * Processor that handles Item events from the IrusExportUsageEventListener */ diff --git a/dspace-api/src/main/java/org/dspace/statistics/service/SolrLoggerService.java b/dspace-api/src/main/java/org/dspace/statistics/service/SolrLoggerService.java index 61b2bb6013de..462703e17045 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/service/SolrLoggerService.java +++ b/dspace-api/src/main/java/org/dspace/statistics/service/SolrLoggerService.java @@ -12,8 +12,8 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrInputDocument; diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java index 20d042d9d993..c216e1b92acc 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java @@ -10,8 +10,8 @@ import java.io.File; import java.io.IOException; import java.util.Set; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.statistics.factory.StatisticsServiceFactory; /** diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetectorService.java b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetectorService.java index 710e8472d2a8..bb6196eb3561 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetectorService.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetectorService.java @@ -10,7 +10,8 @@ import java.io.File; import java.io.IOException; import java.util.Set; -import javax.servlet.http.HttpServletRequest; + +import jakarta.servlet.http.HttpServletRequest; /** * Interface to implement a SpiderDetectorService diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetectorServiceImpl.java b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetectorServiceImpl.java index 2f4a3a61e94a..232e2fd10e84 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetectorServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetectorServiceImpl.java @@ -17,8 +17,8 @@ import java.util.List; import java.util.Set; import java.util.regex.Pattern; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.configuration2.ex.ConversionException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/BitstreamStorageServiceImpl.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/BitstreamStorageServiceImpl.java index 956ac5a7f8f1..c89e5d7a54d1 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/BitstreamStorageServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/BitstreamStorageServiceImpl.java @@ -15,8 +15,8 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.logging.log4j.LogManager; diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java index 48f3b9f325f8..afb2eaa97b3b 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java @@ -21,7 +21,6 @@ import java.util.Map; import java.util.UUID; import java.util.function.Supplier; -import javax.validation.constraints.NotNull; import com.amazonaws.AmazonClientException; import com.amazonaws.auth.AWSCredentials; @@ -38,6 +37,7 @@ import com.amazonaws.services.s3.transfer.TransferManager; import com.amazonaws.services.s3.transfer.TransferManagerBuilder; import com.amazonaws.services.s3.transfer.Upload; +import jakarta.validation.constraints.NotNull; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/service/BitstreamStorageService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/service/BitstreamStorageService.java index 7f5ed8f9129f..8de082aeb733 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/service/BitstreamStorageService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/service/BitstreamStorageService.java @@ -12,8 +12,8 @@ import java.sql.SQLException; import java.util.Map; import java.util.UUID; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java index 0732eea2a0b9..7a2d3a8b740a 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java @@ -635,7 +635,7 @@ private synchronized static FluentConfiguration setupFlyway(DataSource datasourc // For DSpace, we sometimes have to insert "old" migrations in after a major release // if further development/bug fixes are needed in older versions. So, "Ignored" migrations are // nothing to worry about...you can always trigger them to run using "database migrate ignored" from CLI - flywayConfiguration.ignoreIgnoredMigrations(true); + flywayConfiguration.ignoreMigrationPatterns("*:ignored"); // Set Flyway callbacks (i.e. classes which are called post-DB migration and similar) List flywayCallbacks = DSpaceServicesFactory.getInstance().getServiceManager() diff --git a/dspace-api/src/main/java/org/dspace/submit/model/UploadConfiguration.java b/dspace-api/src/main/java/org/dspace/submit/model/UploadConfiguration.java index a6421b3f7adb..757a01cb1cc4 100644 --- a/dspace-api/src/main/java/org/dspace/submit/model/UploadConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/submit/model/UploadConfiguration.java @@ -8,8 +8,8 @@ package org.dspace.submit.model; import java.util.List; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.dspace.services.ConfigurationService; /** diff --git a/dspace-api/src/main/java/org/dspace/supervision/SupervisionOrder.java b/dspace-api/src/main/java/org/dspace/supervision/SupervisionOrder.java index 52d5dacb74bb..6b447361efb0 100644 --- a/dspace-api/src/main/java/org/dspace/supervision/SupervisionOrder.java +++ b/dspace-api/src/main/java/org/dspace/supervision/SupervisionOrder.java @@ -7,17 +7,16 @@ */ package org.dspace.supervision; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; diff --git a/dspace-api/src/main/java/org/dspace/supervision/dao/impl/SupervisionOrderDaoImpl.java b/dspace-api/src/main/java/org/dspace/supervision/dao/impl/SupervisionOrderDaoImpl.java index 09cd0841e78f..ac056d553054 100644 --- a/dspace-api/src/main/java/org/dspace/supervision/dao/impl/SupervisionOrderDaoImpl.java +++ b/dspace-api/src/main/java/org/dspace/supervision/dao/impl/SupervisionOrderDaoImpl.java @@ -9,10 +9,10 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.Item; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java b/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java index ec9a2b12641a..90dd9e47e2e2 100644 --- a/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java +++ b/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java @@ -7,8 +7,7 @@ */ package org.dspace.usage; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.DSpaceObject; import org.dspace.core.Constants; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/usage/UsageSearchEvent.java b/dspace-api/src/main/java/org/dspace/usage/UsageSearchEvent.java index 938f9e798452..f285a4f90aec 100644 --- a/dspace-api/src/main/java/org/dspace/usage/UsageSearchEvent.java +++ b/dspace-api/src/main/java/org/dspace/usage/UsageSearchEvent.java @@ -8,8 +8,8 @@ package org.dspace.usage; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/util/DSpacePostgreSQLDialect.java b/dspace-api/src/main/java/org/dspace/util/DSpacePostgreSQLDialect.java index 0da4f14b7719..8b982d454440 100644 --- a/dspace-api/src/main/java/org/dspace/util/DSpacePostgreSQLDialect.java +++ b/dspace-api/src/main/java/org/dspace/util/DSpacePostgreSQLDialect.java @@ -7,8 +7,9 @@ */ package org.dspace.util; -import org.hibernate.dialect.PostgreSQL94Dialect; -import org.hibernate.dialect.function.SQLFunctionTemplate; +import org.hibernate.boot.model.FunctionContributions; +import org.hibernate.dialect.PostgreSQLDialect; +import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.StandardBasicTypes; /** @@ -16,18 +17,34 @@ * @see org.dspace.contentreport.QueryOperator * @author Jean-François Morin (Université Laval) */ -public class DSpacePostgreSQLDialect extends PostgreSQL94Dialect { +public class DSpacePostgreSQLDialect extends PostgreSQLDialect { public static final String REGEX_MATCHES = "matches"; public static final String REGEX_IMATCHES = "imatches"; public static final String REGEX_NOT_MATCHES = "not_matches"; public static final String REGEX_NOT_IMATCHES = "not_imatches"; - public DSpacePostgreSQLDialect() { - registerFunction(REGEX_MATCHES, new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "?1 ~ ?2")); - registerFunction(REGEX_IMATCHES, new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "?1 ~* ?2")); - registerFunction(REGEX_NOT_MATCHES, new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "?1 !~ ?2")); - registerFunction(REGEX_NOT_IMATCHES, new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "?1 !~* ?2")); - } + @Override + public void initializeFunctionRegistry(FunctionContributions functionContributions) { + super.initializeFunctionRegistry(functionContributions); + + BasicTypeRegistry basicTypeRegistry = functionContributions.getTypeConfiguration().getBasicTypeRegistry(); + functionContributions.getFunctionRegistry().registerPattern( + REGEX_MATCHES, + "?1 ~ ?2", + basicTypeRegistry.resolve( StandardBasicTypes.BOOLEAN )); + functionContributions.getFunctionRegistry().registerPattern( + REGEX_IMATCHES, + "?1 ~* ?2", + basicTypeRegistry.resolve( StandardBasicTypes.BOOLEAN )); + functionContributions.getFunctionRegistry().registerPattern( + REGEX_NOT_MATCHES, + "?1 !~ ?2", + basicTypeRegistry.resolve( StandardBasicTypes.BOOLEAN )); + functionContributions.getFunctionRegistry().registerPattern( + REGEX_NOT_IMATCHES, + "?1 !~* ?2", + basicTypeRegistry.resolve( StandardBasicTypes.BOOLEAN )); + } } diff --git a/dspace-api/src/main/java/org/dspace/util/JpaCriteriaBuilderKit.java b/dspace-api/src/main/java/org/dspace/util/JpaCriteriaBuilderKit.java index 9bb3a0e442f9..7f74f0a728cf 100644 --- a/dspace-api/src/main/java/org/dspace/util/JpaCriteriaBuilderKit.java +++ b/dspace-api/src/main/java/org/dspace/util/JpaCriteriaBuilderKit.java @@ -7,9 +7,9 @@ */ package org.dspace.util; -import javax.persistence.criteria.AbstractQuery; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.AbstractQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Root; /** * Data structure containing the required objects to build criteria diff --git a/dspace-api/src/main/java/org/dspace/util/MultiFormatDateParser.java b/dspace-api/src/main/java/org/dspace/util/MultiFormatDateParser.java index 126daa035332..06b02910c99a 100644 --- a/dspace-api/src/main/java/org/dspace/util/MultiFormatDateParser.java +++ b/dspace-api/src/main/java/org/dspace/util/MultiFormatDateParser.java @@ -21,8 +21,8 @@ import java.util.TimeZone; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.servicemanager.DSpaceKernelInit; diff --git a/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java b/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java index d4590ae24ea2..fa89b3441408 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java +++ b/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java @@ -52,7 +52,9 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen @Override public Item createNewItemAndAddItInWorkspace(Context context, Item nativeItem) { try { - WorkspaceItem workspaceItem = workspaceItemService.create(context, nativeItem.getOwningCollection(), false); + WorkspaceItem workspaceItem = workspaceItemService.create(context, nativeItem.getOwningCollection(), + false, + true); Item itemNew = workspaceItem.getItem(); itemService.update(context, itemNew); return itemNew; diff --git a/dspace-api/src/main/java/org/dspace/versioning/Version.java b/dspace-api/src/main/java/org/dspace/versioning/Version.java index ee5c1c418338..ada857c1cf17 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/Version.java +++ b/dspace-api/src/main/java/org/dspace/versioning/Version.java @@ -8,24 +8,25 @@ package org.dspace.versioning; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import org.dspace.content.Item; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; -import org.hibernate.proxy.HibernateProxyHelper; + /** * @author Fabio Bolognesi (fabio at atmire dot com) diff --git a/dspace-api/src/main/java/org/dspace/versioning/VersionHistory.java b/dspace-api/src/main/java/org/dspace/versioning/VersionHistory.java index 231ccc29d973..f207fe8d4f03 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/VersionHistory.java +++ b/dspace-api/src/main/java/org/dspace/versioning/VersionHistory.java @@ -10,21 +10,22 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.OneToMany; -import javax.persistence.OrderBy; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OrderBy; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.apache.commons.collections4.CollectionUtils; import org.dspace.core.Context; +import org.dspace.core.HibernateProxyHelper; import org.dspace.core.ReloadableEntity; -import org.hibernate.proxy.HibernateProxyHelper; + /** diff --git a/dspace-api/src/main/java/org/dspace/versioning/dao/impl/VersionDAOImpl.java b/dspace-api/src/main/java/org/dspace/versioning/dao/impl/VersionDAOImpl.java index 0e28e72d0752..0ef01b8262ed 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/dao/impl/VersionDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/versioning/dao/impl/VersionDAOImpl.java @@ -10,11 +10,11 @@ import java.sql.SQLException; import java.util.LinkedList; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.Item; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; @@ -74,7 +74,7 @@ public List findVersionsWithItems(Context context, VersionHistory versi ) ); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.desc(versionRoot.get(Version_.versionNumber))); criteriaQuery.orderBy(orderList); @@ -84,9 +84,9 @@ public List findVersionsWithItems(Context context, VersionHistory versi @Override public int countVersionsByHistoryWithItem(Context context, VersionHistory versionHistory) throws SQLException { Query query = createQuery(context, "SELECT count(*) FROM " + Version.class.getSimpleName() - + " WHERE versionhistory_id = (:versionhistoryId)" - + " AND item_id IS NOT NULL"); - query.setParameter("versionhistoryId", versionHistory); + + " WHERE versionHistory = :versionhistory" + + " AND item IS NOT NULL"); + query.setParameter("versionhistory", versionHistory); return count(query); } diff --git a/dspace-api/src/main/java/org/dspace/versioning/dao/impl/VersionHistoryDAOImpl.java b/dspace-api/src/main/java/org/dspace/versioning/dao/impl/VersionHistoryDAOImpl.java index eac78c3e6215..b71ef59f2f94 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/dao/impl/VersionHistoryDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/versioning/dao/impl/VersionHistoryDAOImpl.java @@ -10,11 +10,11 @@ import java.sql.SQLException; import java.util.LinkedList; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.dspace.content.Item; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; @@ -47,7 +47,7 @@ public VersionHistory findByItem(Context context, Item item) throws SQLException criteriaQuery.select(versionHistoryRoot); criteriaQuery.where(criteriaBuilder.equal(join.get(Version_.item), item)); - List orderList = new LinkedList<>(); + List orderList = new LinkedList<>(); orderList.add(criteriaBuilder.desc(join.get(Version_.versionNumber))); criteriaQuery.orderBy(orderList); diff --git a/dspace-api/src/main/java/org/dspace/web/ContextUtil.java b/dspace-api/src/main/java/org/dspace/web/ContextUtil.java index 4bdf26c05381..a17d05002b62 100644 --- a/dspace-api/src/main/java/org/dspace/web/ContextUtil.java +++ b/dspace-api/src/main/java/org/dspace/web/ContextUtil.java @@ -10,10 +10,10 @@ import java.sql.SQLException; import java.util.Enumeration; import java.util.Locale; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/workflow/CurationTaskConfig.java b/dspace-api/src/main/java/org/dspace/workflow/CurationTaskConfig.java index be870ee33e76..675fbb03be2d 100644 --- a/dspace-api/src/main/java/org/dspace/workflow/CurationTaskConfig.java +++ b/dspace-api/src/main/java/org/dspace/workflow/CurationTaskConfig.java @@ -18,14 +18,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.validation.constraints.NotNull; import javax.xml.XMLConstants; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; +import jakarta.validation.constraints.NotNull; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Unmarshaller; import org.xml.sax.SAXException; /** diff --git a/dspace-api/src/main/java/org/dspace/workflow/FlowStep.java b/dspace-api/src/main/java/org/dspace/workflow/FlowStep.java index b133c51cfb52..8709481834ba 100644 --- a/dspace-api/src/main/java/org/dspace/workflow/FlowStep.java +++ b/dspace-api/src/main/java/org/dspace/workflow/FlowStep.java @@ -9,7 +9,8 @@ import java.util.ArrayList; import java.util.List; -import javax.validation.constraints.NotNull; + +import jakarta.validation.constraints.NotNull; /** * Linkage between a workflow step and some {@link org.dspace.curate.CurationTask}s. diff --git a/dspace-api/src/main/java/org/dspace/workflow/Task.java b/dspace-api/src/main/java/org/dspace/workflow/Task.java index 112e7c558500..94e92a67135d 100644 --- a/dspace-api/src/main/java/org/dspace/workflow/Task.java +++ b/dspace-api/src/main/java/org/dspace/workflow/Task.java @@ -11,7 +11,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.validation.constraints.NotNull; + +import jakarta.validation.constraints.NotNull; /** * An association between a {@link org.dspace.curate.CurationTask curation task} diff --git a/dspace-api/src/main/java/org/dspace/workflow/TaskSet.java b/dspace-api/src/main/java/org/dspace/workflow/TaskSet.java index 951940d5bb77..a077bfddbeae 100644 --- a/dspace-api/src/main/java/org/dspace/workflow/TaskSet.java +++ b/dspace-api/src/main/java/org/dspace/workflow/TaskSet.java @@ -8,7 +8,8 @@ package org.dspace.workflow; import java.util.List; -import javax.validation.constraints.NotNull; + +import jakarta.validation.constraints.NotNull; /** * A collection of {@link org.dspace.curate.CurationTask curation tasks} to be diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java index a81bebcd5a35..b4e9f3d7f130 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java @@ -15,9 +15,9 @@ import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.Map; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowServiceImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowServiceImpl.java index bc91a1fd9298..cd18b3a0bd19 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowServiceImpl.java @@ -18,9 +18,9 @@ import java.util.Map; import java.util.MissingResourceException; import java.util.UUID; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/service/XmlWorkflowService.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/service/XmlWorkflowService.java index 6b03803d8a10..6dce02de8347 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/service/XmlWorkflowService.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/service/XmlWorkflowService.java @@ -10,9 +10,9 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Item; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/Action.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/Action.java index 1cfa33b12170..d70fd17a109a 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/Action.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/Action.java @@ -11,8 +11,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DCDate; import org.dspace.content.MetadataSchemaEnum; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/AcceptEditRejectAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/AcceptEditRejectAction.java index 67b400c6592e..b55df1a5db2b 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/AcceptEditRejectAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/AcceptEditRejectAction.java @@ -11,8 +11,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.util.Util; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/FinalEditAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/FinalEditAction.java index 9b83be5d7bfa..b287d0c3d1ad 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/FinalEditAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/FinalEditAction.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.util.Util; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ProcessingAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ProcessingAction.java index 7a1c62adbd1e..6a41f40398cb 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ProcessingAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ProcessingAction.java @@ -9,8 +9,8 @@ import java.io.IOException; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.authorize.AuthorizeException; import org.dspace.content.service.ItemService; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ReviewAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ReviewAction.java index bd74ab3c7152..ad2cbe06b13e 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ReviewAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ReviewAction.java @@ -11,8 +11,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.util.Util; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreEvaluationAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreEvaluationAction.java index 16d35b36683a..c8fd3ecb6692 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreEvaluationAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreEvaluationAction.java @@ -14,8 +14,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; 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..a8ed4fd3dae9 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 @@ -11,8 +11,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SelectReviewerAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SelectReviewerAction.java index 0e8ab40a5205..4adeb127eaed 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SelectReviewerAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SelectReviewerAction.java @@ -12,9 +12,9 @@ import java.util.Arrays; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; 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..64e0957b65b7 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 @@ -11,8 +11,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.util.Util; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AssignAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AssignAction.java index e837a8a89394..4d645ae6a5c1 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AssignAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AssignAction.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.dspace.xmlworkflow.RoleMembers; import org.dspace.xmlworkflow.WorkflowConfigurationException; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AssignOriginalSubmitterAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AssignOriginalSubmitterAction.java index 0cd82fe77084..79e2ffc90068 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AssignOriginalSubmitterAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AssignOriginalSubmitterAction.java @@ -12,9 +12,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; import org.dspace.core.LogHelper; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AutoAssignAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AutoAssignAction.java index 401a7c506b98..cf3ceff5752a 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AutoAssignAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/AutoAssignAction.java @@ -11,8 +11,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/ClaimAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/ClaimAction.java index 21fcf6f30996..385d6feea666 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/ClaimAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/ClaimAction.java @@ -11,9 +11,9 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; import org.dspace.core.LogHelper; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/InheritUsersAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/InheritUsersAction.java index 1ffce1afdb4e..25be8da25cfc 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/InheritUsersAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/InheritUsersAction.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.dspace.xmlworkflow.RoleMembers; import org.dspace.xmlworkflow.WorkflowConfigurationException; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/NoUserSelectionAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/NoUserSelectionAction.java index d23a98cedbbf..9606892554a8 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/NoUserSelectionAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/NoUserSelectionAction.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.dspace.xmlworkflow.RoleMembers; import org.dspace.xmlworkflow.state.Step; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/UserSelectionAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/UserSelectionAction.java index 6a0d3e9ca686..06db5137271b 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/UserSelectionAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/userassignment/UserSelectionAction.java @@ -9,8 +9,8 @@ import java.io.IOException; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/ClaimedTask.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/ClaimedTask.java index 8f4794cb3b45..adaf0ec06e2c 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/ClaimedTask.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/ClaimedTask.java @@ -7,17 +7,16 @@ */ package org.dspace.xmlworkflow.storedcomponents; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; @@ -44,18 +43,12 @@ public class ClaimedTask implements ReloadableEntity { @JoinColumn(name = "workflowitem_id") private XmlWorkflowItem workflowItem; - // @Column(name = "workflow_id") -// @Lob @Column(name = "workflow_id", columnDefinition = "text") private String workflowId; - // @Column(name = "step_id") -// @Lob @Column(name = "step_id", columnDefinition = "text") private String stepId; - // @Column(name = "action_id") -// @Lob @Column(name = "action_id", columnDefinition = "text") private String actionId; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/CollectionRole.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/CollectionRole.java index c9a7995e0390..4cbaf1c4112f 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/CollectionRole.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/CollectionRole.java @@ -8,17 +8,17 @@ package org.dspace.xmlworkflow.storedcomponents; import java.sql.SQLException; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.content.Collection; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; @@ -44,8 +44,6 @@ public class CollectionRole implements ReloadableEntity { @SequenceGenerator(name = "cwf_collectionrole_seq", sequenceName = "cwf_collectionrole_seq", allocationSize = 1) private Integer id; - // @Column(name = "role_id") - // @Lob @Column(name = "role_id", columnDefinition = "text") private String roleId; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/InProgressUser.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/InProgressUser.java index efbd26bde5f5..38f410566d1b 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/InProgressUser.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/InProgressUser.java @@ -7,17 +7,16 @@ */ package org.dspace.xmlworkflow.storedcomponents; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTask.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTask.java index 9cfc9ea06826..0c6b01f5c1fa 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTask.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTask.java @@ -7,18 +7,17 @@ */ package org.dspace.xmlworkflow.storedcomponents; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; @@ -46,18 +45,12 @@ public class PoolTask implements ReloadableEntity { @JoinColumn(name = "workflowitem_id") private XmlWorkflowItem workflowItem; - // @Column(name = "workflow_id") -// @Lob @Column(name = "workflow_id", columnDefinition = "text") private String workflowId; - // @Column(name = "step_id") -// @Lob @Column(name = "step_id", columnDefinition = "text") private String stepId; - // @Column(name = "action_id") -// @Lob @Column(name = "action_id", columnDefinition = "text") private String actionId; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/WorkflowItemRole.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/WorkflowItemRole.java index cc6df9731baa..a0d46c27d1eb 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/WorkflowItemRole.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/WorkflowItemRole.java @@ -8,17 +8,17 @@ package org.dspace.xmlworkflow.storedcomponents; import java.sql.SQLException; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; @@ -44,8 +44,6 @@ public class WorkflowItemRole implements ReloadableEntity { @SequenceGenerator(name = "cwf_workflowitemrole_seq", sequenceName = "cwf_workflowitemrole_seq", allocationSize = 1) private Integer id; - // @Column(name = "role_id") -// @Lob @Column(name = "role_id", columnDefinition = "text") private String roleId; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItem.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItem.java index f6ffe6049a5e..529a35bda3a2 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItem.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItem.java @@ -7,18 +7,17 @@ */ package org.dspace.xmlworkflow.storedcomponents; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/ClaimedTaskDAOImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/ClaimedTaskDAOImpl.java index 956a4648c53a..70fe74de8a2f 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/ClaimedTaskDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/ClaimedTaskDAOImpl.java @@ -9,10 +9,10 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.EPerson; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/CollectionRoleDAOImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/CollectionRoleDAOImpl.java index b3cd32c74f0d..5c19fd5a8e59 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/CollectionRoleDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/CollectionRoleDAOImpl.java @@ -9,11 +9,11 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.Query; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.Query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.content.Collection; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/InProgressUserDAOImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/InProgressUserDAOImpl.java index 783d403c054a..a02a947e2c68 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/InProgressUserDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/InProgressUserDAOImpl.java @@ -9,10 +9,10 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.EPerson; @@ -78,7 +78,7 @@ public int countInProgressUsers(Context context, XmlWorkflowItem workflowItem) t CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root inProgressUserRoot = criteriaQuery.from(InProgressUser.class); - + criteriaQuery.select(criteriaBuilder.count(inProgressUserRoot)); criteriaQuery.where(criteriaBuilder.and( criteriaBuilder.equal(inProgressUserRoot.get(InProgressUser_.workflowItem), workflowItem), criteriaBuilder.equal(inProgressUserRoot.get(InProgressUser_.finished), false) @@ -94,7 +94,7 @@ public int countFinishedUsers(Context context, XmlWorkflowItem workflowItem) thr CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root inProgressUserRoot = criteriaQuery.from(InProgressUser.class); - + criteriaQuery.select(criteriaBuilder.count(inProgressUserRoot)); criteriaQuery.where(criteriaBuilder.and( criteriaBuilder.equal(inProgressUserRoot.get(InProgressUser_.workflowItem), workflowItem), criteriaBuilder.equal(inProgressUserRoot.get(InProgressUser_.finished), true) diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/PoolTaskDAOImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/PoolTaskDAOImpl.java index 0857a325b5df..2e95c2f9d0bb 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/PoolTaskDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/PoolTaskDAOImpl.java @@ -9,10 +9,10 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.EPerson; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/WorkflowItemRoleDAOImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/WorkflowItemRoleDAOImpl.java index fdc2413b5ffd..6dc2fc9601ce 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/WorkflowItemRoleDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/WorkflowItemRoleDAOImpl.java @@ -9,10 +9,10 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.EPerson; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/XmlWorkflowItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/XmlWorkflowItemDAOImpl.java index 659a2123d90a..8994efae1af2 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/XmlWorkflowItemDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/dao/impl/XmlWorkflowItemDAOImpl.java @@ -9,11 +9,11 @@ import java.sql.SQLException; import java.util.List; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.content.Item_; @@ -66,12 +66,11 @@ public int countAll(Context context) throws SQLException { @Override public int countAllInCollection(Context context, Collection collection) throws SQLException { - - CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root xmlWorkflowItemRoot = criteriaQuery.from(XmlWorkflowItem.class); + criteriaQuery.select(criteriaBuilder.count(xmlWorkflowItemRoot)); if (collection != null) { criteriaQuery.where(criteriaBuilder.equal(xmlWorkflowItemRoot.get(XmlWorkflowItem_.collection), collection)); @@ -109,7 +108,8 @@ public int countBySubmitter(Context context, EPerson ep) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); Root xmlWorkflowItemRoot = criteriaQuery.from(XmlWorkflowItem.class); - Join join = xmlWorkflowItemRoot.join("item"); + criteriaQuery.select(criteriaBuilder.count(xmlWorkflowItemRoot)); + Join join = xmlWorkflowItemRoot.join(XmlWorkflowItem_.item); criteriaQuery.where(criteriaBuilder.equal(join.get(Item_.submitter), ep)); return count(context, criteriaQuery, criteriaBuilder, xmlWorkflowItemRoot); } diff --git a/dspace-api/src/main/resources/org/dspace/workflow/workflow-curation.xsd b/dspace-api/src/main/resources/org/dspace/workflow/workflow-curation.xsd index 184ee4bfb615..3c56e2a32399 100644 --- a/dspace-api/src/main/resources/org/dspace/workflow/workflow-curation.xsd +++ b/dspace-api/src/main/resources/org/dspace/workflow/workflow-curation.xsd @@ -11,9 +11,9 @@ + jaxb:version='3.0'> Workflow curation enables curation tasks to be assigned to 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 0212e5efcca1..3a305d0ccdb9 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml @@ -27,6 +27,7 @@ + @@ -180,6 +181,13 @@ submission + + + submit.progressbar.duplicates + org.dspace.app.rest.submit.step.DuplicateDetectionStep + duplicates + + submit.progressbar.coarnotify org.dspace.app.rest.submit.step.NotifyStep @@ -281,6 +289,12 @@ + + + + + + diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index 3dc4e398c11b..b44f319a35f6 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -175,6 +175,8 @@ authority.controlled.dspace.object.owner = true webui.browse.link.1 = author:dc.contributor.* webui.browse.link.2 = subject:dc.subject.* +# Enable duplicate detection for tests +duplicate.enable = true ########################################### # LDN CONFIGURATIONS # @@ -184,3 +186,9 @@ qaevents.enabled = true ldn.ip-range.enabled = true ldn.notify.inbox.block-untrusted = true 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 diff --git a/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java b/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java index e2cd3e040421..9bacbb97eec4 100644 --- a/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java +++ b/dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java @@ -190,29 +190,38 @@ public void destroy() throws Exception { AbstractBuilder.cleanupObjects(); parentCommunity = null; cleanupContext(); + } catch (Exception e) { + throw new RuntimeException("Error cleaning up builder objects & context object", e); + } + + ServiceManager serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); - ServiceManager serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); - // Clear the search core. - MockSolrSearchCore searchService = serviceManager - .getServiceByName(null, MockSolrSearchCore.class); - searchService.reset(); - // Clear the statistics core. - serviceManager - .getServiceByName(SolrStatisticsCore.class.getName(), MockSolrStatisticsCore.class) - .reset(); + // Clear the search core. + MockSolrSearchCore searchService = serviceManager + .getServiceByName(null, MockSolrSearchCore.class); + searchService.reset(); - MockSolrLoggerServiceImpl statisticsService = serviceManager - .getServiceByName("solrLoggerService", MockSolrLoggerServiceImpl.class); - statisticsService.reset(); + // Clear the statistics core. + serviceManager + .getServiceByName(SolrStatisticsCore.class.getName(), MockSolrStatisticsCore.class) + .reset(); - MockAuthoritySolrServiceImpl authorityService = serviceManager - .getServiceByName(AuthoritySearchService.class.getName(), MockAuthoritySolrServiceImpl.class); - authorityService.reset(); + // Reset the statistics logger service + MockSolrLoggerServiceImpl loggerService = serviceManager + .getServiceByName("solrLoggerService", MockSolrLoggerServiceImpl.class); + loggerService.reset(); - MockQAEventService qaEventService = serviceManager - .getServiceByName(QAEventService.class.getName(), MockQAEventService.class); - qaEventService.reset(); + // Clear the authority core + MockAuthoritySolrServiceImpl authorityService = serviceManager + .getServiceByName(AuthoritySearchService.class.getName(), MockAuthoritySolrServiceImpl.class); + authorityService.reset(); + // Clear the QA events core + MockQAEventService qaEventService = serviceManager + .getServiceByName(QAEventService.class.getName(), MockQAEventService.class); + qaEventService.reset(); + + try { // Reload our ConfigurationService (to reset configs to defaults again) DSpaceServicesFactory.getInstance().getConfigurationService().reloadConfig(); @@ -221,7 +230,7 @@ public void destroy() throws Exception { // NOTE: we explicitly do NOT destroy our default eperson & admin as they // are cached and reused for all tests. This speeds up all tests. } catch (Exception e) { - throw new RuntimeException(e); + throw new RuntimeException("Error reloading configuration & resetting builders", e); } } diff --git a/dspace-api/src/test/java/org/dspace/app/itemexport/ItemExportCLIIT.java b/dspace-api/src/test/java/org/dspace/app/itemexport/ItemExportCLIIT.java index 6db37bdbcd05..af12cfd5538a 100644 --- a/dspace-api/src/test/java/org/dspace/app/itemexport/ItemExportCLIIT.java +++ b/dspace-api/src/test/java/org/dspace/app/itemexport/ItemExportCLIIT.java @@ -83,9 +83,9 @@ public void setUp() throws Exception { @After @Override public void destroy() throws Exception { - PathUtils.deleteDirectory(tempDir); + PathUtils.deleteOnExit(tempDir); for (Path path : Files.list(workDir).collect(Collectors.toList())) { - PathUtils.delete(path); + PathUtils.deleteOnExit(path); } super.destroy(); } diff --git a/dspace-api/src/test/java/org/dspace/app/itemimport/ItemImportCLIIT.java b/dspace-api/src/test/java/org/dspace/app/itemimport/ItemImportCLIIT.java index 08ae3af4ae06..d6daa06aaa42 100644 --- a/dspace-api/src/test/java/org/dspace/app/itemimport/ItemImportCLIIT.java +++ b/dspace-api/src/test/java/org/dspace/app/itemimport/ItemImportCLIIT.java @@ -92,9 +92,9 @@ public void setUp() throws Exception { @After @Override public void destroy() throws Exception { - PathUtils.deleteDirectory(tempDir); + PathUtils.deleteOnExit(tempDir); for (Path path : Files.list(workDir).collect(Collectors.toList())) { - PathUtils.delete(path); + PathUtils.deleteOnExit(path); } super.destroy(); } diff --git a/dspace-api/src/test/java/org/dspace/app/ldn/LDNMessageConsumerIT.java b/dspace-api/src/test/java/org/dspace/app/ldn/LDNMessageConsumerIT.java index 305261c7c378..4f5fa6762d31 100644 --- a/dspace-api/src/test/java/org/dspace/app/ldn/LDNMessageConsumerIT.java +++ b/dspace-api/src/test/java/org/dspace/app/ldn/LDNMessageConsumerIT.java @@ -93,8 +93,7 @@ public void testLDNMessageConsumerRequestReview() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyService = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -165,8 +164,7 @@ public void testLDNMessageConsumerRequestReviewAutomatic() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyService = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -242,8 +240,7 @@ public void testLDNMessageConsumerRequestEndorsement() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyService = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -314,8 +311,7 @@ public void testLDNMessageConsumerRequestIngest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyService = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -386,8 +382,7 @@ public void testLDNMessageConsumerRequestFake() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyService = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") diff --git a/dspace-api/src/test/java/org/dspace/app/ldn/action/SendLDNMessageActionIT.java b/dspace-api/src/test/java/org/dspace/app/ldn/action/SendLDNMessageActionIT.java index b1a6db4a0729..73f97b2a6a7c 100644 --- a/dspace-api/src/test/java/org/dspace/app/ldn/action/SendLDNMessageActionIT.java +++ b/dspace-api/src/test/java/org/dspace/app/ldn/action/SendLDNMessageActionIT.java @@ -105,8 +105,7 @@ public void testLDNMessageConsumerRequestReview() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyService = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://www.notify-inbox.info/") .withLdnUrl("https://notify-inbox.info/inbox/") @@ -156,8 +155,7 @@ public void testLDNMessageConsumerRequestReviewGotRedirection() throws Exception // ldnUrl should be https://notify-inbox.info/inbox/ // but used https://notify-inbox.info/inbox for redirection NotifyServiceEntity notifyService = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://www.notify-inbox.info/") .withLdnUrl("https://notify-inbox.info/inbox") @@ -203,8 +201,7 @@ public void testLDNMessageConsumerRequestReviewWithInvalidLdnUrl() throws Except context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyService = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://www.notify-inbox.info/") .withLdnUrl("https://notify-inbox.info/invalidLdnUrl/") 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 7d808ab8715c..2cddbb511f91 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 @@ -159,7 +159,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); + WorkspaceItem workspaceItem = workspaceItemService.create(context, col1, id, false, false); installItemService.installItem(context, workspaceItem, "123456789/0100"); performImportNoForceScript(tempFile); Iterator items = itemService.findByCollection(context, col1); diff --git a/dspace-api/src/test/java/org/dspace/app/requestitem/JavaMailTestTransport.java b/dspace-api/src/test/java/org/dspace/app/requestitem/JavaMailTestTransport.java index 96cf00c312ba..f6fbfe02f376 100644 --- a/dspace-api/src/test/java/org/dspace/app/requestitem/JavaMailTestTransport.java +++ b/dspace-api/src/test/java/org/dspace/app/requestitem/JavaMailTestTransport.java @@ -7,12 +7,12 @@ */ package org.dspace.app.requestitem; -import javax.mail.Address; -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.URLName; +import jakarta.mail.Address; +import jakarta.mail.Message; +import jakarta.mail.MessagingException; +import jakarta.mail.Session; +import jakarta.mail.Transport; +import jakarta.mail.URLName; /** * A dummy load for SMTP transport, which saves the last message "sent" for diff --git a/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemEmailNotifierTest.java b/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemEmailNotifierTest.java index 713e007c58a2..eb3bf68b8942 100644 --- a/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemEmailNotifierTest.java +++ b/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemEmailNotifierTest.java @@ -12,12 +12,11 @@ import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; -import javax.mail.Address; -import javax.mail.Message; -import javax.mail.Provider; -import javax.mail.Session; -import javax.mail.internet.InternetAddress; - +import jakarta.mail.Address; +import jakarta.mail.Message; +import jakarta.mail.Provider; +import jakarta.mail.Session; +import jakarta.mail.internet.InternetAddress; import org.dspace.AbstractUnitTest; import org.dspace.app.requestitem.factory.RequestItemServiceFactory; import org.dspace.app.requestitem.service.RequestItemService; @@ -34,6 +33,7 @@ import org.dspace.handle.service.HandleService; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -78,6 +78,13 @@ public static void setUpClass() { = RequestItemServiceFactory.getInstance().getRequestItemService(); } + @AfterClass + public static void tearDownClass() throws Exception { + // AbstractUnitTest doesn't do this for us. + AbstractBuilder.cleanupObjects(); + AbstractBuilder.destroy(); + } + /** * Test of sendRequest method, of class RequestItemEmailNotifier. * @throws java.lang.Exception passed through. diff --git a/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemHelpdeskStrategyTest.java b/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemHelpdeskStrategyTest.java index b03d7576f991..816756f9d556 100644 --- a/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemHelpdeskStrategyTest.java +++ b/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemHelpdeskStrategyTest.java @@ -67,8 +67,10 @@ public static void setUpClass() } @AfterClass - public static void tearDownClass() { - AbstractBuilder.destroy(); // AbstractUnitTest doesn't do this for us. + public static void tearDownClass() throws Exception { + // AbstractUnitTest doesn't do this for us. + AbstractBuilder.cleanupObjects(); + AbstractBuilder.destroy(); } @Before diff --git a/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemSubmitterStrategyTest.java b/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemSubmitterStrategyTest.java index f485a591b079..964b3fe303f9 100644 --- a/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemSubmitterStrategyTest.java +++ b/dspace-api/src/test/java/org/dspace/app/requestitem/RequestItemSubmitterStrategyTest.java @@ -56,8 +56,10 @@ public static void setUpClass() } @AfterClass - public static void tearDownClass() { - AbstractBuilder.destroy(); // AbstractUnitTest doesn't do this for us. + public static void tearDownClass() throws Exception { + // AbstractUnitTest doesn't do this for us. + AbstractBuilder.cleanupObjects(); + AbstractBuilder.destroy(); } @Before diff --git a/dspace-api/src/test/java/org/dspace/app/suggestion/SuggestionUtilsIT.java b/dspace-api/src/test/java/org/dspace/app/suggestion/SuggestionUtilsIT.java index dd9c0d8f5f76..98abfdb7d02e 100644 --- a/dspace-api/src/test/java/org/dspace/app/suggestion/SuggestionUtilsIT.java +++ b/dspace-api/src/test/java/org/dspace/app/suggestion/SuggestionUtilsIT.java @@ -24,9 +24,9 @@ import java.util.HashMap; import java.util.List; import java.util.Optional; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.Unmarshaller; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.Unmarshaller; import org.apache.commons.collections.CollectionUtils; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; diff --git a/dspace-api/src/test/java/org/dspace/app/util/GoogleMetadataTest.java b/dspace-api/src/test/java/org/dspace/app/util/GoogleMetadataTest.java index c2543ca17b8c..9baf0fe3e963 100644 --- a/dspace-api/src/test/java/org/dspace/app/util/GoogleMetadataTest.java +++ b/dspace-api/src/test/java/org/dspace/app/util/GoogleMetadataTest.java @@ -125,19 +125,17 @@ public void testGetPDFURLDifferentMimeTypes() throws Exception { Bitstream b = bitstreamService.create( context, new ByteArrayInputStream("Bitstream 1".getBytes(StandardCharsets.UTF_8))); b.setName(context, "Word"); - b.setFormat(context, bitstreamFormatService.create(context)); - b.getFormat(context).setMIMEType("application/msword"); + b.setFormat(context, bitstreamFormatService.findByMIMEType(context, "application/msword")); bundleService.addBitstream(context, bundle, b); Bitstream b2 = bitstreamService.create( context, new ByteArrayInputStream("Bitstream 2".getBytes(StandardCharsets.UTF_8))); b2.setName(context, "Pdf"); - b2.setFormat(context, bitstreamFormatService.create(context)); - b2.getFormat(context).setMIMEType("application/pdf"); + b2.setFormat(context, bitstreamFormatService.findByMIMEType(context, "application/pdf")); bundleService.addBitstream(context, bundle, b2); Bitstream b3 = bitstreamService.create( context, new ByteArrayInputStream("Bitstream 3".getBytes(StandardCharsets.UTF_8))); b3.setName(context, "Rtf"); - b3.setFormat(context, bitstreamFormatService.create(context)); + b3.setFormat(context, bitstreamFormatService.findByMIMEType(context, "text/richtext")); b3.getFormat(context).setMIMEType("text/richtext"); bundleService.addBitstream(context, bundle, b3); context.restoreAuthSystemState(); @@ -160,20 +158,17 @@ public void testGetPDFURLSameMimeTypes() throws Exception { Bitstream b = bitstreamService.create( context, new ByteArrayInputStream("123456789".getBytes(StandardCharsets.UTF_8))); b.setName(context, "size9"); - b.setFormat(context, bitstreamFormatService.create(context)); - b.getFormat(context).setMIMEType("application/pdf"); + b.setFormat(context, bitstreamFormatService.findByMIMEType(context, "application/pdf")); bundleService.addBitstream(context, bundle, b); Bitstream b2 = bitstreamService.create( context, new ByteArrayInputStream("1".getBytes(StandardCharsets.UTF_8))); b2.setName(context, "size1"); - b2.setFormat(context, bitstreamFormatService.create(context)); - b2.getFormat(context).setMIMEType("application/pdf"); + b2.setFormat(context, bitstreamFormatService.findByMIMEType(context, "application/pdf")); bundleService.addBitstream(context, bundle, b2); Bitstream b3 = bitstreamService.create( context, new ByteArrayInputStream("12345".getBytes(StandardCharsets.UTF_8))); b3.setName(context, "size5"); - b3.setFormat(context, bitstreamFormatService.create(context)); - b3.getFormat(context).setMIMEType("text/richtext"); + b3.setFormat(context, bitstreamFormatService.findByMIMEType(context, "text/richtext")); bundleService.addBitstream(context, bundle, b3); context.restoreAuthSystemState(); context.commit(); @@ -195,20 +190,17 @@ public void testGetPDFURLSameMimeTypesSameSize() throws Exception { Bitstream b = bitstreamService.create( context, new ByteArrayInputStream("1".getBytes(StandardCharsets.UTF_8))); b.setName(context, "first"); - b.setFormat(context, bitstreamFormatService.create(context)); - b.getFormat(context).setMIMEType("application/pdf"); + b.setFormat(context, bitstreamFormatService.findByMIMEType(context, "application/pdf")); bundleService.addBitstream(context, bundle, b); Bitstream b2 = bitstreamService.create( context, new ByteArrayInputStream("1".getBytes(StandardCharsets.UTF_8))); b2.setName(context, "second"); - b2.setFormat(context, bitstreamFormatService.create(context)); - b2.getFormat(context).setMIMEType("application/pdf"); + b2.setFormat(context, bitstreamFormatService.findByMIMEType(context, "application/pdf")); bundleService.addBitstream(context, bundle, b2); Bitstream b3 = bitstreamService.create( context, new ByteArrayInputStream("1".getBytes(StandardCharsets.UTF_8))); b3.setName(context, "third"); - b3.setFormat(context, bitstreamFormatService.create(context)); - b3.getFormat(context).setMIMEType("application/pdf"); + b3.setFormat(context, bitstreamFormatService.findByMIMEType(context, "application/pdf")); bundleService.addBitstream(context, bundle, b3); context.restoreAuthSystemState(); context.commit(); @@ -230,20 +222,17 @@ public void testGetPDFURLWithPrimaryBitstream() throws Exception { Bitstream b = bitstreamService.create( context, new ByteArrayInputStream("Larger file than primary".getBytes(StandardCharsets.UTF_8))); b.setName(context, "first"); - b.setFormat(context, bitstreamFormatService.create(context)); - b.getFormat(context).setMIMEType("unknown"); + b.setFormat(context, bitstreamFormatService.findUnknown(context)); bundleService.addBitstream(context, bundle, b); Bitstream b2 = bitstreamService.create(context, new ByteArrayInputStream( "Bitstream with more prioritized mimetype than primary".getBytes(StandardCharsets.UTF_8))); b2.setName(context, "second"); - b2.setFormat(context, bitstreamFormatService.create(context)); - b2.getFormat(context).setMIMEType("application/pdf"); + b2.setFormat(context, bitstreamFormatService.findByMIMEType(context, "application/pdf")); bundleService.addBitstream(context, bundle, b2); Bitstream b3 = bitstreamService.create( context, new ByteArrayInputStream("1".getBytes(StandardCharsets.UTF_8))); b3.setName(context, "primary"); - b3.setFormat(context, bitstreamFormatService.create(context)); - b3.getFormat(context).setMIMEType("Primary"); + b3.setFormat(context, bitstreamFormatService.findByMIMEType(context, "text/richtext")); bundleService.addBitstream(context, bundle, b3); bundle.setPrimaryBitstreamID(b3); context.restoreAuthSystemState(); @@ -267,20 +256,17 @@ public void testGetPDFURLWithUndefinedMimeTypes() throws Exception { Bitstream b = bitstreamService.create( context, new ByteArrayInputStream("12".getBytes(StandardCharsets.UTF_8))); b.setName(context, "small"); - b.setFormat(context, bitstreamFormatService.create(context)); - b.getFormat(context).setMIMEType("unknown type 1"); + b.setFormat(context, bitstreamFormatService.findUnknown(context)); bundleService.addBitstream(context, bundle, b); Bitstream b2 = bitstreamService.create( context, new ByteArrayInputStream("12121212".getBytes(StandardCharsets.UTF_8))); b2.setName(context, "medium"); - b2.setFormat(context, bitstreamFormatService.create(context)); - b2.getFormat(context).setMIMEType("unknown type 2"); + b2.setFormat(context, bitstreamFormatService.findUnknown(context)); bundleService.addBitstream(context, bundle, b2); Bitstream b3 = bitstreamService.create( context, new ByteArrayInputStream("12121212121212".getBytes(StandardCharsets.UTF_8))); b3.setName(context, "large"); - b3.setFormat(context, bitstreamFormatService.create(context)); - b3.getFormat(context).setMIMEType("unknown type 3"); + b3.setFormat(context, bitstreamFormatService.findUnknown(context)); bundleService.addBitstream(context, bundle, b3); context.restoreAuthSystemState(); context.commit(); @@ -328,18 +314,15 @@ public void testGetPDFURLWithEmptyBitstreams() throws Exception { Bitstream b = bitstreamService.create(context, new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8))); b.setName(context, "small"); - b.setFormat(context, bitstreamFormatService.create(context)); - b.getFormat(context).setMIMEType("unknown type 1"); + b.setFormat(context, bitstreamFormatService.findUnknown(context)); bundleService.addBitstream(context, bundle, b); Bitstream b2 = bitstreamService.create(context, new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8))); b2.setName(context, "medium"); - b2.setFormat(context, bitstreamFormatService.create(context)); - b2.getFormat(context).setMIMEType("unknown type 2"); + b2.setFormat(context, bitstreamFormatService.findUnknown(context)); bundleService.addBitstream(context, bundle, b2); Bitstream b3 = bitstreamService.create(context, new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8))); b3.setName(context, "large"); - b3.setFormat(context, bitstreamFormatService.create(context)); - b3.getFormat(context).setMIMEType("unknown type 3"); + b3.setFormat(context, bitstreamFormatService.findUnknown(context)); bundleService.addBitstream(context, bundle, b3); context.restoreAuthSystemState(); context.commit(); @@ -361,8 +344,7 @@ public void testGetPdfUrlOfEmbargoed() throws Exception { Bitstream b = bitstreamService.create( context, new ByteArrayInputStream("Larger file than primary".getBytes(StandardCharsets.UTF_8))); b.setName(context, "first"); - b.setFormat(context, bitstreamFormatService.create(context)); - b.getFormat(context).setMIMEType("unknown"); + b.setFormat(context, bitstreamFormatService.findUnknown(context)); bundleService.addBitstream(context, bundle, b); // Set 3 month embargo on pdf Period period = Period.ofMonths(3); diff --git a/dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java b/dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java index c67963f203ac..5c18835c4f1c 100644 --- a/dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java @@ -15,6 +15,7 @@ import org.apache.logging.log4j.Logger; import org.dspace.alerts.service.SystemWideAlertService; import org.dspace.app.ldn.factory.NotifyServiceFactory; +import org.dspace.app.ldn.service.LDNMessageService; import org.dspace.app.ldn.service.NotifyPatternToTriggerService; import org.dspace.app.ldn.service.NotifyService; import org.dspace.app.ldn.service.NotifyServiceInboundPatternService; @@ -126,6 +127,7 @@ public abstract class AbstractBuilder { static QAEventService qaEventService; static SolrSuggestionStorageService solrSuggestionService; + static LDNMessageService ldnMessageService; protected Context context; @@ -199,6 +201,7 @@ public static void init() { notifyPatternToTriggerService = NotifyServiceFactory.getInstance().getNotifyPatternToTriggerService(); qaEventService = new DSpace().getSingletonService(QAEventService.class); solrSuggestionService = new DSpace().getSingletonService(SolrSuggestionStorageService.class); + ldnMessageService = NotifyServiceFactory.getInstance().getLDNMessageService(); } @@ -240,6 +243,7 @@ public static void destroy() { inboundPatternService = null; notifyPatternToTriggerService = null; qaEventService = null; + ldnMessageService = null; } diff --git a/dspace-api/src/test/java/org/dspace/builder/LDNMessageBuilder.java b/dspace-api/src/test/java/org/dspace/builder/LDNMessageBuilder.java new file mode 100644 index 000000000000..1ed369457365 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/builder/LDNMessageBuilder.java @@ -0,0 +1,127 @@ +/** + * 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.builder; + +import java.sql.SQLException; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.app.ldn.model.Notification; +import org.dspace.app.ldn.service.LDNMessageService; +import org.dspace.core.Context; +import org.dspace.discovery.SearchServiceException; + +/** + * Builder for {@link LDNMessageEntity} entities. + * + * @author Mohamed Eskander (mohamed.eskander at 4science.com) + * + */ +public class LDNMessageBuilder extends AbstractBuilder { + + /* Log4j logger*/ + private static final Logger log = LogManager.getLogger(); + + private LDNMessageEntity ldnMessageEntity; + + protected LDNMessageBuilder(Context context) { + super(context); + } + + @Override + protected LDNMessageService getService() { + return ldnMessageService; + } + + @Override + public void cleanup() throws Exception { + try (Context c = new Context()) { + c.setDispatcher("noindex"); + c.turnOffAuthorisationSystem(); + // Ensure object and any related objects are reloaded before checking to see what needs cleanup + ldnMessageEntity = c.reloadEntity(ldnMessageEntity); + if (ldnMessageEntity != null) { + delete(ldnMessageEntity); + } + c.complete(); + indexingService.commit(); + } + } + + @Override + public void delete(Context c, LDNMessageEntity ldnMessageEntity) throws Exception { + if (ldnMessageEntity != null) { + getService().delete(c, ldnMessageEntity); + } + } + + @Override + public LDNMessageEntity build() { + try { + + ldnMessageService.update(context, ldnMessageEntity); + context.dispatchEvents(); + + indexingService.commit(); + } catch (SearchServiceException | SQLException e) { + log.error(e); + } + return ldnMessageEntity; + } + + public void delete(LDNMessageEntity ldnMessageEntity) throws Exception { + try (Context c = new Context()) { + c.turnOffAuthorisationSystem(); + LDNMessageEntity nsEntity = c.reloadEntity(ldnMessageEntity); + if (nsEntity != null) { + getService().delete(c, nsEntity); + } + c.complete(); + } + + indexingService.commit(); + } + + public static LDNMessageBuilder createNotifyServiceBuilder(Context context, String id) { + LDNMessageBuilder ldnMessageServiceBuilder = new LDNMessageBuilder(context); + return ldnMessageServiceBuilder.create(context, id); + } + + public static LDNMessageBuilder createNotifyServiceBuilder(Context context, Notification notification) { + LDNMessageBuilder ldnMessageServiceBuilder = new LDNMessageBuilder(context); + return ldnMessageServiceBuilder.create(context, notification); + } + + private LDNMessageBuilder create(Context context, String id) { + try { + + this.context = context; + this.ldnMessageEntity = ldnMessageService.create(context, id); + + } catch (SQLException e) { + log.warn("Failed to create the NotifyService", e); + } + + return this; + } + + private LDNMessageBuilder create(Context context, Notification notification) { + try { + + this.context = context; + this.ldnMessageEntity = ldnMessageService.create(context, notification, "127.0.0.1"); + + } catch (SQLException e) { + log.warn("Failed to create the NotifyService", e); + } + + return this; + } + +} \ No newline at end of file diff --git a/dspace-api/src/test/java/org/dspace/builder/NotifyServiceBuilder.java b/dspace-api/src/test/java/org/dspace/builder/NotifyServiceBuilder.java index 9c8de62d8bcc..60d924d31822 100644 --- a/dspace-api/src/test/java/org/dspace/builder/NotifyServiceBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/NotifyServiceBuilder.java @@ -88,16 +88,16 @@ public void delete(NotifyServiceEntity notifyServiceEntity) throws Exception { indexingService.commit(); } - public static NotifyServiceBuilder createNotifyServiceBuilder(Context context) { + public static NotifyServiceBuilder createNotifyServiceBuilder(Context context, String name) { NotifyServiceBuilder notifyServiceBuilder = new NotifyServiceBuilder(context); - return notifyServiceBuilder.create(context); + return notifyServiceBuilder.create(context, name); } - private NotifyServiceBuilder create(Context context) { + private NotifyServiceBuilder create(Context context, String name) { try { this.context = context; - this.notifyServiceEntity = notifyService.create(context); + this.notifyServiceEntity = notifyService.create(context, name); } catch (SQLException e) { log.warn("Failed to create the NotifyService", e); @@ -106,11 +106,6 @@ private NotifyServiceBuilder create(Context context) { return this; } - public NotifyServiceBuilder withName(String name) { - notifyServiceEntity.setName(name); - return this; - } - public NotifyServiceBuilder withDescription(String description) { notifyServiceEntity.setDescription(description); return this; @@ -146,4 +141,20 @@ public NotifyServiceBuilder withUpperIp(String upperIp) { return this; } + /** + * Delete the Test NotifyServiceEntity referred to by the given ID + * @param id ID of NotifyServiceEntity to delete + * @throws SQLException if error occurs + */ + public static void deleteNotifyService(Integer id) throws SQLException { + try (Context c = new Context()) { + c.turnOffAuthorisationSystem(); + NotifyServiceEntity notifyServiceEntity = notifyService.find(c, id); + if (notifyServiceEntity != null) { + notifyService.delete(c, notifyServiceEntity); + } + c.complete(); + } + } + } \ No newline at end of file diff --git a/dspace-api/src/test/java/org/dspace/builder/RequestItemBuilder.java b/dspace-api/src/test/java/org/dspace/builder/RequestItemBuilder.java index 66e6245ff625..8481b17e1458 100644 --- a/dspace-api/src/test/java/org/dspace/builder/RequestItemBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/RequestItemBuilder.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.Date; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.requestitem.RequestItem; 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 7d844415ab24..8b82149cdf7f 100644 --- a/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java @@ -116,10 +116,12 @@ public void cleanup() throws Exception { delete(c, workspaceItem); } else { item = c.reloadEntity(item); - // check if the wsi has been pushed to the workflow - XmlWorkflowItem wfi = workflowItemService.findByItem(c, item); - if (wfi != null) { - workflowItemService.delete(c, wfi); + if (item != null) { + // check if the wsi has been pushed to the workflow + XmlWorkflowItem wfi = workflowItemService.findByItem(c, item); + if (wfi != null) { + workflowItemService.delete(c, wfi); + } } } item = c.reloadEntity(item); diff --git a/dspace-api/src/test/java/org/dspace/checker/dao/impl/ChecksumHistoryDAOImplTest.java b/dspace-api/src/test/java/org/dspace/checker/dao/impl/ChecksumHistoryDAOImplTest.java index 860df5e887a5..03b274a67ade 100644 --- a/dspace-api/src/test/java/org/dspace/checker/dao/impl/ChecksumHistoryDAOImplTest.java +++ b/dspace-api/src/test/java/org/dspace/checker/dao/impl/ChecksumHistoryDAOImplTest.java @@ -15,8 +15,8 @@ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; -import javax.persistence.Query; +import jakarta.persistence.Query; import org.dspace.AbstractUnitTest; import org.dspace.checker.ChecksumResultCode; import org.dspace.content.Bitstream; @@ -122,7 +122,7 @@ public void testDeleteByDateAndCode() // See if matching old row is gone. qry = dbc.getSession().createQuery( - "SELECT COUNT(*) FROM ChecksumHistory WHERE process_end_date = :date"); + "SELECT COUNT(*) FROM ChecksumHistory WHERE processEndDate = :date"); long count; qry.setParameter("date", matchDate); diff --git a/dspace-api/src/test/java/org/dspace/content/BitstreamFormatTest.java b/dspace-api/src/test/java/org/dspace/content/BitstreamFormatTest.java index ff99a820b5b7..aa1952492b4a 100644 --- a/dspace-api/src/test/java/org/dspace/content/BitstreamFormatTest.java +++ b/dspace-api/src/test/java/org/dspace/content/BitstreamFormatTest.java @@ -222,6 +222,7 @@ public void testCreateAdmin() throws SQLException, AuthorizeException { assertThat("testCreate 3", found.getSupportLevel(), equalTo(-1)); assertFalse("testCreate 4", found.isInternal()); bitstreamFormatService.delete(context, found); + context.commit(); } /** @@ -497,6 +498,7 @@ public void testDeleteAdmin() throws SQLException, AuthorizeException { BitstreamFormat bitstreamFormat = bitstreamFormatService.create(context); int toDeleteIdentifier = bitstreamFormat.getID(); bitstreamFormatService.delete(context, bitstreamFormat); + context.commit(); BitstreamFormat b = bitstreamFormatService.find(context, toDeleteIdentifier); assertThat("testDeleteAdmin 0", b, nullValue()); } diff --git a/dspace-api/src/test/java/org/dspace/content/DuplicateDetectionTest.java b/dspace-api/src/test/java/org/dspace/content/DuplicateDetectionTest.java new file mode 100644 index 000000000000..0b6c909f03e8 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/content/DuplicateDetectionTest.java @@ -0,0 +1,430 @@ +/** + * 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.content; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNull; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.AbstractIntegrationTestWithDatabase; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.ItemBuilder; +import org.dspace.builder.WorkflowItemBuilder; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.DuplicateDetectionService; +import org.dspace.content.virtual.PotentialDuplicate; +import org.dspace.discovery.SearchServiceException; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; +import org.junit.Before; +import org.junit.Test; + +/** + * + * Integration tests for the duplicate detection service + * + * @author Kim Shepherd + */ +public class DuplicateDetectionTest extends AbstractIntegrationTestWithDatabase { + private DuplicateDetectionService duplicateDetectionService = ContentServiceFactory.getInstance() + .getDuplicateDetectionService(); + private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); + private Collection col; + private Collection workflowCol; + private Item item1; + private Item item2; + private Item item3; + private final String item1IssueDate = "2011-10-17"; + private final String item1Subject = "ExtraEntry 1"; + private final String item1Title = "Public item I"; + private final String item1Author = "Smith, Donald"; + + private static final Logger log = LogManager.getLogger(); + + @Before + public void setUp() throws Exception { + super.setUp(); + // Temporarily enable duplicate detection and set comparison distance to 1 + configurationService.setProperty("duplicate.enable", true); + configurationService.setProperty("duplicate.comparison.distance", 1); + configurationService.setProperty("duplicate.comparison.normalise.lowercase", true); + configurationService.setProperty("duplicate.comparison.normalise.whitespace", true); + configurationService.setProperty("duplicate.comparison.solr.field", "deduplication_keyword"); + configurationService.setProperty("duplicate.comparison.metadata.field", new String[]{"dc.title"}); + configurationService.setProperty("duplicate.preview.metadata.field", + new String[]{"dc.date.issued", "dc.subject"}); + + context.turnOffAuthorisationSystem(); + context.setDispatcher("default"); + + parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); + col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection").build(); + workflowCol = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Workflow Collection") + .withWorkflowGroup("reviewer", admin) + .build(); + + // Ingest three example items with slightly different titles + // item2 is 1 edit distance from item1 and item3 + // item1 and item3 are 2 edit distance from each other + item1 = ItemBuilder.createItem(context, col) + .withTitle(item1Title) // Public item I + .withIssueDate(item1IssueDate) + .withAuthor(item1Author) + .withSubject(item1Subject) + .build(); + item2 = ItemBuilder.createItem(context, col) + .withTitle("Public item II") + .withIssueDate("2012-10-17") + .withAuthor("Smith, Donald X.") + .withSubject("ExtraEntry 2") + .build(); + item3 = ItemBuilder.createItem(context, col) + .withTitle("Public item III") + .withIssueDate("2013-10-17") + .withAuthor("Smith, Donald Y.") + .withSubject("ExtraEntry 3") + .build(); + + + } + + /** + * Test instantiation of simple potential duplicate object + */ + @Test + public void testPotentialDuplicateInstantatation() { + PotentialDuplicate potentialDuplicate = new PotentialDuplicate(); + // The constructor should instantiate a new list for metadata + assertEquals("Metadata value list size should be 0", + 0, potentialDuplicate.getMetadataValueList().size()); + // Other properties should not be set + assertNull("Title should be null", potentialDuplicate.getTitle()); + //StringUtils.getLevenshteinDistance() + } + + /** + * Test instantiation of simple potential duplicate object given an item as a constructor argument + */ + @Test + public void testPotentialDuplicateInstantiationWithItem() { + PotentialDuplicate potentialDuplicate = new PotentialDuplicate(item1); + // We should have title, uuid, owning collection name set and metadata value list instantiated to empty + assertEquals("UUID should match item1 uuid", item1.getID(), potentialDuplicate.getUuid()); + assertEquals("Title should match item1 title", item1Title, potentialDuplicate.getTitle()); + assertEquals("Owning collection should match item1 owning collection", + item1.getOwningCollection().getName(), potentialDuplicate.getOwningCollectionName()); + assertEquals("Metadata value list size should be 0", + 0, potentialDuplicate.getMetadataValueList().size()); + } + + /** + * Test that a search for getPotentialDuplicates returns the expected results, populated with the expected + * preview values and metadata. This is the core method used by the duplicate item link repository and + * detect duplicates submission step. + * + * @throws Exception + */ + @Test + public void testSearchDuplicates() throws Exception { + + // Get potential duplicates of item 1: + // Expected: Public item II should appear as it has the configured levenshtein distance of 1 + List potentialDuplicates = duplicateDetectionService.getPotentialDuplicates(context, item1); + + // Make sure result list is size 1 + int size = 1; + assertEquals("Potential duplicates of item1 should have size " + size, + size, potentialDuplicates.size()); + + // The only member should be Public item II (one distance from public item I) + assertEquals("Item II should be be the detected duplicate", + item2.getID(), potentialDuplicates.get(0).getUuid()); + + // Get potential duplicates of item2: + // Expected: BOTH other items should appear as they are both 1 distance away from "Public item II" + potentialDuplicates = duplicateDetectionService.getPotentialDuplicates(context, item2); + + // Sort by title + potentialDuplicates.sort(Comparator.comparing(PotentialDuplicate::getTitle)); + + // Make sure result list is size 1 + size = 2; + assertEquals("Potential duplicates of item2 should have size " + size, + size, potentialDuplicates.size()); + + // The result list should contain both item1 and item3 in the expected order + assertEquals("item1 should be the first detected duplicate", + item1.getID(), potentialDuplicates.get(0).getUuid()); + assertEquals("item3 should be be the second detected duplicate", + item3.getID(), potentialDuplicates.get(1).getUuid()); + + // Check metadata is populated as per configuration, using item1 (first in results) + // Check for date + Optional foundDate = potentialDuplicates.get(0).getMetadataValueList().stream() + .filter(metadataValue -> metadataValue.getMetadataField().toString('.') + .equals("dc.date.issued")) + .map(MetadataValue::getValue).findFirst(); + assertThat("There should be an issue date found", foundDate.isPresent()); + assertEquals("item1 issue date should match the duplicate obj metadata issue date", + item1IssueDate, foundDate.get()); + // Check for subject + Optional foundSubject = potentialDuplicates.get(0).getMetadataValueList().stream() + .filter(metadataValue -> metadataValue.getMetadataField().toString('.').equals("dc.subject")) + .map(MetadataValue::getValue).findFirst(); + assertThat("There should be a subject found", foundSubject.isPresent()); + assertEquals("item1 subject should match the duplicate obj metadata subject", + item1Subject, foundSubject.get()); + + // Check for author, which was NOT configured to be copied + Optional foundAuthor = potentialDuplicates.get(0).getMetadataValueList().stream() + .filter(metadataValue -> metadataValue.getMetadataField().toString('.') + .equals("dc.contributor.author")) + .map(MetadataValue::getValue).findFirst(); + assertThat("There should NOT be an author found", foundAuthor.isEmpty()); + + } + + /** + * Test that a search for getPotentialDuplicates properly escapes Solr reserved characters + * e.g. + - && | | ! ( ) { } [ ] ^ " ~ * ? : \ + * + * @throws Exception + */ + @Test + public void testSearchDuplicatesWithReservedSolrCharacters() throws Exception { + + + + Item item4 = ItemBuilder.createItem(context, col) + .withTitle("Testing: An Important Development Step") + .withIssueDate(item1IssueDate) + .withAuthor(item1Author) + .withSubject(item1Subject) + .build(); + Item item5 = ItemBuilder.createItem(context, col) + .withTitle("Testing an important development step") + .withIssueDate("2012-10-17") + .withAuthor("Smith, Donald X.") + .withSubject("ExtraEntry 2") + .build(); + + // Get potential duplicates of item 4 and make sure no exceptions are thrown + List potentialDuplicates = new ArrayList<>(); + try { + potentialDuplicates = duplicateDetectionService.getPotentialDuplicates(context, item4); + } catch (SearchServiceException e) { + fail("Duplicate search with special characters should NOT result in search exception (" + + e.getMessage() + ")"); + } + + // Make sure result list is size 1 + int size = 1; + assertEquals("Potential duplicates of item4 (special characters) should have size " + size, + size, potentialDuplicates.size()); + + // The only member should be item 5 + assertEquals("Item 5 should be be the detected duplicate", + item5.getID(), potentialDuplicates.get(0).getUuid()); + + } + + //configurationService.setProperty("duplicate.comparison.metadata.field", new String[]{"dc.title"}); + + /** + * Test that a search for a very long title which also contains reserved characters + * + * @throws Exception + */ + @Test + public void testSearchDuplicatesWithVeryLongTitle() throws Exception { + + Item item6 = ItemBuilder.createItem(context, col) + .withTitle("Testing: This title is over 200 characters long and should behave just the same as a " + + "shorter title, with or without reserved characters. This integration test will prove that " + + "long titles are detected as potential duplicates.") + .withIssueDate(item1IssueDate) + .withAuthor(item1Author) + .withSubject(item1Subject) + .build(); + // This item is the same as above, just missing a comma from the title. + Item item7 = ItemBuilder.createItem(context, col) + .withTitle("Testing: This title is over 200 characters long and should behave just the same as a " + + "shorter title with or without reserved characters. This integration test will prove that " + + "long titles are detected as potential duplicates.") + .withIssueDate("2012-10-17") + .withAuthor("Smith, Donald X.") + .withSubject("ExtraEntry 2") + .build(); + + // Get potential duplicates of item 4 and make sure no exceptions are thrown + List potentialDuplicates = new ArrayList<>(); + try { + potentialDuplicates = duplicateDetectionService.getPotentialDuplicates(context, item6); + } catch (SearchServiceException e) { + fail("Duplicate search with special characters (long title) should NOT result in search exception (" + + e.getMessage() + ")"); + } + + // Make sure result list is size 1 + int size = 1; + assertEquals("Potential duplicates of item6 (long title) should have size " + size, + size, potentialDuplicates.size()); + + // The only member should be item 5 + assertEquals("Item 7's long title should match Item 6 as a potential duplicate", + item7.getID(), potentialDuplicates.get(0).getUuid()); + + } + + /** + * Test that a search for a very long title which also contains reserved characters + * + * @throws Exception + */ + @Test + public void testSearchDuplicatesExactMatch() throws Exception { + + // Set distance to 0 manually + configurationService.setProperty("duplicate.comparison.distance", 0); + + Item item8 = ItemBuilder.createItem(context, col) + .withTitle("This integration test will prove that the edit distance of 0 results in an exact match") + .withIssueDate(item1IssueDate) + .withAuthor(item1Author) + .withSubject(item1Subject) + .build(); + // This item is the same as above + Item item9 = ItemBuilder.createItem(context, col) + .withTitle("This integration test will prove that the edit distance of 0 results in an exact match") + .withIssueDate("2012-10-17") + .withAuthor("Smith, Donald X.") + .withSubject("ExtraEntry") + .build(); + // This item has one character different, greater than the edit distance + Item item10 = ItemBuilder.createItem(context, col) + .withTitle("This integration test will prove that the edit distance of 0 results in an exact match.") + .withIssueDate("2012-10-17") + .withAuthor("Smith, Donald X.") + .withSubject("ExtraEntry") + .build(); + + // Get potential duplicates of item 4 and make sure no exceptions are thrown + List potentialDuplicates = new ArrayList<>(); + try { + potentialDuplicates = duplicateDetectionService.getPotentialDuplicates(context, item8); + } catch (SearchServiceException e) { + fail("Duplicate search with special characters (long title) should NOT result in search exception (" + + e.getMessage() + ")"); + } + + // Make sure result list is size 1 - we do NOT expect item 10 to appear + int size = 1; + assertEquals("ONLY one exact match should be found (item 9) " + size, + size, potentialDuplicates.size()); + + // The only member should be item 9 + assertEquals("Item 9 should match Item 8 as a potential duplicate", + item9.getID(), potentialDuplicates.get(0).getUuid()); + + } + + @Test + public void testSearchDuplicatesInWorkflow() throws Exception { + // Get potential duplicates of item 1: + // Expected: Public item II should appear as it has the configured levenshtein distance of 1 + context.turnOffAuthorisationSystem(); + //context.setDispatcher("default"); + XmlWorkflowItem workflowItem1 = WorkflowItemBuilder.createWorkflowItem(context, workflowCol) + .withTitle("Unique title") + .withSubmitter(eperson) + .build(); + XmlWorkflowItem workflowItem2 = WorkflowItemBuilder.createWorkflowItem(context, workflowCol) + .withTitle("Unique title") + .withSubmitter(eperson) + .build(); + + //indexingService.commit(); + context.restoreAuthSystemState(); + context.setCurrentUser(admin); + List potentialDuplicates = + duplicateDetectionService.getPotentialDuplicates(context, workflowItem1.getItem()); + + // Make sure result list is size 1 + int size = 1; + assertEquals("Potential duplicates of item1 should have size " + size, + size, potentialDuplicates.size()); + + // The only member should be workflow item 2 + assertEquals("Workflow item 2 should be be the detected duplicate", + workflowItem2.getItem().getID(), potentialDuplicates.get(0).getUuid()); + } + + /** + * Test that a search for getPotentialDuplicates with multiple fields configured as comparison value + * gives the expected results + * + * @throws Exception + */ + @Test + public void testSearchDuplicatesWithMultipleFields() throws Exception { + // Set configure to use both title and author fields + configurationService.setProperty("duplicate.comparison.metadata.field", + new String[]{"dc.title", "dc.contributor.author"}); + + Item item10 = ItemBuilder.createItem(context, col) + .withTitle("Compare both title and author") + .withIssueDate(item1IssueDate) + .withAuthor("Surname, F.") + .withSubject(item1Subject) + .build(); + Item item11 = ItemBuilder.createItem(context, col) + .withTitle("Compare both title and author") + .withIssueDate("2012-10-17") + .withAuthor("Surname, F.") + .withSubject("ExtraEntry 2") + .build(); + + Item item12 = ItemBuilder.createItem(context, col) + .withTitle("Compare both title and author") + .withIssueDate("2012-10-17") + .withAuthor("Lastname, First.") + .withSubject("ExtraEntry 2") + .build(); + + // Get potential duplicates of item 10 and make sure no exceptions are thrown + List potentialDuplicates = new ArrayList<>(); + try { + potentialDuplicates = duplicateDetectionService.getPotentialDuplicates(context, item10); + } catch (SearchServiceException e) { + fail("Duplicate search with title and author (" + + e.getMessage() + ")"); + } + + // Make sure result list is size 1 + int size = 1; + assertEquals("Potential duplicates of item10 (title + author) should have size " + size, + size, potentialDuplicates.size()); + + // The only member should be item 11 since item 12 has a different author (but hte same title + assertEquals("Item 11 should be be the detected duplicate", + item11.getID(), potentialDuplicates.get(0).getUuid()); + + } + +} 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..6bc79cad558b 100644 --- a/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java +++ b/dspace-api/src/test/java/org/dspace/discovery/DiscoveryIT.java @@ -19,8 +19,8 @@ import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; diff --git a/dspace-api/src/test/java/org/dspace/eperson/EPersonInWorkflowIT.java b/dspace-api/src/test/java/org/dspace/eperson/EPersonInWorkflowIT.java index 0aa549e8c829..5d7ed53fa0b0 100644 --- a/dspace-api/src/test/java/org/dspace/eperson/EPersonInWorkflowIT.java +++ b/dspace-api/src/test/java/org/dspace/eperson/EPersonInWorkflowIT.java @@ -15,8 +15,8 @@ import java.sql.SQLException; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.AbstractIntegrationTestWithDatabase; diff --git a/dspace-api/src/test/java/org/dspace/eperson/EPersonTest.java b/dspace-api/src/test/java/org/dspace/eperson/EPersonTest.java index 3780afcf6393..4439e39e70b1 100644 --- a/dspace-api/src/test/java/org/dspace/eperson/EPersonTest.java +++ b/dspace-api/src/test/java/org/dspace/eperson/EPersonTest.java @@ -21,8 +21,8 @@ import java.util.Iterator; import java.util.List; import java.util.Set; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import org.apache.commons.codec.DecoderException; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; diff --git a/dspace-api/src/test/java/org/dspace/external/MockOpenaireRestConnector.java b/dspace-api/src/test/java/org/dspace/external/MockOpenaireRestConnector.java index c67402dfdcc6..9e1362e2311f 100644 --- a/dspace-api/src/test/java/org/dspace/external/MockOpenaireRestConnector.java +++ b/dspace-api/src/test/java/org/dspace/external/MockOpenaireRestConnector.java @@ -8,7 +8,6 @@ package org.dspace.external; import java.io.InputStream; -import javax.xml.bind.JAXBException; import eu.openaire.jaxb.helper.OpenAIREHandler; import eu.openaire.jaxb.model.Response; @@ -30,7 +29,7 @@ public MockOpenaireRestConnector(String url) { public Response searchProjectByKeywords(int page, int size, String... keywords) { try { return OpenAIREHandler.unmarshal(this.getClass().getResourceAsStream("openaire-projects.xml")); - } catch (JAXBException e) { + } catch (Exception e) { e.printStackTrace(); } return null; @@ -40,7 +39,7 @@ public Response searchProjectByKeywords(int page, int size, String... keywords) public Response searchProjectByIDAndFunder(String projectID, String projectFunder, int page, int size) { try { return OpenAIREHandler.unmarshal(this.getClass().getResourceAsStream("openaire-project.xml")); - } catch (JAXBException e) { + } catch (Exception e) { e.printStackTrace(); } return null; @@ -50,7 +49,7 @@ public Response searchProjectByIDAndFunder(String projectID, String projectFunde public Response search(String path, int page, int size) { try { return OpenAIREHandler.unmarshal(this.getClass().getResourceAsStream("openaire-no-projects.xml")); - } catch (JAXBException e) { + } catch (Exception e) { e.printStackTrace(); } return null; diff --git a/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidPublicationDataProviderIT.java b/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidPublicationDataProviderIT.java index dae14115b8e0..671fe9467961 100644 --- a/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidPublicationDataProviderIT.java +++ b/dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidPublicationDataProviderIT.java @@ -27,9 +27,9 @@ import java.util.List; import java.util.Optional; import java.util.function.Predicate; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.Unmarshaller; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.Unmarshaller; import org.apache.commons.codec.binary.StringUtils; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; diff --git a/dspace-api/src/test/java/org/dspace/orcid/service/OrcidEntityFactoryServiceIT.java b/dspace-api/src/test/java/org/dspace/orcid/service/OrcidEntityFactoryServiceIT.java index 17bc6ee531c3..912efcfcf323 100644 --- a/dspace-api/src/test/java/org/dspace/orcid/service/OrcidEntityFactoryServiceIT.java +++ b/dspace-api/src/test/java/org/dspace/orcid/service/OrcidEntityFactoryServiceIT.java @@ -274,13 +274,13 @@ private Predicate externalId(String type, String value, Relationship private Predicate contributor(String name, ContributorRole role, SequenceType sequence) { return contributor -> contributor.getCreditName().getContent().equals(name) - && role.equals(contributor.getContributorAttributes().getContributorRole()) + && role.value().equals(contributor.getContributorAttributes().getContributorRole()) && contributor.getContributorAttributes().getContributorSequence() == sequence; } private Predicate fundingContributor(String name, FundingContributorRole role) { return contributor -> contributor.getCreditName().getContent().equals(name) - && role.equals(contributor.getContributorAttributes().getContributorRole()); + && role.value().equals(contributor.getContributorAttributes().getContributorRole()); } private Predicate date(String year, String month, String days) { diff --git a/dspace-api/src/test/java/org/dspace/statistics/export/ITIrusExportUsageEventListener.java b/dspace-api/src/test/java/org/dspace/statistics/export/ITIrusExportUsageEventListener.java index e28e8284a218..0c861a0d293d 100644 --- a/dspace-api/src/test/java/org/dspace/statistics/export/ITIrusExportUsageEventListener.java +++ b/dspace-api/src/test/java/org/dspace/statistics/export/ITIrusExportUsageEventListener.java @@ -21,8 +21,8 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.codec.CharEncoding; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-api/src/test/java/org/dspace/statistics/export/processor/BitstreamEventProcessorIT.java b/dspace-api/src/test/java/org/dspace/statistics/export/processor/BitstreamEventProcessorIT.java index a690b1a1c6ef..7f0866684255 100644 --- a/dspace-api/src/test/java/org/dspace/statistics/export/processor/BitstreamEventProcessorIT.java +++ b/dspace-api/src/test/java/org/dspace/statistics/export/processor/BitstreamEventProcessorIT.java @@ -15,8 +15,8 @@ import java.io.FileInputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.codec.CharEncoding; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.BitstreamBuilder; diff --git a/dspace-api/src/test/java/org/dspace/statistics/export/processor/ExportEventProcessorIT.java b/dspace-api/src/test/java/org/dspace/statistics/export/processor/ExportEventProcessorIT.java index e42003e4fc8b..fb53d0c83c54 100644 --- a/dspace-api/src/test/java/org/dspace/statistics/export/processor/ExportEventProcessorIT.java +++ b/dspace-api/src/test/java/org/dspace/statistics/export/processor/ExportEventProcessorIT.java @@ -18,8 +18,8 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.codec.CharEncoding; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; diff --git a/dspace-api/src/test/java/org/dspace/statistics/util/DummyHttpServletRequest.java b/dspace-api/src/test/java/org/dspace/statistics/util/DummyHttpServletRequest.java index 61325c652cc1..0059ce4f3fae 100644 --- a/dspace-api/src/test/java/org/dspace/statistics/util/DummyHttpServletRequest.java +++ b/dspace-api/src/test/java/org/dspace/statistics/util/DummyHttpServletRequest.java @@ -19,21 +19,22 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import javax.servlet.AsyncContext; -import javax.servlet.DispatcherType; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; +import jakarta.servlet.AsyncContext; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletConnection; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.http.HttpUpgradeHandler; +import jakarta.servlet.http.Part; import org.apache.commons.collections.CollectionUtils; import org.dspace.core.Utils; @@ -64,7 +65,7 @@ public void setRemoteHost(String host) { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#changeSessionId + * @see jakarta.servlet.http.HttpServletRequest#changeSessionId */ @Override public String changeSessionId() { @@ -73,7 +74,7 @@ public String changeSessionId() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getAuthType() + * @see jakarta.servlet.http.HttpServletRequest#getAuthType() */ @Override public String getAuthType() { @@ -82,7 +83,7 @@ public String getAuthType() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getContextPath() + * @see jakarta.servlet.http.HttpServletRequest#getContextPath() */ @Override public String getContextPath() { @@ -91,7 +92,7 @@ public String getContextPath() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getCookies() + * @see jakarta.servlet.http.HttpServletRequest#getCookies() */ @Override public Cookie[] getCookies() { @@ -100,7 +101,7 @@ public Cookie[] getCookies() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String) + * @see jakarta.servlet.http.HttpServletRequest#getDateHeader(java.lang.String) */ @Override public long getDateHeader(String arg0) { @@ -118,7 +119,7 @@ public void addHeader(String headerName, String headerValue) { values.add(headerValue); } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getDispatcherType() + * @see jakarta.servlet.http.HttpServletRequest#getDispatcherType() */ @Override public DispatcherType getDispatcherType() { @@ -127,7 +128,31 @@ public DispatcherType getDispatcherType() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String) + * @see jakarta.servlet.http.HttpServletRequest#getRequestId() + */ + @Override + public String getRequestId() { + return null; + } + + /* (non-Javadoc) + * @see jakarta.servlet.http.HttpServletRequest#getProtocolRequestId() + */ + @Override + public String getProtocolRequestId() { + return null; + } + + /* (non-Javadoc) + * @see jakarta.servlet.http.HttpServletRequest#getServletConnection() + */ + @Override + public ServletConnection getServletConnection() { + return null; + } + + /* (non-Javadoc) + * @see jakarta.servlet.http.HttpServletRequest#getHeader(java.lang.String) */ @Override public String getHeader(String key) { @@ -139,7 +164,7 @@ public String getHeader(String key) { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getHeaderNames() + * @see jakarta.servlet.http.HttpServletRequest#getHeaderNames() */ @Override public Enumeration getHeaderNames() { @@ -147,7 +172,7 @@ public Enumeration getHeaderNames() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String) + * @see jakarta.servlet.http.HttpServletRequest#getHeaders(java.lang.String) */ @Override public Enumeration getHeaders(String arg0) { @@ -155,7 +180,7 @@ public Enumeration getHeaders(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String) + * @see jakarta.servlet.http.HttpServletRequest#getIntHeader(java.lang.String) */ @Override public int getIntHeader(String arg0) { @@ -163,7 +188,7 @@ public int getIntHeader(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getMethod() + * @see jakarta.servlet.http.HttpServletRequest#getMethod() */ @Override public String getMethod() { @@ -172,7 +197,7 @@ public String getMethod() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getPathInfo() + * @see jakarta.servlet.http.HttpServletRequest#getPathInfo() */ @Override public String getPathInfo() { @@ -181,7 +206,7 @@ public String getPathInfo() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getPathTranslated() + * @see jakarta.servlet.http.HttpServletRequest#getPathTranslated() */ @Override public String getPathTranslated() { @@ -190,7 +215,7 @@ public String getPathTranslated() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getQueryString() + * @see jakarta.servlet.http.HttpServletRequest#getQueryString() */ @Override public String getQueryString() { @@ -199,7 +224,7 @@ public String getQueryString() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getRemoteUser() + * @see jakarta.servlet.http.HttpServletRequest#getRemoteUser() */ @Override public String getRemoteUser() { @@ -208,7 +233,7 @@ public String getRemoteUser() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getRequestURI() + * @see jakarta.servlet.http.HttpServletRequest#getRequestURI() */ @Override public String getRequestURI() { @@ -217,7 +242,7 @@ public String getRequestURI() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getRequestURL() + * @see jakarta.servlet.http.HttpServletRequest#getRequestURL() */ @Override public StringBuffer getRequestURL() { @@ -226,7 +251,7 @@ public StringBuffer getRequestURL() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId() + * @see jakarta.servlet.http.HttpServletRequest#getRequestedSessionId() */ @Override public String getRequestedSessionId() { @@ -235,7 +260,7 @@ public String getRequestedSessionId() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getServletPath() + * @see jakarta.servlet.http.HttpServletRequest#getServletPath() */ @Override public String getServletPath() { @@ -244,7 +269,7 @@ public String getServletPath() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getSession() + * @see jakarta.servlet.http.HttpServletRequest#getSession() */ @Override public HttpSession getSession() { @@ -253,7 +278,7 @@ public HttpSession getSession() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getSession(boolean) + * @see jakarta.servlet.http.HttpServletRequest#getSession(boolean) */ @Override public HttpSession getSession(boolean arg0) { @@ -262,7 +287,7 @@ public HttpSession getSession(boolean arg0) { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getUserPrincipal() + * @see jakarta.servlet.http.HttpServletRequest#getUserPrincipal() */ @Override public Principal getUserPrincipal() { @@ -271,7 +296,7 @@ public Principal getUserPrincipal() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie() + * @see jakarta.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie() */ @Override public boolean isRequestedSessionIdFromCookie() { @@ -280,7 +305,7 @@ public boolean isRequestedSessionIdFromCookie() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL() + * @see jakarta.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL() */ @Override public boolean isRequestedSessionIdFromURL() { @@ -289,17 +314,7 @@ public boolean isRequestedSessionIdFromURL() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl() - */ - @Override - @Deprecated - public boolean isRequestedSessionIdFromUrl() { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#authenticate(javax.servlet.http.HttpServletResponse) + * @see jakarta.servlet.http.HttpServletRequest#authenticate(jakarta.servlet.http.HttpServletResponse) */ @Override public boolean authenticate(HttpServletResponse httpServletResponse) { @@ -307,7 +322,7 @@ public boolean authenticate(HttpServletResponse httpServletResponse) { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#login(java.lang.String,java.lang.String) + * @see jakarta.servlet.http.HttpServletRequest#login(java.lang.String,java.lang.String) */ @Override public void login(String s, String s1) { @@ -315,7 +330,7 @@ public void login(String s, String s1) { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#logout() + * @see jakarta.servlet.http.HttpServletRequest#logout() */ @Override public void logout() { @@ -323,7 +338,7 @@ public void logout() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getPart(java.lang.String) + * @see jakarta.servlet.http.HttpServletRequest#getPart(java.lang.String) */ @Override public Part getPart(String arg0) { @@ -332,7 +347,7 @@ public Part getPart(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#getParts() + * @see jakarta.servlet.http.HttpServletRequest#getParts() */ @Override public Collection getParts() { @@ -340,7 +355,7 @@ public Collection getParts() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#upgrade(java.lang.Class) + * @see jakarta.servlet.http.HttpServletRequest#upgrade(java.lang.Class) */ @Override public T upgrade(Class aClass) throws IOException, ServletException { @@ -348,7 +363,7 @@ public T upgrade(Class aClass) throws IOExcept } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid() + * @see jakarta.servlet.http.HttpServletRequest#isRequestedSessionIdValid() */ @Override public boolean isRequestedSessionIdValid() { @@ -357,7 +372,7 @@ public boolean isRequestedSessionIdValid() { } /* (non-Javadoc) - * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String) + * @see jakarta.servlet.http.HttpServletRequest#isUserInRole(java.lang.String) */ @Override public boolean isUserInRole(String arg0) { @@ -366,7 +381,7 @@ public boolean isUserInRole(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getAttribute(java.lang.String) + * @see jakarta.servlet.ServletRequest#getAttribute(java.lang.String) */ @Override public Object getAttribute(String arg0) { @@ -375,7 +390,7 @@ public Object getAttribute(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getAttributeNames() + * @see jakarta.servlet.ServletRequest#getAttributeNames() */ @Override public Enumeration getAttributeNames() { @@ -384,7 +399,7 @@ public Enumeration getAttributeNames() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getCharacterEncoding() + * @see jakarta.servlet.ServletRequest#getCharacterEncoding() */ @Override public String getCharacterEncoding() { @@ -393,7 +408,7 @@ public String getCharacterEncoding() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getContentLength() + * @see jakarta.servlet.ServletRequest#getContentLength() */ @Override public int getContentLength() { @@ -402,7 +417,7 @@ public int getContentLength() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getContentLengthLong() + * @see jakarta.servlet.ServletRequest#getContentLengthLong() */ @Override public long getContentLengthLong() { @@ -410,7 +425,7 @@ public long getContentLengthLong() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getContentType() + * @see jakarta.servlet.ServletRequest#getContentType() */ @Override public String getContentType() { @@ -419,7 +434,7 @@ public String getContentType() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getInputStream() + * @see jakarta.servlet.ServletRequest#getInputStream() */ @Override public ServletInputStream getInputStream() throws IOException { @@ -428,7 +443,7 @@ public ServletInputStream getInputStream() throws IOException { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getLocale() + * @see jakarta.servlet.ServletRequest#getLocale() */ @Override public Locale getLocale() { @@ -437,7 +452,7 @@ public Locale getLocale() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getLocales() + * @see jakarta.servlet.ServletRequest#getLocales() */ @Override public Enumeration getLocales() { @@ -446,7 +461,7 @@ public Enumeration getLocales() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getParameter(java.lang.String) + * @see jakarta.servlet.ServletRequest#getParameter(java.lang.String) */ @Override public String getParameter(String arg0) { @@ -455,7 +470,7 @@ public String getParameter(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getParameterMap() + * @see jakarta.servlet.ServletRequest#getParameterMap() */ @Override public Map getParameterMap() { @@ -464,7 +479,7 @@ public Map getParameterMap() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getParameterNames() + * @see jakarta.servlet.ServletRequest#getParameterNames() */ @Override public Enumeration getParameterNames() { @@ -473,7 +488,7 @@ public Enumeration getParameterNames() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String) + * @see jakarta.servlet.ServletRequest#getParameterValues(java.lang.String) */ @Override public String[] getParameterValues(String arg0) { @@ -482,7 +497,7 @@ public String[] getParameterValues(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getProtocol() + * @see jakarta.servlet.ServletRequest#getProtocol() */ @Override public String getProtocol() { @@ -491,7 +506,7 @@ public String getProtocol() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getReader() + * @see jakarta.servlet.ServletRequest#getReader() */ @Override public BufferedReader getReader() throws IOException { @@ -500,17 +515,7 @@ public BufferedReader getReader() throws IOException { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getRealPath(java.lang.String) - */ - @Override - @Deprecated - public String getRealPath(String arg0) { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getRemoteAddr() + * @see jakarta.servlet.ServletRequest#getRemoteAddr() */ @Override public String getRemoteAddr() { @@ -518,7 +523,7 @@ public String getRemoteAddr() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getRemoteHost() + * @see jakarta.servlet.ServletRequest#getRemoteHost() */ @Override public String getRemoteHost() { @@ -526,7 +531,7 @@ public String getRemoteHost() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String) + * @see jakarta.servlet.ServletRequest#getRequestDispatcher(java.lang.String) */ @Override public RequestDispatcher getRequestDispatcher(String arg0) { @@ -535,7 +540,7 @@ public RequestDispatcher getRequestDispatcher(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getScheme() + * @see jakarta.servlet.ServletRequest#getScheme() */ @Override public String getScheme() { @@ -544,7 +549,7 @@ public String getScheme() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getServerName() + * @see jakarta.servlet.ServletRequest#getServerName() */ @Override public String getServerName() { @@ -553,7 +558,7 @@ public String getServerName() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getServerPort() + * @see jakarta.servlet.ServletRequest#getServerPort() */ @Override public int getServerPort() { @@ -562,7 +567,7 @@ public int getServerPort() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#isSecure() + * @see jakarta.servlet.ServletRequest#isSecure() */ @Override public boolean isSecure() { @@ -571,7 +576,7 @@ public boolean isSecure() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String) + * @see jakarta.servlet.ServletRequest#removeAttribute(java.lang.String) */ @Override public void removeAttribute(String arg0) { @@ -579,7 +584,7 @@ public void removeAttribute(String arg0) { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object) + * @see jakarta.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object) */ @Override public void setAttribute(String arg0, Object arg1) { @@ -587,7 +592,7 @@ public void setAttribute(String arg0, Object arg1) { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String) + * @see jakarta.servlet.ServletRequest#setCharacterEncoding(java.lang.String) */ @Override public void setCharacterEncoding(String arg0) @@ -596,7 +601,7 @@ public void setCharacterEncoding(String arg0) } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#startAsync + * @see jakarta.servlet.ServletRequest#startAsync */ @Override public AsyncContext startAsync() throws IllegalStateException { @@ -604,7 +609,7 @@ public AsyncContext startAsync() throws IllegalStateException { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#startAsync(javax.servlet.ServletRequest,javax.servlet.ServletResponse) + * @see jakarta.servlet.ServletRequest#startAsync(jakarta.servlet.ServletRequest,jakarta.servlet.ServletResponse) */ @Override public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) @@ -613,7 +618,7 @@ public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse se } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#isAsyncStarted + * @see jakarta.servlet.ServletRequest#isAsyncStarted */ @Override public boolean isAsyncStarted() { @@ -621,7 +626,7 @@ public boolean isAsyncStarted() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#isAsyncSupported + * @see jakarta.servlet.ServletRequest#isAsyncSupported */ @Override public boolean isAsyncSupported() { @@ -629,7 +634,7 @@ public boolean isAsyncSupported() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getAsyncContext + * @see jakarta.servlet.ServletRequest#getAsyncContext */ @Override public AsyncContext getAsyncContext() { @@ -657,7 +662,7 @@ public int getLocalPort() { } /* (non-Javadoc) - * @see javax.servlet.ServletRequest#getServletContext + * @see jakarta.servlet.ServletRequest#getServletContext */ @Override public ServletContext getServletContext() { diff --git a/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorServiceImplTest.java b/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorServiceImplTest.java index 24f8c0f124be..0b311a3115dd 100644 --- a/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorServiceImplTest.java @@ -94,7 +94,7 @@ public void testCaseInsensitiveMatching() throws Exception { /** * Test method for - * {@link org.dspace.statistics.util.SpiderDetectorService#isSpider(javax.servlet.http.HttpServletRequest)}. + * {@link org.dspace.statistics.util.SpiderDetectorService#isSpider(jakarta.servlet.http.HttpServletRequest)}. */ @Test public void testIsSpiderHttpServletRequest() { diff --git a/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorTest.java b/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorTest.java index 63046b32b6d4..ba638e4ed796 100644 --- a/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorTest.java +++ b/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorTest.java @@ -49,7 +49,7 @@ public void testGetSpiderIpAddresses() { /** * Test method for - * {@link org.dspace.statistics.util.SpiderDetector#isSpider(javax.servlet.http.HttpServletRequest)}. + * {@link org.dspace.statistics.util.SpiderDetector#isSpider(jakarta.servlet.http.HttpServletRequest)}. */ @Test public void testIsSpiderHttpServletRequest() { diff --git a/dspace-api/src/test/java/org/dspace/util/DSpaceH2Dialect.java b/dspace-api/src/test/java/org/dspace/util/DSpaceH2Dialect.java index 9df86c0218de..cd37a6fb31d9 100644 --- a/dspace-api/src/test/java/org/dspace/util/DSpaceH2Dialect.java +++ b/dspace-api/src/test/java/org/dspace/util/DSpaceH2Dialect.java @@ -11,8 +11,9 @@ import java.util.Map; import java.util.regex.Pattern; +import org.hibernate.boot.model.FunctionContributions; import org.hibernate.dialect.H2Dialect; -import org.hibernate.dialect.function.SQLFunctionTemplate; +import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.StandardBasicTypes; /** @@ -23,8 +24,16 @@ public class DSpaceH2Dialect extends H2Dialect { private static Map regexCache = new HashMap<>(); - public DSpaceH2Dialect() { - registerFunction("matches", new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "matches(?1, ?2)")); + @Override + public void initializeFunctionRegistry(FunctionContributions functionContributions) { + super.initializeFunctionRegistry(functionContributions); + + BasicTypeRegistry basicTypeRegistry = functionContributions.getTypeConfiguration().getBasicTypeRegistry(); + + functionContributions.getFunctionRegistry().registerPattern( + "matches", + "matches(?1, ?2)", + basicTypeRegistry.resolve(StandardBasicTypes.BOOLEAN)); // The SQL function is registered in AbstractIntegrationTestWithDatabase.initDatabase(). } diff --git a/dspace-api/src/test/java/org/dspace/workflow/CurationTaskConfigTest.java b/dspace-api/src/test/java/org/dspace/workflow/CurationTaskConfigTest.java index 92d6ff91481b..61a283c89ef2 100644 --- a/dspace-api/src/test/java/org/dspace/workflow/CurationTaskConfigTest.java +++ b/dspace-api/src/test/java/org/dspace/workflow/CurationTaskConfigTest.java @@ -16,8 +16,8 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; -import javax.xml.bind.JAXBException; +import jakarta.xml.bind.JAXBException; import org.junit.BeforeClass; import org.junit.Test; import org.xml.sax.SAXException; diff --git a/dspace-api/src/test/java/org/dspace/workflow/WorkflowCurationIT.java b/dspace-api/src/test/java/org/dspace/workflow/WorkflowCurationIT.java index 66dd2cee807f..d3866d534b24 100644 --- a/dspace-api/src/test/java/org/dspace/workflow/WorkflowCurationIT.java +++ b/dspace-api/src/test/java/org/dspace/workflow/WorkflowCurationIT.java @@ -11,8 +11,8 @@ import java.util.List; import java.util.regex.Pattern; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; diff --git a/dspace-api/src/test/java/org/dspace/xmlworkflow/XmlWorkflowServiceIT.java b/dspace-api/src/test/java/org/dspace/xmlworkflow/XmlWorkflowServiceIT.java index 865abaca2152..20fd0cde26b8 100644 --- a/dspace-api/src/test/java/org/dspace/xmlworkflow/XmlWorkflowServiceIT.java +++ b/dspace-api/src/test/java/org/dspace/xmlworkflow/XmlWorkflowServiceIT.java @@ -12,8 +12,8 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; diff --git a/dspace-api/src/test/java/org/dspace/xmlworkflow/state/actions/processingaction/NoAction.java b/dspace-api/src/test/java/org/dspace/xmlworkflow/state/actions/processingaction/NoAction.java index ae387c97495b..f5e4521fcdc5 100644 --- a/dspace-api/src/test/java/org/dspace/xmlworkflow/state/actions/processingaction/NoAction.java +++ b/dspace-api/src/test/java/org/dspace/xmlworkflow/state/actions/processingaction/NoAction.java @@ -11,8 +11,8 @@ import java.sql.SQLException; import java.util.Collections; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; import org.dspace.workflow.WorkflowException; diff --git a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/AnnotationGenerator.java b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/AnnotationGenerator.java index 3947df35337f..f6d7aa8950bb 100644 --- a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/AnnotationGenerator.java +++ b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/AnnotationGenerator.java @@ -9,11 +9,11 @@ import java.util.ArrayList; import java.util.List; -import javax.validation.constraints.NotNull; import de.digitalcollections.iiif.model.Motivation; import de.digitalcollections.iiif.model.openannotation.Annotation; import de.digitalcollections.iiif.model.sharedcanvas.Resource; +import jakarta.validation.constraints.NotNull; /** diff --git a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/AnnotationListGenerator.java b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/AnnotationListGenerator.java index da977a5ccc0d..924cf48a9f57 100644 --- a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/AnnotationListGenerator.java +++ b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/AnnotationListGenerator.java @@ -9,11 +9,11 @@ import java.util.ArrayList; import java.util.List; -import javax.validation.constraints.NotNull; import de.digitalcollections.iiif.model.openannotation.Annotation; import de.digitalcollections.iiif.model.sharedcanvas.AnnotationList; import de.digitalcollections.iiif.model.sharedcanvas.Resource; +import jakarta.validation.constraints.NotNull; import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.RequestScope; diff --git a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/CanvasGenerator.java b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/CanvasGenerator.java index f064a1b974ce..701a79aa4bba 100644 --- a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/CanvasGenerator.java +++ b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/CanvasGenerator.java @@ -9,12 +9,12 @@ import java.util.ArrayList; import java.util.List; -import javax.validation.constraints.NotNull; import de.digitalcollections.iiif.model.ImageContent; import de.digitalcollections.iiif.model.MetadataEntry; import de.digitalcollections.iiif.model.sharedcanvas.Canvas; import de.digitalcollections.iiif.model.sharedcanvas.Resource; +import jakarta.validation.constraints.NotNull; /** * This generator wraps the domain model for a single {@code Canvas}. diff --git a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ContentSearchGenerator.java b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ContentSearchGenerator.java index 28cc13c07d36..80af636d3589 100644 --- a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ContentSearchGenerator.java +++ b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ContentSearchGenerator.java @@ -10,11 +10,11 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; -import javax.validation.constraints.NotNull; import de.digitalcollections.iiif.model.Profile; import de.digitalcollections.iiif.model.Service; import de.digitalcollections.iiif.model.search.ContentSearchService; +import jakarta.validation.constraints.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.RequestScope; diff --git a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ExternalLinksGenerator.java b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ExternalLinksGenerator.java index 94c18283753c..709983e9c5a8 100644 --- a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ExternalLinksGenerator.java +++ b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ExternalLinksGenerator.java @@ -7,11 +7,10 @@ */ package org.dspace.app.iiif.model.generator; -import javax.validation.constraints.NotNull; - import de.digitalcollections.iiif.model.OtherContent; import de.digitalcollections.iiif.model.PropertyValue; import de.digitalcollections.iiif.model.sharedcanvas.Resource; +import jakarta.validation.constraints.NotNull; /** * This generator wraps the other content domain model. diff --git a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ImageContentGenerator.java b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ImageContentGenerator.java index aef979b6353e..235e7413f606 100644 --- a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ImageContentGenerator.java +++ b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ImageContentGenerator.java @@ -7,10 +7,9 @@ */ package org.dspace.app.iiif.model.generator; -import javax.validation.constraints.NotNull; - import de.digitalcollections.iiif.model.ImageContent; import de.digitalcollections.iiif.model.sharedcanvas.Resource; +import jakarta.validation.constraints.NotNull; /** * This service generator wraps the image content model. diff --git a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ManifestGenerator.java b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ManifestGenerator.java index 807269264088..dd196154ec6c 100644 --- a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ManifestGenerator.java +++ b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/ManifestGenerator.java @@ -10,7 +10,6 @@ import java.net.URI; import java.util.ArrayList; import java.util.List; -import javax.validation.constraints.NotNull; import de.digitalcollections.iiif.model.ImageContent; import de.digitalcollections.iiif.model.MetadataEntry; @@ -22,6 +21,7 @@ import de.digitalcollections.iiif.model.sharedcanvas.Range; import de.digitalcollections.iiif.model.sharedcanvas.Resource; import de.digitalcollections.iiif.model.sharedcanvas.Sequence; +import jakarta.validation.constraints.NotNull; import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.RequestScope; diff --git a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/RangeGenerator.java b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/RangeGenerator.java index fe8acf31c43f..5b022bc91631 100644 --- a/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/RangeGenerator.java +++ b/dspace-iiif/src/main/java/org/dspace/app/iiif/model/generator/RangeGenerator.java @@ -9,12 +9,12 @@ import java.util.ArrayList; import java.util.List; -import javax.validation.constraints.NotNull; import de.digitalcollections.iiif.model.enums.ViewingHint; import de.digitalcollections.iiif.model.sharedcanvas.Canvas; import de.digitalcollections.iiif.model.sharedcanvas.Range; import de.digitalcollections.iiif.model.sharedcanvas.Resource; +import jakarta.validation.constraints.NotNull; import org.dspace.app.iiif.service.RangeService; /** diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index db8b55c79b5d..88f30d7f9fb9 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -118,8 +118,8 @@ - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided 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 806ecf9d07f4..dc4efde880d5 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 @@ -19,7 +19,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * OAI-PMH webapp configuration. Replaces the old web.xml @@ -36,7 +36,7 @@ @Import(BasicConfiguration.class) // Scan for controllers in this package @ComponentScan("org.dspace.xoai.controller") -public class OAIWebConfig extends WebMvcConfigurerAdapter implements JtwigViewResolverConfigurer { +public class OAIWebConfig implements WebMvcConfigurer, JtwigViewResolverConfigurer { // Path where OAI is deployed. Defaults to "oai" // NOTE: deployment on this path is handled by org.dspace.xoai.controller.DSpaceOAIDataProvider diff --git a/dspace-oai/src/main/java/org/dspace/xoai/controller/DSpaceOAIDataProvider.java b/dspace-oai/src/main/java/org/dspace/xoai/controller/DSpaceOAIDataProvider.java index 379f2fa18134..3d826152c6ba 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/controller/DSpaceOAIDataProvider.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/controller/DSpaceOAIDataProvider.java @@ -7,8 +7,8 @@ */ package org.dspace.xoai.controller; +import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static java.util.Arrays.asList; -import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static org.apache.logging.log4j.LogManager.getLogger; import java.io.IOException; @@ -17,9 +17,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import javax.xml.stream.XMLStreamException; import com.lyncode.xoai.dataprovider.OAIDataProvider; @@ -28,6 +25,9 @@ import com.lyncode.xoai.dataprovider.exceptions.InvalidContextException; import com.lyncode.xoai.dataprovider.exceptions.OAIException; import com.lyncode.xoai.dataprovider.exceptions.WritingXmlException; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.Logger; import org.dspace.core.Context; import org.dspace.xoai.services.api.cache.XOAICacheService; diff --git a/dspace-oai/src/main/java/org/dspace/xoai/services/impl/DSpaceEarliestDateResolver.java b/dspace-oai/src/main/java/org/dspace/xoai/services/impl/DSpaceEarliestDateResolver.java index 6c378ff6d101..733c1b67e0c3 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/services/impl/DSpaceEarliestDateResolver.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/services/impl/DSpaceEarliestDateResolver.java @@ -9,8 +9,8 @@ import java.sql.SQLException; import java.util.Date; -import javax.persistence.NoResultException; +import jakarta.persistence.NoResultException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.content.MetadataValue; diff --git a/dspace-oai/src/main/java/org/dspace/xoai/services/impl/DSpaceHandleResolver.java b/dspace-oai/src/main/java/org/dspace/xoai/services/impl/DSpaceHandleResolver.java index 6ed44bdcc233..fdce0a23a6ab 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/services/impl/DSpaceHandleResolver.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/services/impl/DSpaceHandleResolver.java @@ -8,8 +8,8 @@ package org.dspace.xoai.services.impl; import java.sql.SQLException; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.dspace.content.DSpaceObject; import org.dspace.handle.factory.HandleServiceFactory; import org.dspace.handle.service.HandleService; diff --git a/dspace-oai/src/main/java/org/dspace/xoai/services/impl/context/DSpaceContextService.java b/dspace-oai/src/main/java/org/dspace/xoai/services/impl/context/DSpaceContextService.java index 904b7f888539..e86d15a4fa4e 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/services/impl/context/DSpaceContextService.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/services/impl/context/DSpaceContextService.java @@ -7,8 +7,7 @@ */ package org.dspace.xoai.services.impl.context; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.dspace.xoai.services.api.context.ContextService; import org.dspace.xoai.services.api.context.ContextServiceException; diff --git a/dspace-oai/src/main/java/org/dspace/xoai/services/impl/xoai/DSpaceRepositoryConfiguration.java b/dspace-oai/src/main/java/org/dspace/xoai/services/impl/xoai/DSpaceRepositoryConfiguration.java index 2a000f43ea06..8c9841dfb949 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/services/impl/xoai/DSpaceRepositoryConfiguration.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/services/impl/xoai/DSpaceRepositoryConfiguration.java @@ -14,11 +14,11 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import javax.servlet.http.HttpServletRequest; import com.lyncode.xoai.dataprovider.core.DeleteMethod; import com.lyncode.xoai.dataprovider.core.Granularity; import com.lyncode.xoai.dataprovider.services.api.RepositoryConfiguration; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-rdf/pom.xml b/dspace-rdf/pom.xml index f21381eb4ea3..d45cdad81968 100644 --- a/dspace-rdf/pom.xml +++ b/dspace-rdf/pom.xml @@ -71,8 +71,8 @@ - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided diff --git a/dspace-rdf/src/main/java/org/dspace/rdf/providing/DataProviderServlet.java b/dspace-rdf/src/main/java/org/dspace/rdf/providing/DataProviderServlet.java index 007f865fb700..2ebcf5836c8f 100644 --- a/dspace-rdf/src/main/java/org/dspace/rdf/providing/DataProviderServlet.java +++ b/dspace-rdf/src/main/java/org/dspace/rdf/providing/DataProviderServlet.java @@ -11,13 +11,13 @@ import java.io.IOException; import java.io.PrintWriter; import java.sql.SQLException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import com.hp.hpl.jena.rdf.model.Model; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; +import org.apache.jena.rdf.model.Model; import org.apache.logging.log4j.Logger; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; diff --git a/dspace-rdf/src/main/java/org/dspace/rdf/providing/LocalURIRedirectionServlet.java b/dspace-rdf/src/main/java/org/dspace/rdf/providing/LocalURIRedirectionServlet.java index 7224bb9bfb05..d985740f520d 100644 --- a/dspace-rdf/src/main/java/org/dspace/rdf/providing/LocalURIRedirectionServlet.java +++ b/dspace-rdf/src/main/java/org/dspace/rdf/providing/LocalURIRedirectionServlet.java @@ -9,11 +9,11 @@ import java.io.IOException; import java.sql.SQLException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +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.content.DSpaceObject; diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 93faf48da4e9..22f9643381ba 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -213,7 +213,7 @@ - ${agnostic.build.dir}/testing/dspace/ + ${agnostic.build.dir}/testing/dspace true ${agnostic.build.dir}/testing/dspace/solr/ @@ -272,7 +272,7 @@ - ${agnostic.build.dir}/testing/dspace/ + ${agnostic.build.dir}/testing/dspace true ${agnostic.build.dir}/testing/dspace/solr/ @@ -293,6 +293,14 @@ spring-expression ${spring.version} + + + @@ -368,6 +376,13 @@ org.webjars.bowergithub.codeseven toastr 2.1.4 + + + + org.webjars.bowergithub.jquery + jquery-dist + + @@ -389,6 +404,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 @@ -533,6 +570,13 @@ spring-boot-starter-test test + + + org.apache.httpcomponents.client5 + httpclient5 + 5.3.1 + test + org.springframework.security spring-security-test @@ -574,6 +618,13 @@ solr-core ${solr.client.version} test + + + + org.antlr + antlr4-runtime + + org.apache.lucene @@ -597,8 +648,8 @@ test - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api 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 6faade104e18..070f3d8a1868 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 @@ -14,9 +14,9 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.converter.EPersonConverter; import org.dspace.app.rest.link.HalLinkService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamBundleController.java index 38fb4f4150ad..a26087b49cfe 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamBundleController.java @@ -14,9 +14,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.link.HalLinkService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamCategoryRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamCategoryRestController.java index aa511bcb9282..81968269fac6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamCategoryRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamCategoryRestController.java @@ -10,9 +10,9 @@ import static org.dspace.app.rest.utils.ContextUtil.obtainContext; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.repository.BitstreamRestRepository; import org.dspace.authorize.AuthorizeException; 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 9b5ede37c85f..9d9a5018f890 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 @@ -15,10 +15,10 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.Response; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.ws.rs.core.Response; import org.apache.catalina.connector.ClientAbortException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index 0cb6bc47e033..d86c54e4fccc 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -13,8 +13,8 @@ import java.io.InputStream; import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.converter.ConverterService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionGroupRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionGroupRestController.java index d85685a188b0..6aa6f7537895 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionGroupRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionGroupRestController.java @@ -13,9 +13,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.exception.UnprocessableEntityException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionHarvestSettingsController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionHarvestSettingsController.java index 856804808c46..2ff1a851932b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionHarvestSettingsController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionHarvestSettingsController.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.converter.HarvestedCollectionConverter; import org.dspace.app.rest.link.HalLinkService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionItemTemplateController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionItemTemplateController.java index 6a0890fabc44..66a3965d869e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionItemTemplateController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionItemTemplateController.java @@ -12,11 +12,11 @@ import java.io.IOException; import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.BadRequestException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.BadRequestException; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.CollectionRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionLogoController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionLogoController.java index 9c69043bb983..7d0535858f1e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionLogoController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionLogoController.java @@ -12,8 +12,8 @@ import java.io.IOException; import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.CollectionRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityAdminGroupRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityAdminGroupRestController.java index 2265ac941e6b..77c5d96295a2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityAdminGroupRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityAdminGroupRestController.java @@ -12,9 +12,9 @@ import java.io.IOException; import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.GroupRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityLogoController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityLogoController.java index e1efffb19030..72bfc0e5bc64 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityLogoController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityLogoController.java @@ -12,8 +12,8 @@ import java.io.IOException; import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.CommunityRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ContentReportRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ContentReportRestController.java index dd4196f8910e..c3df859e955e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ContentReportRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ContentReportRestController.java @@ -15,9 +15,9 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +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.converter.ConverterService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CsrfRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CsrfRestController.java new file mode 100644 index 000000000000..7f94b22cfea5 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CsrfRestController.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.app.rest; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.rest.webmvc.ControllerUtils; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.CsrfTokenRepository; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Define GET /api/security/csrf endpoint which may be used to obtain a CSRF token from Spring Security. + * This is useful to force a CSRF token to be generated prior to a POST/PUT/PATCH request that requires it. + *

+ * NOTE: This endpoint should be used sparingly to ensure clients are NOT performing two requests for every modifying + * request (e.g. a GET /csrf followed by a POST/PUT/PATCH to another endpoint). Ideally, calling this endpoint is only + * necessary BEFORE the first POST/PUT/PATCH (if a CSRF token has not yet been obtained), or in scenarios where the + * client must *force* the CSRF token to be reloaded. + */ +@RequestMapping(value = "/api/security") +@RestController +public class CsrfRestController { + + @Lazy + @Autowired + CsrfTokenRepository csrfTokenRepository; + + /** + * Return the current CSRF token as defined by Spring Security. + * Inspired by + * https://docs.spring.io/spring-security/reference/5.8/migration/servlet/exploits.html#_i_am_using_a_single_page_application_with_httpsessioncsrftokenrepository + * @param request HTTP Request + * @param response HTTP response + * @param csrfToken injected CsrfToken by Spring Security + * @return An empty response with CSRF in header & cookie + */ + @GetMapping("/csrf") + @PreAuthorize("permitAll()") + public ResponseEntity> getCsrf(HttpServletRequest request, + HttpServletResponse response, + CsrfToken csrfToken) { + // Save the CSRF token to our response using the currently enabled CsrfTokenRepository + csrfTokenRepository.saveToken(csrfToken, request, response); + + // Return a 204 No Content status + return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT); + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/EntityTypeLabelRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/EntityTypeLabelRestController.java index 9880f21ab915..93658848b08e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/EntityTypeLabelRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/EntityTypeLabelRestController.java @@ -8,9 +8,9 @@ package org.dspace.app.rest; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.model.EntityTypeRest; import org.dspace.app.rest.model.hateoas.EntityTypeResource; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/GroupRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/GroupRestController.java index f644863e03f3..4ad2834cbcf5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/GroupRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/GroupRestController.java @@ -23,9 +23,9 @@ import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.utils.Utils; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/HarvesterMetadataController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/HarvesterMetadataController.java index dad1a2eb7511..a40629cae5a4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/HarvesterMetadataController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/HarvesterMetadataController.java @@ -9,9 +9,9 @@ import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.model.HarvesterMetadataRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index 5175dec5e2e3..fd40b5cafd63 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -12,10 +12,10 @@ import java.io.IOException; import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.converter.MetadataConverter; import org.dspace.app.rest.exception.UnprocessableEntityException; 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 b5a0c957f265..eec5b15825ac 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 @@ -14,9 +14,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemTemplateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemTemplateRestController.java index a6dbf3496e49..5ebc567e600c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemTemplateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemTemplateRestController.java @@ -12,9 +12,9 @@ import java.io.IOException; import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNInboxController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNInboxController.java index 5d18494fc28a..f0ccbcf873c4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNInboxController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNInboxController.java @@ -9,8 +9,8 @@ import java.sql.SQLException; import java.util.regex.Pattern; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.validator.routines.UrlValidator; import org.apache.logging.log4j.Logger; import org.dspace.app.ldn.LDNMessageEntity; @@ -93,7 +93,7 @@ public ResponseEntity options() { */ @ExceptionHandler(ResponseStatusException.class) public ResponseEntity handleResponseStatusException(ResponseStatusException e) { - return ResponseEntity.status(e.getStatus().value()) + return ResponseEntity.status(e.getStatusCode().value()) .body(e.getMessage()); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNMessageRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNMessageRestController.java new file mode 100644 index 000000000000..92335cb5cc1e --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/LDNMessageRestController.java @@ -0,0 +1,94 @@ +/** + * 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; + +import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_URN_UUID; + +import java.sql.SQLException; +import java.util.List; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.app.ldn.service.LDNMessageService; +import org.dspace.app.rest.converter.ConverterService; +import org.dspace.app.rest.model.LDNMessageEntityRest; +import org.dspace.app.rest.utils.ContextUtil; +import org.dspace.app.rest.utils.Utils; +import org.dspace.authorize.AuthorizeException; +import org.dspace.core.Context; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.hateoas.Link; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Rest Controller for requesting the reprocessing of LDNMessageEntity + * + * @author Stefano Maffei (stefano.maffei at 4science.com) + */ +@RestController +@RequestMapping("/api/" + LDNMessageEntityRest.CATEGORY + "/" + + LDNMessageEntityRest.NAME_PLURALS + REGEX_REQUESTMAPPING_IDENTIFIER_AS_URN_UUID + "/enqueueretry") +public class LDNMessageRestController implements InitializingBean { + + private static final Logger log = LogManager.getLogger(LDNMessageRestController.class); + + @Autowired + private ConverterService converterService; + + @Autowired + private LDNMessageService ldnMessageService; + + @Autowired + private Utils utils; + + @Autowired + private DiscoverableEndpointsService discoverableEndpointsService; + + @Override + public void afterPropertiesSet() { + discoverableEndpointsService.register(this, + List.of(Link.of("/api/" + LDNMessageEntityRest.CATEGORY + "/" + + LDNMessageEntityRest.NAME_PLURALS + "/{id}/enqueueretry", + "enqueueretry"))); + } + + @PostMapping(produces = "application/json") + @PreAuthorize("hasAuthority('ADMIN')") + public ResponseEntity findByItem(@PathVariable("id") String id) + throws SQLException, AuthorizeException, JsonProcessingException { + + Context context = ContextUtil.obtainCurrentRequestContext(); + LDNMessageEntity ldnMessageEntity = ldnMessageService.find(context, id); + if (ldnMessageEntity == null) { + throw new ResourceNotFoundException("No such item: " + id); + } + ldnMessageEntity.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_QUEUED_FOR_RETRY); + ldnMessageService.update(context, ldnMessageEntity); + + LDNMessageEntityRest resultRequestStatusRests = converterService.toRest( + ldnMessageEntity, utils.obtainProjection()); + + context.complete(); + String result = new ObjectMapper() + .writerWithDefaultPrettyPrinter().writeValueAsString(resultRequestStatusRests); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java index 14dae21ebec0..6f886096bd30 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java @@ -14,9 +14,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.MethodNotAllowedException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/OidcRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/OidcRestController.java index 0c35b4333860..eaba79d1a8b2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/OidcRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/OidcRestController.java @@ -10,9 +10,9 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletResponse; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; 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 665504139cb3..d10b5ed9f7a5 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 @@ -12,15 +12,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ScopeResolver; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/PrimaryBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/PrimaryBitstreamController.java index c236954dab48..d978752b7d4c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/PrimaryBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/PrimaryBitstreamController.java @@ -12,8 +12,8 @@ import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.BundleRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipRestController.java index 4959d5ac75ee..b9c940f1c107 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipRestController.java @@ -10,9 +10,9 @@ import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.model.RelationshipRest; import org.dspace.app.rest.repository.RelationshipRestRepository; import org.dspace.app.rest.utils.ContextUtil; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyEPersonReplaceRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyEPersonReplaceRestController.java index e772aa0abe18..3311f303ade6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyEPersonReplaceRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyEPersonReplaceRestController.java @@ -15,9 +15,9 @@ import java.sql.SQLException; import java.util.List; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.utils.Utils; import org.dspace.authorize.AuthorizeException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyGroupReplaceRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyGroupReplaceRestController.java index e9ba0dff4429..2a041aba3a0a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyGroupReplaceRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyGroupReplaceRestController.java @@ -15,9 +15,9 @@ import java.sql.SQLException; import java.util.List; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.utils.Utils; import org.dspace.authorize.AuthorizeException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java index f692ba7fd79a..772096e705a5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java @@ -23,11 +23,11 @@ import java.util.List; import java.util.Optional; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; @@ -55,6 +55,7 @@ import org.dspace.app.rest.utils.Utils; import org.dspace.authorize.AuthorizeException; import org.dspace.util.UUIDUtils; +import org.springframework.aop.AopInvocationException; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; @@ -219,8 +220,10 @@ private HALResource findOneInter Optional modelObject = Optional.empty(); try { modelObject = repository.findById(id); - } catch (ClassCastException e) { - // ignore, as handled below + } catch (ClassCastException | IllegalArgumentException | AopInvocationException e) { + // These exceptions may be thrown if the "id" param above is not valid for DSpaceRestRepository.findById() + // (e.g. passing an Integer param when a UUID is expected, or similar). + // We can safely ignore these exceptions as they simply mean the object was not found (see below). } if (!modelObject.isPresent()) { throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found"); @@ -370,7 +373,8 @@ public RepresentationModel findRel(HttpServletRequest request, HttpServletRespon * @return The relevant ResponseEntity for this request * @throws HttpRequestMethodNotSupportedException If something goes wrong */ - @RequestMapping(method = RequestMethod.POST, consumes = {"application/json", "application/hal+json"}) + @RequestMapping(method = RequestMethod.POST, value = {"", "/"}, + consumes = {"application/json", "application/hal+json"}) public ResponseEntity> post(HttpServletRequest request, @PathVariable String apiCategory, @PathVariable String model, @@ -397,7 +401,7 @@ public ResponseEntity> post(HttpServletRequest request, * @return The relevant ResponseEntity for this request * @throws HttpRequestMethodNotSupportedException If something goes wrong */ - @RequestMapping(method = RequestMethod.POST, consumes = {"text/uri-list"}) + @RequestMapping(method = RequestMethod.POST, value = {"", "/"}, consumes = {"text/uri-list"}) public ResponseEntity> postWithUriListContentType(HttpServletRequest request, @PathVariable String apiCategory, @PathVariable String model) @@ -650,7 +654,7 @@ private ResponseEntity> uploadI * @throws IOException * @throws AuthorizeException */ - @RequestMapping(method = { RequestMethod.POST }, headers = "content-type=multipart/form-data") + @RequestMapping(method = { RequestMethod.POST }, value = {"", "/"}, headers = "content-type=multipart/form-data") public ResponseEntity> upload( HttpServletRequest request, @PathVariable String apiCategory, @@ -961,7 +965,8 @@ private RepresentationModel findRelInternal(HttpServle } /** - * Find all + * Find all via a GET request to the root endpoint. This method will trigger in cases where the called endpoint + * either includes a trailing slash or not. * * @param apiCategory * @param model @@ -969,7 +974,7 @@ private RepresentationModel findRelInternal(HttpServle * @param assembler * @return */ - @RequestMapping(method = RequestMethod.GET) + @RequestMapping(method = RequestMethod.GET, value = {"", "/"}) @SuppressWarnings("unchecked") public PagedModel> findAll(@PathVariable String apiCategory, @PathVariable String model, Pageable page, PagedResourcesAssembler assembler, HttpServletResponse response, diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RootRestResourceController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RootRestResourceController.java index 7cb1854af88a..d6ed84c3d656 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RootRestResourceController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RootRestResourceController.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.model.hateoas.RootResource; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/SitemapRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/SitemapRestController.java index efc79f2a395d..95d0ba772959 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/SitemapRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/SitemapRestController.java @@ -13,9 +13,9 @@ import java.io.InputStream; import java.nio.file.Files; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.catalina.connector.ClientAbortException; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.utils.ContextUtil; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/SubmissionCCLicenseUrlRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/SubmissionCCLicenseUrlRepository.java index d65e569c80e8..6daac9be8cf0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/SubmissionCCLicenseUrlRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/SubmissionCCLicenseUrlRepository.java @@ -10,8 +10,8 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import javax.servlet.ServletRequest; +import jakarta.servlet.ServletRequest; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.exception.DSpaceBadRequestException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/UUIDLookupRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/UUIDLookupRestController.java index 40c0a79b97be..8a35794aa193 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/UUIDLookupRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/UUIDLookupRestController.java @@ -14,9 +14,9 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.converter.ConverterService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/WebApplication.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/WebApplication.java index 3c79cc18636d..4c835d99183c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/WebApplication.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/WebApplication.java @@ -10,8 +10,8 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; -import javax.servlet.Filter; +import jakarta.servlet.Filter; import org.dspace.app.ldn.LDNQueueExtractor; import org.dspace.app.ldn.LDNQueueTimeoutChecker; import org.dspace.app.rest.filter.DSpaceRequestContextFilter; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowDefinitionCollectionsLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowDefinitionCollectionsLinkRepository.java index 53d61216e6e7..549a5ec78e93 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowDefinitionCollectionsLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowDefinitionCollectionsLinkRepository.java @@ -9,9 +9,9 @@ import java.util.ArrayList; import java.util.List; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.WorkflowDefinitionRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowDefinitionStepsLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowDefinitionStepsLinkRepository.java index bf8ac0cf201e..91cb0cffc0f4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowDefinitionStepsLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowDefinitionStepsLinkRepository.java @@ -8,9 +8,9 @@ package org.dspace.app.rest; import java.util.List; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.WorkflowDefinitionRest; import org.dspace.app.rest.model.WorkflowStepRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowStepActionsLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowStepActionsLinkRepository.java index e34b8bb1731b..0740d318a056 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowStepActionsLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/WorkflowStepActionsLinkRepository.java @@ -8,9 +8,9 @@ package org.dspace.app.rest; import java.util.List; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.WorkflowActionRest; import org.dspace.app.rest.model.WorkflowStepRest; import org.dspace.app.rest.projection.Projection; 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 ad78fe2db40b..08a7e9aec8e9 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.SolrHealthIndicator; import org.dspace.authority.AuthoritySolrServiceImpl; import org.dspace.discovery.SolrSearchCore; import org.dspace.statistics.SolrStatisticsCore; @@ -22,7 +23,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.actuate.health.Status; -import org.springframework.boot.actuate.solr.SolrHealthIndicator; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.annotation.Bean; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java index 55ae7b9595a9..abb79d57984c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java @@ -16,9 +16,9 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/JsonPatchConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/JsonPatchConverter.java index aba4d6a99536..89cbc1c2d7d1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/JsonPatchConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/JsonPatchConverter.java @@ -10,13 +10,13 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import javax.annotation.Nonnull; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.annotation.Nonnull; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.CopyOperation; import org.dspace.app.rest.model.patch.FromOperation; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/LDNMessageEntityConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/LDNMessageEntityConverter.java new file mode 100644 index 000000000000..1c0783aec4d9 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/LDNMessageEntityConverter.java @@ -0,0 +1,71 @@ +/** + * 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.converter; + +import java.util.UUID; + +import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.app.ldn.NotifyServiceEntity; +import org.dspace.app.rest.model.LDNMessageEntityRest; +import org.dspace.app.rest.projection.Projection; +import org.dspace.content.DSpaceObject; +import org.dspace.discovery.IndexableObject; +import org.springframework.stereotype.Component; + +/** + * Converter to translate between {@link LDNMessageEntity} and {@link LDNMessageEntityRest} representations. + * @author Stefano Maffei (stefano.maffei at 4science.com) + */ +@Component +public class LDNMessageEntityConverter implements IndexableObjectConverter { + + @Override + public LDNMessageEntityRest convert(LDNMessageEntity obj, Projection projection) { + LDNMessageEntityRest ldnRest = new LDNMessageEntityRest(); + ldnRest.setNotificationId(obj.getID()); + ldnRest.setId(obj.getID()); + ldnRest.setQueueStatus(obj.getQueueStatus()); + ldnRest.setQueueStatusLabel(LDNMessageEntity.getQueueStatus(obj)); + ldnRest.setContext(getObjectIdentifier(obj.getContext())); + ldnRest.setObject(getObjectIdentifier(obj.getObject())); + ldnRest.setActivityStreamType(obj.getActivityStreamType()); + ldnRest.setCoarNotifyType(obj.getCoarNotifyType()); + ldnRest.setTarget(getObjectIdentifier(obj.getTarget())); + ldnRest.setOrigin(getObjectIdentifier(obj.getOrigin())); + ldnRest.setInReplyTo(getObjectIdentifier(obj.getInReplyTo())); + ldnRest.setQueueAttempts(obj.getQueueAttempts()); + ldnRest.setQueueLastStartTime(obj.getQueueLastStartTime()); + ldnRest.setQueueTimeout(obj.getQueueTimeout()); + ldnRest.setMessage(obj.getMessage()); + ldnRest.setNotificationType(LDNMessageEntity.getNotificationType(obj)); + return ldnRest; + } + + private UUID getObjectIdentifier(DSpaceObject dso) { + return dso == null ? null : dso.getID(); + } + + private Integer getObjectIdentifier(NotifyServiceEntity nse) { + return nse == null ? null : nse.getID(); + } + + private String getObjectIdentifier(LDNMessageEntity msg) { + return msg == null ? null : msg.getID(); + } + + @Override + public Class getModelClass() { + return LDNMessageEntity.class; + } + + @Override + public boolean supportsModel(IndexableObject idxo) { + return idxo.getIndexedObject() instanceof LDNMessageEntity; + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/PotentialDuplicateConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/PotentialDuplicateConverter.java new file mode 100644 index 000000000000..8d2814b611e5 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/PotentialDuplicateConverter.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.app.rest.converter; + +import org.dspace.app.rest.model.MetadataValueList; +import org.dspace.app.rest.model.PotentialDuplicateRest; +import org.dspace.app.rest.projection.Projection; +import org.dspace.content.virtual.PotentialDuplicate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * Convert DSpace PotentialDuplicate object to a PotentialDuplicateRest REST resource + * for use in REST results. + * + * @author Kim Shepherd + */ +@Component +public class PotentialDuplicateConverter implements DSpaceConverter { + @Lazy + @Autowired + private ConverterService converter; + + /** + * Convert a PotentialDuplicate model object into its equivalent REST resource, applying + * a given projection. + * @see PotentialDuplicate + * @see PotentialDuplicateRest + * + * @param modelObject a PotentialDuplicate object + * @param projection current projection + * @return a converted PotentialDuplicateRest REST object + */ + @Override + public PotentialDuplicateRest convert(PotentialDuplicate modelObject, Projection projection) { + if (modelObject == null) { + return null; + } + // Instantiate new REST model object + PotentialDuplicateRest rest = new PotentialDuplicateRest(); + // Set or otherwise transform things here, then return + rest.setUuid(modelObject.getUuid()); + rest.setTitle(modelObject.getTitle()); + rest.setOwningCollectionName(modelObject.getOwningCollectionName()); + rest.setWorkflowItemId(modelObject.getWorkflowItemId()); + rest.setWorkspaceItemId(modelObject.getWorkspaceItemId()); + rest.setMetadata(converter.toRest(new MetadataValueList(modelObject.getMetadataValueList()), projection)); + + // Return converted object + return rest; + } + + /** + * For what DSpace API model class does this converter convert? + * @return Class of model objects represented. + */ + @Override + public Class getModelClass() { + return PotentialDuplicate.class; + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/QAEventConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/QAEventConverter.java index b908bf3e41f1..098f4dafb75b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/QAEventConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/QAEventConverter.java @@ -10,12 +10,12 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; -import javax.annotation.PostConstruct; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; +import jakarta.annotation.PostConstruct; import org.dspace.app.rest.model.CorrectionTypeQAEventMessageRest; import org.dspace.app.rest.model.NotifyQAEventMessageRest; import org.dspace.app.rest.model.OpenaireQAEventMessageRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RequestItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RequestItemConverter.java index 27ea4f66305b..e6d6f4da2aee 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RequestItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RequestItemConverter.java @@ -8,8 +8,7 @@ package org.dspace.app.rest.converter; -import javax.inject.Named; - +import jakarta.inject.Named; import org.dspace.app.requestitem.RequestItem; import org.dspace.app.rest.model.RequestItemRest; import org.dspace.app.rest.projection.Projection; 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..e9786962e0f5 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 @@ -11,8 +11,8 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.dspace.app.rest.model.PageRest; import org.dspace.app.rest.model.SearchEventRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionDefinitionConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionDefinitionConverter.java index a84545520463..8e4fd247874c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionDefinitionConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionDefinitionConverter.java @@ -11,8 +11,8 @@ import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.SubmissionDefinitionRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceAccessDeniedHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceAccessDeniedHandler.java index c2842d33d2bc..8df77f424a7d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceAccessDeniedHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceAccessDeniedHandler.java @@ -8,10 +8,10 @@ package org.dspace.app.rest.exception; import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceApiExceptionControllerAdvice.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceApiExceptionControllerAdvice.java index 25e11f69164e..6bfb43297b54 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceApiExceptionControllerAdvice.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/exception/DSpaceApiExceptionControllerAdvice.java @@ -7,7 +7,7 @@ */ package org.dspace.app.rest.exception; -import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; +import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static org.springframework.web.servlet.DispatcherServlet.EXCEPTION_ATTRIBUTE; import java.io.IOException; @@ -15,10 +15,10 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.inject.Inject; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.exception.ResourceAlreadyExistsException; @@ -33,6 +33,7 @@ import org.springframework.data.repository.support.QueryMethodParameterConversionException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.csrf.InvalidCsrfTokenException; @@ -42,7 +43,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.context.request.WebRequest; -import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.multipart.MultipartException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; @@ -98,13 +98,6 @@ protected void handleWrongRequestException(HttpServletRequest request, HttpServl sendErrorResponse(request, response, ex, "Request is invalid or incorrect", HttpServletResponse.SC_BAD_REQUEST); } - @ExceptionHandler(MaxUploadSizeExceededException.class) - protected void handleMaxUploadSizeExceededException(HttpServletRequest request, HttpServletResponse response, - Exception ex) throws IOException { - sendErrorResponse(request, response, ex, "Request entity is too large", - HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE); - } - @ExceptionHandler(SQLException.class) protected void handleSQLException(HttpServletRequest request, HttpServletResponse response, Exception ex) throws IOException { @@ -187,7 +180,7 @@ protected void handleCustomUnprocessableEntityException(HttpServletRequest reque @ExceptionHandler(QueryMethodParameterConversionException.class) protected void ParameterConversionException(HttpServletRequest request, HttpServletResponse response, Exception ex) throws IOException { - // we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428 + // we want the 400 status for missing parameters, see https://github.com/DSpace/DSpace/issues/7765 sendErrorResponse(request, response, ex, "A required parameter is invalid", HttpStatus.BAD_REQUEST.value()); @@ -196,7 +189,7 @@ protected void ParameterConversionException(HttpServletRequest request, HttpServ @ExceptionHandler(MissingParameterException.class) protected void MissingParameterException(HttpServletRequest request, HttpServletResponse response, Exception ex) throws IOException { - // we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428 + // we want the 400 status for missing parameters, see https://github.com/DSpace/DSpace/issues/7765 sendErrorResponse(request, response, ex, "A required parameter is missing", HttpStatus.BAD_REQUEST.value()); @@ -216,16 +209,16 @@ protected void handleInvalidCaptchaTokenRequestException(HttpServletRequest requ @Override protected ResponseEntity handleMissingServletRequestParameter(MissingServletRequestParameterException ex, - HttpHeaders headers, HttpStatus status, + HttpHeaders headers, HttpStatusCode status, WebRequest request) { - // we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428 + // we want the 400 status for missing parameters, see https://github.com/DSpace/DSpace/issues/7765 return super.handleMissingServletRequestParameter(ex, headers, HttpStatus.BAD_REQUEST, request); } @Override protected ResponseEntity handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers, - HttpStatus status, WebRequest request) { - // we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428 + HttpStatusCode status, WebRequest request) { + // we want the 400 status for missing parameters, see https://github.com/DSpace/DSpace/issues/7765 return super.handleTypeMismatch(ex, headers, HttpStatus.BAD_REQUEST, request); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/filter/ContentLanguageHeaderResponseFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/filter/ContentLanguageHeaderResponseFilter.java index 74ffd73ad463..5f45f7edc554 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/filter/ContentLanguageHeaderResponseFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/filter/ContentLanguageHeaderResponseFilter.java @@ -9,14 +9,14 @@ import java.io.IOException; import java.util.Locale; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.core.I18nUtil; import org.springframework.stereotype.Component; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/filter/DSpaceRequestContextFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/filter/DSpaceRequestContextFilter.java index 99e65c199239..59cf70202154 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/filter/DSpaceRequestContextFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/filter/DSpaceRequestContextFilter.java @@ -8,13 +8,13 @@ package org.dspace.app.rest.filter; import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.core.Context; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/hdlresolver/HdlResolverRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/hdlresolver/HdlResolverRestController.java index 540c3fd17243..3fe897e0e5e1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/hdlresolver/HdlResolverRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/hdlresolver/HdlResolverRestController.java @@ -10,10 +10,10 @@ import java.text.MessageFormat; import java.util.List; import java.util.Optional; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SolrHealthIndicator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SolrHealthIndicator.java new file mode 100644 index 000000000000..1d9f4fee24de --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/health/SolrHealthIndicator.java @@ -0,0 +1,123 @@ +/** + * 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.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.impl.BaseHttpSolrClient.RemoteSolrException; +import org.apache.solr.client.solrj.request.CoreAdminRequest; +import org.apache.solr.common.params.CoreAdminParams; +import org.springframework.boot.actuate.health.AbstractHealthIndicator; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.actuate.health.Status; + +/** + * {@link HealthIndicator} for Apache Solr. + * + * This is copied from the 'org.springframework.boot.actuate.solr.SolrHealthIndicator' in Spring Boot v2, + * as that class was removed in Spring Boot v3. See https://github.com/spring-projects/spring-boot/issues/31054 + * + * This HealthIndicator has updated by DSpace to support later versions of Spring Boot and Solr. + */ +public class SolrHealthIndicator extends AbstractHealthIndicator { + + private static final int HTTP_NOT_FOUND_STATUS = 404; + + private final SolrClient solrClient; + + private volatile StatusCheck statusCheck; + + public SolrHealthIndicator(SolrClient solrClient) { + super("Solr health check failed"); + this.solrClient = solrClient; + } + + @Override + protected void doHealthCheck(Health.Builder builder) throws Exception { + int statusCode = initializeStatusCheck(); + Status status = (statusCode != 0) ? Status.DOWN : Status.UP; + builder.status(status).withDetail("status", statusCode).withDetail("detectedPathType", + this.statusCheck.getPathType()); + } + + private int initializeStatusCheck() throws Exception { + StatusCheck statusCheck = this.statusCheck; + if (statusCheck != null) { + // Already initialized + return statusCheck.getStatus(this.solrClient); + } + try { + return initializeStatusCheck(new RootStatusCheck()); + } catch (RemoteSolrException ex) { + // 404 is thrown when SolrClient has a baseUrl pointing to a particular core. + if (ex.code() == HTTP_NOT_FOUND_STATUS) { + return initializeStatusCheck(new ParticularCoreStatusCheck()); + } + throw ex; + } + } + + private int initializeStatusCheck(StatusCheck statusCheck) throws Exception { + int result = statusCheck.getStatus(this.solrClient); + this.statusCheck = statusCheck; + return result; + } + + /** + * Strategy used to perform the status check. + */ + private abstract static class StatusCheck { + + private final String pathType; + + StatusCheck(String pathType) { + this.pathType = pathType; + } + + abstract int getStatus(SolrClient client) throws Exception; + + String getPathType() { + return this.pathType; + } + + } + + /** + * {@link StatusCheck} used when {@code baseUrl} points to the root context. + */ + private static class RootStatusCheck extends StatusCheck { + + RootStatusCheck() { + super("root"); + } + + @Override + public int getStatus(SolrClient client) throws Exception { + CoreAdminRequest request = new CoreAdminRequest(); + request.setAction(CoreAdminParams.CoreAdminAction.STATUS); + return request.process(client).getStatus(); + } + + } + + /** + * {@link StatusCheck} used when {@code baseUrl} points to the particular core. + */ + private static class ParticularCoreStatusCheck extends StatusCheck { + + ParticularCoreStatusCheck() { + super("particular core"); + } + + @Override + public int getStatus(SolrClient client) throws Exception { + return client.ping().getStatus(); + } + + } +} \ No newline at end of file diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/LDNMessageEntityRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/LDNMessageEntityRest.java new file mode 100644 index 000000000000..336f2c63c343 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/LDNMessageEntityRest.java @@ -0,0 +1,200 @@ +/** + * 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.model; + +import java.util.Date; +import java.util.UUID; + +import org.dspace.app.rest.RestResourceController; + +/** + * The LDN Message REST resource. + * @author Stefano Maffei (stefano.maffei at 4science.com) + */ +@SuppressWarnings("serial") +public class LDNMessageEntityRest extends BaseObjectRest { + + public static final String NAME = "message"; + public static final String NAME_PLURALS = "messages"; + public static final String CATEGORY = RestAddressableModel.LDN; + + private String notificationId; + + private Integer queueStatus; + + private String queueStatusLabel; + + private UUID context; + + private UUID object; + + private Integer target; + + private Integer origin; + + private String inReplyTo; + + private String activityStreamType; + + private String coarNotifyType; + + private Integer queueAttempts; + + private Date queueLastStartTime; + + private Date queueTimeout; + + private String notificationType; + + private String message; + + public LDNMessageEntityRest() { + super(); + } + + @Override + public String getType() { + return NAME; + } + + @Override + public String getTypePlural() { + return NAME_PLURALS; + } + + @Override + public String getCategory() { + return CATEGORY; + } + + @Override + public Class getController() { + return RestResourceController.class; + } + + public String getNotificationId() { + return notificationId; + } + + public void setNotificationId(String notificationId) { + this.notificationId = notificationId; + } + + public Integer getQueueStatus() { + return queueStatus; + } + + public void setQueueStatus(Integer queueStatus) { + this.queueStatus = queueStatus; + } + + public String getQueueStatusLabel() { + return queueStatusLabel; + } + + public void setQueueStatusLabel(String queueStatusLabel) { + this.queueStatusLabel = queueStatusLabel; + } + + public UUID getContext() { + return context; + } + + public void setContext(UUID context) { + this.context = context; + } + + public UUID getObject() { + return object; + } + + public void setObject(UUID object) { + this.object = object; + } + + public Integer getTarget() { + return target; + } + + public void setTarget(Integer target) { + this.target = target; + } + + public Integer getOrigin() { + return origin; + } + + public void setOrigin(Integer source) { + this.origin = source; + } + + public String getActivityStreamType() { + return activityStreamType; + } + + public void setActivityStreamType(String activityStreamType) { + this.activityStreamType = activityStreamType; + } + + public String getCoarNotifyType() { + return coarNotifyType; + } + + public void setCoarNotifyType(String coarNotifyType) { + this.coarNotifyType = coarNotifyType; + } + + public Integer getQueueAttempts() { + return queueAttempts; + } + + public void setQueueAttempts(Integer queueAttempts) { + this.queueAttempts = queueAttempts; + } + + public Date getQueueLastStartTime() { + return queueLastStartTime; + } + + public void setQueueLastStartTime(Date queueLastStartTime) { + this.queueLastStartTime = queueLastStartTime; + } + + public Date getQueueTimeout() { + return queueTimeout; + } + + public void setQueueTimeout(Date queueTimeout) { + this.queueTimeout = queueTimeout; + } + + public String getNotificationType() { + return notificationType; + } + + public void setNotificationType(String notificationType) { + this.notificationType = notificationType; + } + + public String getInReplyTo() { + return inReplyTo; + } + + public void setInReplyTo(String inReplyTo) { + this.inReplyTo = inReplyTo; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PotentialDuplicateRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PotentialDuplicateRest.java new file mode 100644 index 000000000000..9d706a8d5791 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PotentialDuplicateRest.java @@ -0,0 +1,199 @@ +/** + * 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.model; + +import java.util.UUID; + +/** + * REST Model defining a Potential Duplicate for serialisation to JSON + * This is used in lists of potential duplicates for submission section data and item link / embeds. + * + * @author Kim Shepherd + */ +public class PotentialDuplicateRest extends RestAddressableModel { + + public static final String CATEGORY = RestModel.SUBMISSION; + public static final String NAME = RestModel.DUPLICATES; + + /** + * Type of REST resource + */ + private static final String TYPE = "DUPLICATE"; + /** + * Plural type of REST resource + */ + private static final String TYPE_PLURAL = "DUPLICATES"; + /** + * Title of duplicate object + */ + private String title; + /** + * UUID of duplicate object + */ + private UUID uuid; + /** + * Owning collection name (title) for duplicate item + */ + private String owningCollectionName; + /** + * Workspace item ID, if the duplicate is a workspace item + */ + private Integer workspaceItemId; + /** + * Workflow item ID, if the duplicate is a workflow item + */ + private Integer workflowItemId; + /** + * List of configured metadata copied across from the duplicate item + */ + private MetadataRest metadata; + + /** + * Default constructor + */ + public PotentialDuplicateRest() { + } + + /** + * Get UUID of duplicate item + * @return UUID of duplicate item + */ + public UUID getUuid() { + return uuid; + } + + /** + * Set UUID of duplicate item + * @param uuid UUID of duplicate item + */ + public void setUuid(UUID uuid) { + this.uuid = uuid; + } + + /** + * Get title of duplicate item + * @return title of duplicate item + */ + public String getTitle() { + return title; + } + + /** + * Set title of duplicate item + * @param title of duplicate item + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * Get owning collection name (title) of duplicate item + * @return owning collection name (title) of duplicate item + */ + public String getOwningCollectionName() { + return owningCollectionName; + } + + /** + * Set owning collection name (title) of duplicate item + * @param owningCollectionName owning collection name (title) of duplicate item + */ + public void setOwningCollectionName(String owningCollectionName) { + this.owningCollectionName = owningCollectionName; + } + + /** + * Get metadata (sorted, field->value list) for duplicate item + * @return (sorted, field->value list) for duplicate item + */ + public MetadataRest getMetadata() { + return metadata; + } + + /** + * Set metadata (sorted, field->value list) for duplicate item + * @param metadata MetadataRest list of values mapped to field keys + */ + public void setMetadata(MetadataRest metadata) { + this.metadata = metadata; + } + + /** + * Get workspace ID for duplicate item, if any + * @return workspace item ID or null + */ + public Integer getWorkspaceItemId() { + return workspaceItemId; + } + + /** + * Set workspace ID for duplicate item + * @param workspaceItemId workspace item ID + */ + public void setWorkspaceItemId(Integer workspaceItemId) { + this.workspaceItemId = workspaceItemId; + } + + /** + * Get workflow ID for duplicate item, if anh + * @return workflow item ID or null + */ + public Integer getWorkflowItemId() { + return workflowItemId; + } + + /** + * Set workflow ID for duplicate item + * @param workflowItemId workspace item ID + */ + public void setWorkflowItemId(Integer workflowItemId) { + this.workflowItemId = workflowItemId; + } + + /** + * Get REST resource type name + * @return REST resource type (see static final string) + */ + @Override + public String getType() { + return TYPE; + } + + /** + * Get REST resource type plural name + * @return REST resource type plural name (see static final string) + */ + @Override + public String getTypePlural() { + return TYPE_PLURAL; + } + + /** + * Get REST resource category. + * Not implemented as this model is intended for use only as an ItemLink repository and submission section data, + * it is actually a simple RestModel but has to 'implement' RestAddressableModel to serialize correctly + * + * @return null (not implemented) + */ + @Override + public String getCategory() { + return null; + } + + /** + * Get REST controller for this model. + * Not implemented as this model is intended for use only as an ItemLink repository and submission section data, + * it is actually a simple RestModel but has to 'implement' RestAddressableModel to serialize correctly + * + * @return null (not implemented) + */ + @Override + public Class getController() { + return null; + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RestModel.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RestModel.java index b575ddb59815..72aae3b25a7e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RestModel.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RestModel.java @@ -24,6 +24,7 @@ public interface RestModel extends Serializable { public static final String CORE = "core"; public static final String EPERSON = "eperson"; public static final String DISCOVER = "discover"; + public static final String DUPLICATES = "duplicates"; public static final String CONFIGURATION = "config"; public static final String INTEGRATION = "integration"; public static final String STATISTICS = "statistics"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/LDNMessageEntityResource.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/LDNMessageEntityResource.java new file mode 100644 index 000000000000..2ac899fa4bb8 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/LDNMessageEntityResource.java @@ -0,0 +1,27 @@ +/** + * 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.model.hateoas; + +import org.dspace.app.rest.model.LDNMessageEntityRest; +import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource; +import org.dspace.app.rest.utils.Utils; + +/** + * Browse Entry Rest HAL Resource. The HAL Resource wraps the REST Resource + * adding support for the links and embedded resources + * + * @author Stefano Maffei (stefano.maffei at 4science.com) + */ +@RelNameDSpaceResource(LDNMessageEntityRest.NAME) +public class LDNMessageEntityResource extends DSpaceResource { + + public LDNMessageEntityResource(LDNMessageEntityRest data, Utils utils) { + super(data, utils); + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/PotentialDuplicateResource.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/PotentialDuplicateResource.java new file mode 100644 index 000000000000..e753126133b4 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/PotentialDuplicateResource.java @@ -0,0 +1,22 @@ +/** + * 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.model.hateoas; + +import org.dspace.app.rest.model.PotentialDuplicateRest; + +/** + * + * Wrap PotentialDuplicatesRest REST resource in a very simple HALResource class + * + * @author Kim Shepherd + */ +public class PotentialDuplicateResource extends HALResource { + public PotentialDuplicateResource(PotentialDuplicateRest data) { + super(data); + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/patch/JsonValueEvaluator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/patch/JsonValueEvaluator.java index 07d488f518e4..67127ccf8fcf 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/patch/JsonValueEvaluator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/patch/JsonValueEvaluator.java @@ -7,10 +7,9 @@ */ package org.dspace.app.rest.model.patch; -import javax.annotation.Nonnull; - import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.Nonnull; import org.springframework.data.rest.webmvc.json.patch.PatchException; /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/step/DataDuplicateDetection.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/step/DataDuplicateDetection.java new file mode 100644 index 000000000000..9506e9676e03 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/step/DataDuplicateDetection.java @@ -0,0 +1,46 @@ +/** + * 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.model.step; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import org.dspace.app.rest.model.PotentialDuplicateRest; + +/** + * Section data model for potential duplicate items detected during submission + * + * @author Kim Shepherd + */ +public class DataDuplicateDetection implements SectionData { + public DataDuplicateDetection() { + } + + /** + * A list of potential duplicate items found by DuplicateDetectionService, in their REST model form + */ + @JsonUnwrapped + private List potentialDuplicates; + + /** + * Return the list of detected potential duplicates in REST model form + * @return list of potential duplicate REST models + */ + public List getPotentialDuplicates() { + return potentialDuplicates; + } + + /** + * Set list of potential duplicates. + * @see org.dspace.app.rest.converter.PotentialDuplicateConverter + * @param potentialDuplicates list of potential duplicates + */ + public void setPotentialDuplicates(List potentialDuplicates) { + this.potentialDuplicates = potentialDuplicates; + } +} \ No newline at end of file diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/projection/Projection.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/projection/Projection.java index 19b67d851d10..42314897a849 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/projection/Projection.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/projection/Projection.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.projection; -import javax.persistence.Entity; - +import jakarta.persistence.Entity; import org.dspace.app.rest.model.LinkRest; import org.dspace.app.rest.model.RestAddressableModel; import org.dspace.app.rest.model.RestModel; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationEpersonLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationEpersonLinkRepository.java index dad973b0f845..ca123d2de84d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationEpersonLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationEpersonLinkRepository.java @@ -8,9 +8,9 @@ package org.dspace.app.rest.repository; import java.sql.SQLException; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.authorization.AuthorizationRestUtil; import org.dspace.app.rest.model.AuthorizationRest; import org.dspace.app.rest.model.EPersonRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureLinkRepository.java index 6bf8b2236791..f450aa61b523 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureLinkRepository.java @@ -7,9 +7,8 @@ */ package org.dspace.app.rest.repository; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; - +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.authorization.AuthorizationFeature; import org.dspace.app.rest.authorization.AuthorizationFeatureService; import org.dspace.app.rest.authorization.AuthorizationRestUtil; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationObjectLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationObjectLinkRepository.java index 5bf7c1b9b6cc..6c9697d4424b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationObjectLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationObjectLinkRepository.java @@ -8,9 +8,9 @@ package org.dspace.app.rest.repository; import java.sql.SQLException; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.authorization.AuthorizationRestUtil; import org.dspace.app.rest.model.AuthorizationRest; import org.dspace.app.rest.model.BaseObjectRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamBundleLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamBundleLinkRepository.java index 17c26174d3f1..a2c3ab95bed5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamBundleLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamBundleLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.BundleRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatLinkRepository.java index 491eb2c34817..d86128c34469 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamFormatRest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java index c4c1981f9d78..1ae8600a5c94 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java @@ -10,11 +10,11 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.BitstreamFormatRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamRestRepository.java index 57a9a03adde6..0350a5178e20 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamRestRepository.java @@ -13,10 +13,10 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; 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.dspace.app.rest.Parameter; import org.dspace.app.rest.SearchRestMethod; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamThumbnailLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamThumbnailLinkRepository.java index 57d5f107e06f..eab0ba19407f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamThumbnailLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamThumbnailLinkRepository.java @@ -10,9 +10,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.projection.Projection; import org.dspace.content.Bitstream; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseEntryLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseEntryLinkRepository.java index cc1fcc9d5d9d..52fcbeecfdd8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseEntryLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseEntryLinkRepository.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.Iterator; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.converter.BrowseEntryConverter; import org.dspace.app.rest.model.BrowseEntryRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseItemLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseItemLinkRepository.java index 6dcf65fd501c..286a3216bf04 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseItemLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseItemLinkRepository.java @@ -11,8 +11,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.model.BrowseIndexRest; import org.dspace.app.rest.model.ItemRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleBitstreamLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleBitstreamLinkRepository.java index 393b49052071..3893ef561b28 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleBitstreamLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleBitstreamLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.BundleRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleItemLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleItemLinkRepository.java index 53dedddfbfc4..d23e9e96e6ef 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleItemLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleItemLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BundleRest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundlePrimaryBitstreamLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundlePrimaryBitstreamLinkRepository.java index f419b0b8aaf3..e6f0e1cd2e42 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundlePrimaryBitstreamLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundlePrimaryBitstreamLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.BitstreamRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java index e12594ddc143..dbc67dd0155b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java @@ -12,9 +12,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskRestRepository.java index a5934833a629..f68cb85c2be1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskRestRepository.java @@ -12,9 +12,9 @@ import java.util.Arrays; import java.util.List; import java.util.UUID; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskStepLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskStepLinkRepository.java index 3093a2ac0c9f..3079d0360923 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskStepLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskStepLinkRepository.java @@ -8,9 +8,9 @@ package org.dspace.app.rest.repository; import java.sql.SQLException; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.ClaimedTaskRest; import org.dspace.app.rest.model.WorkflowStepRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionAdminGroupLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionAdminGroupLinkRepository.java index 0ce8aa82e307..22a6c31f1e94 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionAdminGroupLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionAdminGroupLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionBitstreamReadGroupLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionBitstreamReadGroupLinkRepository.java index 55cacf3e33f7..f96af09cb958 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionBitstreamReadGroupLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionBitstreamReadGroupLinkRepository.java @@ -10,9 +10,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionItemReadGroupLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionItemReadGroupLinkRepository.java index a8bf3615cf87..5badc4cb7bc2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionItemReadGroupLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionItemReadGroupLinkRepository.java @@ -10,9 +10,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionLicenseLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionLicenseLinkRepository.java index dcb9705dbc16..ed0b253bd764 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionLicenseLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionLicenseLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.LicenseRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionLogoLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionLogoLinkRepository.java index cf2360dc05fa..3549e4972d8f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionLogoLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionLogoLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionMappedItemLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionMappedItemLinkRepository.java index 02795b312e96..892130239e76 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionMappedItemLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionMappedItemLinkRepository.java @@ -11,9 +11,9 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionParentCommunityLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionParentCommunityLinkRepository.java index 62a6f4e41d7e..bbec0aa1d40b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionParentCommunityLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionParentCommunityLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.CommunityRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionRestRepository.java index 6fcae23453ed..0d59aeb254b5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionRestRepository.java @@ -14,11 +14,11 @@ import java.util.Objects; import java.util.SortedMap; import java.util.UUID; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.Parameter; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionSubmitterGroupLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionSubmitterGroupLinkRepository.java index 58645479fa61..48acc2b83294 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionSubmitterGroupLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionSubmitterGroupLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityAdminGroupLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityAdminGroupLinkRepository.java index a3550584080b..cf36b8c915c2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityAdminGroupLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityAdminGroupLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CommunityRest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityCollectionLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityCollectionLinkRepository.java index f8e88918327e..1fa3468a519e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityCollectionLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityCollectionLinkRepository.java @@ -12,9 +12,9 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.CommunityRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityLogoLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityLogoLinkRepository.java index 0765e2efa3e1..1c828f81de8a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityLogoLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityLogoLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.CommunityRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityParentCommunityLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityParentCommunityLinkRepository.java index 7c14c944c26a..a9c778501596 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityParentCommunityLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityParentCommunityLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CommunityRest; import org.dspace.app.rest.projection.Projection; import org.dspace.content.Community; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityRestRepository.java index 7d060319d911..0d4e6be133e8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityRestRepository.java @@ -13,11 +13,11 @@ import java.util.List; import java.util.SortedMap; import java.util.UUID; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.Parameter; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunitySubcommunityLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunitySubcommunityLinkRepository.java index a577e97f98e7..e47e684080cb 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunitySubcommunityLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunitySubcommunityLinkRepository.java @@ -12,9 +12,9 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CommunityRest; import org.dspace.app.rest.projection.Projection; import org.dspace.content.Community; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java index a93f5e55dc02..74beeb3dac84 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java @@ -14,9 +14,9 @@ import java.util.List; import java.util.Optional; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.RESTAuthorizationException; @@ -34,8 +34,8 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.multipart.MultipartFile; /** @@ -48,7 +48,7 @@ */ public abstract class DSpaceRestRepository extends AbstractDSpaceRestRepository - implements PagingAndSortingRepository, BeanNameAware { + implements CrudRepository, PagingAndSortingRepository, BeanNameAware { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(DSpaceRestRepository.class); @@ -152,7 +152,6 @@ public Optional findById(ID id) { * the rest object id * @return the REST object identified by its ID */ - @PreAuthorize("hasAuthority('ADMIN')") public abstract T findOne(Context context, ID id); @Override diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DuplicateRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DuplicateRestRepository.java new file mode 100644 index 000000000000..8730211a5eba --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DuplicateRestRepository.java @@ -0,0 +1,186 @@ +/** + * 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.repository; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.app.rest.DiscoverableEndpointsService; +import org.dspace.app.rest.Parameter; +import org.dspace.app.rest.SearchRestMethod; +import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException; +import org.dspace.app.rest.model.PotentialDuplicateRest; +import org.dspace.app.rest.utils.ContextUtil; +import org.dspace.content.Item; +import org.dspace.content.service.DuplicateDetectionService; +import org.dspace.content.service.ItemService; +import org.dspace.content.virtual.PotentialDuplicate; +import org.dspace.core.Context; +import org.dspace.discovery.SearchServiceException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.hateoas.Link; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; + +/** + * The REST repository for the api/submission/duplicates endpoint, which handles requests for finding + * potential duplicates of a given item (archived or in-progress). + * + * Find one and find all are not implemented as actual REST methods because a duplicate is the result + * of comparing an item with other indexed items, not an object that can be referenced by some kind of ID, but + * we must at least implement the Java methods here in order to extend DSpaceRestRepository and implement + * SearchRestMethods. + * + * @author Kim Shepherd + */ +@ConditionalOnProperty("duplicate.enable") +@Component(PotentialDuplicateRest.CATEGORY + "." + PotentialDuplicateRest.NAME) +public class DuplicateRestRepository extends DSpaceRestRepository + implements InitializingBean { + + /** + * Discoverable endpoints service + */ + @Autowired + DiscoverableEndpointsService discoverableEndpointsService; + + /** + * Duplicate detection service + */ + @Autowired + DuplicateDetectionService duplicateDetectionService; + + /** + * Item service + */ + @Autowired + ItemService itemService; + + /** + * Logger + */ + private final static Logger log = LogManager.getLogger(); + + /** + * Register this repository endpoint as /api/submission/duplicates + * @throws Exception + */ + @Override + public void afterPropertiesSet() throws Exception { + discoverableEndpointsService + .register(this, Arrays.asList(Link.of( + "/api/" + PotentialDuplicateRest.CATEGORY + "/" + PotentialDuplicateRest.NAME + "/search", + PotentialDuplicateRest.NAME + "-search"))); + } + + /** + * This REST method is NOT IMPLEMENTED - it does not make sense in duplicate detection, in which the only + * real addressable objects involved are Items. + * + * @param context + * the dspace context + * @param name + * the rest object id + * @return not implemented + * @throws RepositoryMethodNotImplementedException + */ + @PreAuthorize("permitAll()") + @Override + public PotentialDuplicateRest findOne(Context context, String name) { + throw new RepositoryMethodNotImplementedException("Duplicate detection endpoint only implements searchBy", ""); + } + + /** + * This REST method is NOT IMPLEMENTED - it does not make sense in duplicate detection, where there can be no "all" + * + * @param context + * the dspace context + * @return not implemented + * @throws RepositoryMethodNotImplementedException + */ + @PreAuthorize("permitAll()") + @Override + public Page findAll(Context context, Pageable pageable) { + throw new RepositoryMethodNotImplementedException("Duplicate detection endpoint only implements searchBy", ""); + } + + /** + * Return a paged list of potential duplicate matches for the given item ID. This may be an item wrapped in + * an in-progress item wrapper like workspace or workflow, as long as the current user has READ access to this item. + * Results from the service search method will only contain matches that lead to items which are readable by + * the current user. + * + * @param uuid The item UUID to search + * @param pageable Pagination options + * @return Paged list of potential duplicates + * @throws Exception + */ + @PreAuthorize("hasPermission(#uuid, 'ITEM', 'READ')") + @SearchRestMethod(name = "findByItem") + public Page findByItem(@Parameter(value = "uuid", required = true) UUID uuid, + Pageable pageable) { + // Instantiate object to represent this item + Item item; + // Instantiate list of potential duplicates which we will convert and return as paged ItemRest list + List potentialDuplicates = new LinkedList<>(); + // Instantiate total count + int total = 0; + // Obtain context + Context context = ContextUtil.obtainCurrentRequestContext(); + + // Try to get item based on UUID parameter + try { + item = itemService.find(context, uuid); + } catch (SQLException e) { + throw new ResourceNotFoundException(e.getMessage()); + } + + // If the item is null or otherwise invalid (template, etc) then throw an appropriate error + if (item == null) { + throw new ResourceNotFoundException("No such item: " + uuid); + } + if (item.getTemplateItemOf() != null) { + throw new IllegalArgumentException("Cannot get duplicates for template item"); + } + + try { + // Search for the list of potential duplicates + potentialDuplicates = duplicateDetectionService.getPotentialDuplicates(context, item); + } catch (SearchServiceException e) { + // If the search fails, log an error and return an empty list rather than throwing a fatal error + log.error("Search service error retrieving duplicates: {}", e.getMessage()); + } + + // Construct rest pages and return + Page restPage = converter.toRestPage(potentialDuplicates, pageable, total, + utils.obtainProjection()); + + return restPage; + + } + + /** + * Return the domain class for potential duplicate objects + * @return PotentialDuplicateRest.class + */ + @Override + public Class getDomainClass() { + return PotentialDuplicateRest.class; + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonGroupLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonGroupLinkRepository.java index af38584c1fe0..5825fa003e93 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonGroupLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonGroupLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.EPersonRest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java index 3b88703ce47d..ce1edc1eed92 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java @@ -12,9 +12,9 @@ import java.util.Arrays; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EntityTypeRelationshipLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EntityTypeRelationshipLinkRepository.java index cea27f58300b..8b30f8643513 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EntityTypeRelationshipLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EntityTypeRelationshipLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.List; import java.util.Objects; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.EntityTypeRest; import org.dspace.app.rest.model.RelationshipTypeRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ExternalSourceEntityTypeLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ExternalSourceEntityTypeLinkRepository.java index 21e87b44d00f..4e371f44257a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ExternalSourceEntityTypeLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ExternalSourceEntityTypeLinkRepository.java @@ -10,9 +10,9 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.collections4.CollectionUtils; import org.dspace.app.rest.model.EntityTypeRest; import org.dspace.app.rest.model.ExternalSourceRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/FeedbackRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/FeedbackRestRepository.java index aee8cf60054a..b57bdbb61785 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/FeedbackRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/FeedbackRestRepository.java @@ -8,10 +8,10 @@ package org.dspace.app.rest.repository; import java.io.IOException; import java.sql.SQLException; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.DSpaceFeedbackNotFoundException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupEPersonLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupEPersonLinkRepository.java index 965d13aa7be6..d1ec7f693e7a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupEPersonLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupEPersonLinkRepository.java @@ -11,9 +11,9 @@ import java.util.List; import java.util.Set; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; import org.dspace.core.Context; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupGroupLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupGroupLinkRepository.java index 721f69ed90ba..36f0c47374d2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupGroupLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupGroupLinkRepository.java @@ -10,9 +10,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; import org.dspace.core.Context; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupParentObjectLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupParentObjectLinkRepository.java index 8ce43e4af8f6..973d695d6604 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupParentObjectLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupParentObjectLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.DSpaceObjectRest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupRestRepository.java index 7f16e5c43b75..160f838741ae 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupRestRepository.java @@ -13,9 +13,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.Parameter; import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.converter.MetadataConverter; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/HarvestedCollectionRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/HarvestedCollectionRestRepository.java index d7f12a1813bd..07a7d678854a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/HarvestedCollectionRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/HarvestedCollectionRestRepository.java @@ -13,10 +13,10 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.converter.HarvestedCollectionConverter; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.HarvestTypeEnum; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/IdentifierRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/IdentifierRestRepository.java index 204401d69a8c..7e8e8e2d8917 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/IdentifierRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/IdentifierRestRepository.java @@ -16,10 +16,10 @@ import java.util.Arrays; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.NotSupportedException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.ws.rs.NotSupportedException; import org.dspace.app.rest.DiscoverableEndpointsService; import org.dspace.app.rest.Parameter; import org.dspace.app.rest.SearchRestMethod; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemAccessStatusLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemAccessStatusLinkRepository.java index 83e720a413ef..975171fba3c3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemAccessStatusLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemAccessStatusLinkRepository.java @@ -10,9 +10,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.access.status.service.AccessStatusService; import org.dspace.app.rest.model.AccessStatusRest; import org.dspace.app.rest.model.ItemRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemBundleLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemBundleLinkRepository.java index 19efe5e8420e..a6089c2331e9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemBundleLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemBundleLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BundleRest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemIdentifierLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemIdentifierLinkRepository.java index 2cc7a62174ae..e2ad964bf43d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemIdentifierLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemIdentifierLinkRepository.java @@ -12,9 +12,9 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.IdentifierRest; import org.dspace.app.rest.model.IdentifiersRest; import org.dspace.app.rest.model.ItemRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemMappedCollectionLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemMappedCollectionLinkRepository.java index 382b1a3b93f7..41e438427cae 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemMappedCollectionLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemMappedCollectionLinkRepository.java @@ -11,9 +11,9 @@ import java.util.List; import java.util.UUID; import java.util.stream.Collectors; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemOwningCollectionLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemOwningCollectionLinkRepository.java index 22c82c4d3dcf..b41ace1dd307 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemOwningCollectionLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemOwningCollectionLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRelationshipLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRelationshipLinkRepository.java index c5f63ab5a887..5ae8179d0bd0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRelationshipLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRelationshipLinkRepository.java @@ -10,9 +10,9 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.model.RelationshipRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java index a1659c58d38c..1a22a5f7477f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java @@ -14,11 +14,11 @@ import java.util.List; import java.util.Objects; import java.util.UUID; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -365,4 +365,5 @@ protected ItemRest createAndReturn(Context context, List stringList) Item item = uriListHandlerService.handle(context, req, stringList, Item.class); return converter.toRest(item, utils.obtainProjection()); } + } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemTemplateItemOfLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemTemplateItemOfLinkRepository.java index fb7db2b38de7..45ac2420fa7f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemTemplateItemOfLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemTemplateItemOfLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemThumbnailLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemThumbnailLinkRepository.java index 7a42050eec92..fd56151d7edf 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemThumbnailLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemThumbnailLinkRepository.java @@ -10,9 +10,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemVersionLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemVersionLinkRepository.java index 5e489d5ebf0c..abf107b82241 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemVersionLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemVersionLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.model.VersionRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/LDNMessageRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/LDNMessageRestRepository.java new file mode 100644 index 000000000000..d28080ab36cd --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/LDNMessageRestRepository.java @@ -0,0 +1,87 @@ +/** + * 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.repository; + +import java.sql.SQLException; + +import jakarta.servlet.http.HttpServletRequest; +import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.app.ldn.service.LDNMessageService; +import org.dspace.app.rest.exception.MethodNotAllowedException; +import org.dspace.app.rest.model.LDNMessageEntityRest; +import org.dspace.app.rest.model.patch.Patch; +import org.dspace.authorize.AuthorizeException; +import org.dspace.core.Context; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; + +/** + * This is the repository responsible to manage LDNMessageEntry Rest object + * + * @author Stefano Maffei(stefano.maffei at 4science.com) + */ + +@Component(LDNMessageEntityRest.CATEGORY + "." + LDNMessageEntityRest.NAME_PLURALS) +public class LDNMessageRestRepository extends DSpaceRestRepository { + + @Autowired + private LDNMessageService ldnMessageService; + + @Override + @PreAuthorize("hasAuthority('ADMIN')") + public LDNMessageEntityRest findOne(Context context, String id) { + try { + LDNMessageEntity ldnMessageEntity = ldnMessageService.find(context, id); + if (ldnMessageEntity == null) { + throw new ResourceNotFoundException("The LDNMessageEntity for ID: " + id + " could not be found"); + } + return converter.toRest(ldnMessageEntity, utils.obtainProjection()); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + @PreAuthorize("hasAuthority('ADMIN')") + public Page findAll(Context context, Pageable pageable) { + try { + return converter.toRestPage(ldnMessageService.findAll(context), pageable, utils.obtainProjection()); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + @PreAuthorize("hasAuthority('ADMIN')") + protected LDNMessageEntityRest createAndReturn(Context context) throws AuthorizeException, SQLException { + throw new MethodNotAllowedException("Creation of LDN Message is not supported via Endpoint"); + } + + @Override + @PreAuthorize("hasAuthority('ADMIN')") + protected void patch(Context context, HttpServletRequest request, String apiCategory, String model, String id, + Patch patch) throws AuthorizeException, SQLException { + throw new MethodNotAllowedException("Patch of LDN Message is not supported via Endpoint"); + } + + @Override + @PreAuthorize("hasAuthority('ADMIN')") + protected void delete(Context context, String id) throws AuthorizeException { + throw new MethodNotAllowedException("Deletion of LDN Message is not supported via Endpoint"); + } + + @Override + public Class getDomainClass() { + return LDNMessageEntityRest.class; + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataFieldRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataFieldRestRepository.java index a6e6bd34edd2..0d0bc1729a26 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataFieldRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataFieldRestRepository.java @@ -17,11 +17,11 @@ import java.util.Iterator; import java.util.List; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.core.JsonProcessingException; 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.logging.log4j.Logger; import org.dspace.app.rest.Parameter; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataSchemaRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataSchemaRestRepository.java index c57d33b1504d..d7338dc31419 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataSchemaRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataSchemaRestRepository.java @@ -13,11 +13,11 @@ import java.sql.SQLException; import java.util.List; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.MetadataSchemaRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/NotifyServiceRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/NotifyServiceRestRepository.java index c3b15ad77f20..8beb9f5f2745 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/NotifyServiceRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/NotifyServiceRestRepository.java @@ -13,10 +13,10 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.ldn.NotifyServiceEntity; import org.dspace.app.ldn.NotifyServiceInboundPattern; import org.dspace.app.ldn.service.NotifyService; @@ -106,8 +106,7 @@ protected NotifyServiceRest createAndReturn(Context context) throws AuthorizeExc notifyServiceRest.getLdnUrl())); } - NotifyServiceEntity notifyServiceEntity = notifyService.create(context); - notifyServiceEntity.setName(notifyServiceRest.getName()); + NotifyServiceEntity notifyServiceEntity = notifyService.create(context, notifyServiceRest.getName()); notifyServiceEntity.setDescription(notifyServiceRest.getDescription()); notifyServiceEntity.setUrl(notifyServiceRest.getUrl()); notifyServiceEntity.setLdnUrl(notifyServiceRest.getLdnUrl()); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/OrcidHistoryRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/OrcidHistoryRestRepository.java index e804654907d6..77d7ba23611e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/OrcidHistoryRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/OrcidHistoryRestRepository.java @@ -9,8 +9,8 @@ import java.sql.SQLException; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException; import org.dspace.app.rest.model.OrcidHistoryRest; import org.dspace.app.rest.repository.handler.service.UriListHandlerService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/PoolTaskStepLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/PoolTaskStepLinkRepository.java index 9e1a41cb92b9..9af6a5730918 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/PoolTaskStepLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/PoolTaskStepLinkRepository.java @@ -8,9 +8,9 @@ package org.dspace.app.rest.repository; import java.sql.SQLException; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.PoolTaskRest; import org.dspace.app.rest.model.WorkflowStepRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessFileTypesLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessFileTypesLinkRepository.java index 1727e720a8da..cb83379d8b08 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessFileTypesLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessFileTypesLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.List; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.ProcessFileTypesRest; import org.dspace.app.rest.model.ProcessRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessFilesLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessFilesLinkRepository.java index e09a47ad7ceb..d981a9c7976b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessFilesLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessFilesLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.List; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.model.BitstreamRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessOutputLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessOutputLinkRepository.java index 632e7d7c94e0..016450c92569 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessOutputLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessOutputLinkRepository.java @@ -8,9 +8,9 @@ package org.dspace.app.rest.repository; import java.sql.SQLException; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.ProcessRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRelatedLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRelatedLinkRepository.java index 81f9aaab5850..f4e84a233b2e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRelatedLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRelatedLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.model.QAEventRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRestRepository.java index 44be4ececaa1..e6c25dfd9f2f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRestRepository.java @@ -12,10 +12,10 @@ import java.util.List; import java.util.Objects; import java.util.UUID; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.dspace.app.rest.Parameter; import org.dspace.app.rest.SearchRestMethod; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventTargetLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventTargetLinkRepository.java index 74dbccc467d9..eb2ca8317b51 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventTargetLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventTargetLinkRepository.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.model.QAEventRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventTopicLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventTopicLinkRepository.java index 067958e96c39..02eeaae0d759 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventTopicLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventTopicLinkRepository.java @@ -7,9 +7,8 @@ */ package org.dspace.app.rest.repository; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; - +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.QAEventRest; import org.dspace.app.rest.model.QATopicRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RegistrationRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RegistrationRestRepository.java index 4f21ecf62670..9c1c3b393bbb 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RegistrationRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RegistrationRestRepository.java @@ -11,11 +11,11 @@ import java.io.IOException; import java.sql.SQLException; -import javax.mail.MessagingException; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.mail.MessagingException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -43,6 +43,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; /** @@ -79,6 +80,7 @@ public class RegistrationRestRepository extends DSpaceRestRepository - * Based on Spring Security's CsrfAuthenticationStrategy: - * https://github.com/spring-projects/spring-security/blob/5.2.x/web/src/main/java/org/springframework/security/web/csrf/CsrfAuthenticationStrategy.java + * This is essentially a customization of Spring Security's CsrfAuthenticationStrategy: + * https://github.com/spring-projects/spring-security/blob/6.2.x/web/src/main/java/org/springframework/security/web/csrf/CsrfAuthenticationStrategy.java */ public class DSpaceCsrfAuthenticationStrategy implements SessionAuthenticationStrategy { - private final CsrfTokenRepository csrfTokenRepository; + private final Log logger = LogFactory.getLog(getClass()); + + private final CsrfTokenRepository tokenRepository; + + private CsrfTokenRequestHandler requestHandler = new XorCsrfTokenRequestAttributeHandler(); /** * Creates a new instance - * @param csrfTokenRepository the {@link CsrfTokenRepository} to use + * @param tokenRepository the {@link CsrfTokenRepository} to use + */ + public DSpaceCsrfAuthenticationStrategy(CsrfTokenRepository tokenRepository) { + Assert.notNull(tokenRepository, "tokenRepository cannot be null"); + this.tokenRepository = tokenRepository; + } + + /** + * Method is copied from {@link CsrfAuthenticationStrategy#setRequestHandler(CsrfTokenRequestHandler)} */ - public DSpaceCsrfAuthenticationStrategy(CsrfTokenRepository csrfTokenRepository) { - Assert.notNull(csrfTokenRepository, "csrfTokenRepository cannot be null"); - this.csrfTokenRepository = csrfTokenRepository; + public void setRequestHandler(CsrfTokenRequestHandler requestHandler) { + Assert.notNull(requestHandler, "requestHandler cannot be null"); + this.requestHandler = requestHandler; } /** * This method is triggered anytime a new Authentication occurs. As DSpace uses Stateless authentication, * this method is triggered on _every request_ after an initial login occurs. This is because the Spring Security - * Authentication object is recreated on every request. + * 'Authentication' object is recreated on every request. *

* Therefore, for DSpace, we've customized this method to ensure a new CSRF Token is NOT generated each time a new - * Authentication object is created -- doing so causes the CSRF Token to change with every request. Instead, we + * Authentication object is created -- as doing so causes the CSRF Token to change with every request. Instead, we * check to see if the client also passed a CSRF token via a querystring parameter (i.e. "_csrf"). If so, this means * the client has sent the token in a less secure manner & it must then be regenerated. *

@@ -58,8 +75,10 @@ public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) throws SessionAuthenticationException { + // Check if token returned in server-side cookie - CsrfToken token = this.csrfTokenRepository.loadToken(request); + CsrfToken token = this.tokenRepository.loadToken(request); + // For DSpace, this will only be null if we are forcing CSRF token regeneration (e.g. on initial login) boolean containsToken = token != null; @@ -70,18 +89,31 @@ public void onAuthentication(Authentication authentication, // If token exists was sent in a parameter, then we need to reset our token // (as sending token in a param is insecure) if (containsParameter) { - // Note: We first set the token to null & then set a new one. This results in 2 cookies sent, - // the first being empty and the second having the new token. - // This behavior is borrowed from Spring Security's CsrfAuthenticationStrategy, see - // https://github.com/spring-projects/spring-security/blob/5.4.x/web/src/main/java/org/springframework/security/web/csrf/CsrfAuthenticationStrategy.java - this.csrfTokenRepository.saveToken(null, request, response); - CsrfToken newToken = this.csrfTokenRepository.generateToken(request); - this.csrfTokenRepository.saveToken(newToken, request, response); - - request.setAttribute(CsrfToken.class.getName(), newToken); - request.setAttribute(newToken.getParameterName(), newToken); + resetCSRFToken(request, response); } } } + /** + * A custom utility method to force Spring Security to reset the CSRF token. This is used by DSpace to reset + * the token whenever the CSRF token is passed insecurely (as a request param, see onAuthentication() above) + * or on logout (see JWTTokenRestAuthenticationServiceImpl) + * @param request current HTTP request + * @param response current HTTP response + * @see org.dspace.app.rest.security.jwt.JWTTokenRestAuthenticationServiceImpl + */ + public void resetCSRFToken(HttpServletRequest request, HttpServletResponse response) { + // Note: We first set the token to null & then set a new one. This results in 2 cookies sent, + // the first being empty and the second having the new token. + // This behavior is borrowed from Spring Security's CsrfAuthenticationStrategy, see + // https://github.com/spring-projects/spring-security/blob/6.2.x/web/src/main/java/org/springframework/security/web/csrf/CsrfAuthenticationStrategy.java + this.tokenRepository.saveToken(null, request, response); + DeferredCsrfToken deferredCsrfToken = this.tokenRepository.loadDeferredToken(request, response); + this.requestHandler.handle(request, response, deferredCsrfToken::get); + // This may look odd, but reading the deferred CSRF token will cause Spring Security to send it back + // in the next request. This ensures our new token is sent back immediately (instead of in a later request) + deferredCsrfToken.get(); + this.logger.debug("Replaced CSRF Token"); + } + } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRepository.java index 2079727ac889..0bcd2a55237d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRepository.java @@ -8,12 +8,13 @@ package org.dspace.app.rest.security; import java.util.UUID; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.HttpHeaders; +import java.util.function.Consumer; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.ResponseCookie; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.security.web.csrf.CsrfToken; import org.springframework.security.web.csrf.CsrfTokenRepository; import org.springframework.security.web.csrf.DefaultCsrfToken; @@ -25,9 +26,10 @@ * This is a custom Spring Security CsrfTokenRepository which supports *cross-domain* CSRF protection (allowing the * client and backend to be on different domains). It's inspired by https://stackoverflow.com/a/33175322 *

- * This also borrows heavily from Spring Security's CookieCsrfTokenRepository: - * https://github.com/spring-projects/spring-security/blob/5.2.x/web/src/main/java/org/springframework/security/web/csrf/CookieCsrfTokenRepository.java - * + * This is essentially a customization of Spring Security's CookieCsrfTokenRepository: + * https://github.com/spring-projects/spring-security/blob/6.2.x/web/src/main/java/org/springframework/security/web/csrf/CookieCsrfTokenRepository.java + * However, as that class is "final" we aannot override it directly. + *

* How it works: * * 1. Backend generates XSRF token & stores in a *server-side* cookie named DSPACE-XSRF-COOKIE. By default, this cookie @@ -53,11 +55,19 @@ public class DSpaceCsrfTokenRepository implements CsrfTokenRepository { // This cookie name is changed from the default "XSRF-TOKEN" to ensure it is uniquely named and doesn't conflict // with any other XSRF-TOKEN cookies (e.g. in Angular UI, the XSRF-TOKEN cookie is a *client-side* only cookie) - static final String DEFAULT_CSRF_COOKIE_NAME = "DSPACE-XSRF-COOKIE"; + public static final String DEFAULT_CSRF_COOKIE_NAME = "DSPACE-XSRF-COOKIE"; + + // The HTTP header that is sent back to the client whenever a new CSRF token is created + // (NOTE: This is purposefully different from DEFAULT_CSRF_HEADER_NAME below!) + public static final String DSPACE_CSRF_HEADER_NAME = "DSPACE-XSRF-TOKEN"; - static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf"; + public static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf"; - static final String DEFAULT_CSRF_HEADER_NAME = "X-XSRF-TOKEN"; + // The HTTP header that Spring Security expects to receive from the client in order to validate a CSRF token + public static final String DEFAULT_CSRF_HEADER_NAME = "X-XSRF-TOKEN"; + + private static final String CSRF_TOKEN_REMOVED_ATTRIBUTE_NAME = CookieCsrfTokenRepository.class.getName() + .concat(".REMOVED"); private String parameterName = DEFAULT_CSRF_PARAMETER_NAME; @@ -71,73 +81,93 @@ public class DSpaceCsrfTokenRepository implements CsrfTokenRepository { private String cookieDomain; + private Boolean secure; + + private int cookieMaxAge = -1; + + private Consumer cookieCustomizer = (builder) -> { + }; + public DSpaceCsrfTokenRepository() { } + /** + * Method is copied from {@link CookieCsrfTokenRepository#setCookieCustomizer(Consumer)} + */ + public void setCookieCustomizer(Consumer cookieCustomizer) { + Assert.notNull(cookieCustomizer, "cookieCustomizer must not be null"); + this.cookieCustomizer = cookieCustomizer; + } + + /** + * Method is copied from {@link CookieCsrfTokenRepository#generateToken(HttpServletRequest)} + */ @Override public CsrfToken generateToken(HttpServletRequest request) { - return new DefaultCsrfToken(this.headerName, this.parameterName, - createNewToken()); + return new DefaultCsrfToken(this.headerName, this.parameterName, createNewToken()); } /** - * This method has been modified for DSpace. + * This method has been modified for DSpace. It borrows MOST of the logic from + * {@link CookieCsrfTokenRepository#saveToken(CsrfToken, HttpServletRequest, HttpServletResponse)} *

- * It now uses ResponseCookie to build the cookie, so that the "SameSite" attribute can be applied. + * It applies a "SameSite" attribute to every cookie by default. *

- * It also sends the token (if not empty) in both the cookie and the custom "DSPACE-XSRF-TOKEN" header + * It also sends the token (if not empty) back in BOTH the cookie and the custom "DSPACE-XSRF-TOKEN" header. + * By default, Spring Security will only send the token back in the cookie. * @param token current token * @param request current request * @param response current response */ @Override - public void saveToken(CsrfToken token, HttpServletRequest request, - HttpServletResponse response) { - String tokenValue = token == null ? "" : token.getToken(); - Cookie cookie = new Cookie(this.cookieName, tokenValue); - cookie.setSecure(request.isSecure()); - if (this.cookiePath != null && !this.cookiePath.isEmpty()) { - cookie.setPath(this.cookiePath); - } else { - cookie.setPath(this.getRequestContext(request)); - } - if (token == null) { - cookie.setMaxAge(0); - } else { - cookie.setMaxAge(-1); - } - cookie.setHttpOnly(cookieHttpOnly); - if (this.cookieDomain != null && !this.cookieDomain.isEmpty()) { - cookie.setDomain(this.cookieDomain); - } + public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) { + String tokenValue = (token != null) ? token.getToken() : ""; - // Custom: Turn the above Cookie into a ResponseCookie so that we can set "SameSite" attribute - // If client is on a different domain than the backend, then Cookie MUST use "SameSite=None" and "Secure". - // Most modern browsers will block it otherwise. - // TODO: Make SameSite configurable? "Lax" cookies are more secure, but require client & backend on same domain. - String sameSite = "None"; - if (!cookie.getSecure()) { - sameSite = "Lax"; - } - ResponseCookie responseCookie = ResponseCookie.from(cookie.getName(), cookie.getValue()) - .path(cookie.getPath()).maxAge(cookie.getMaxAge()) - .domain(cookie.getDomain()).httpOnly(cookie.isHttpOnly()) - .secure(cookie.getSecure()).sameSite(sameSite).build(); + ResponseCookie.ResponseCookieBuilder cookieBuilder = + ResponseCookie.from(this.cookieName, tokenValue) + .secure((this.secure != null) ? this.secure : request.isSecure()) + .path(StringUtils.hasLength(this.cookiePath) ? + this.cookiePath : this.getRequestContext(request)) + .maxAge((token != null) ? this.cookieMaxAge : 0) + .httpOnly(this.cookieHttpOnly) + .domain(this.cookieDomain) + // Custom for DSpace: If client is on a different domain than the backend, then Cookie MUST + // use "SameSite=None" and "Secure". Most modern browsers will block it otherwise. + // TODO: Make SameSite configurable? "Lax" cookies are more secure, but require client & + // backend on same domain. + .sameSite(request.isSecure() ? "None" : "Lax");; - // Write the ResponseCookie to the Set-Cookie header - // This cookie is only used by the backend & not needed by client - response.addHeader(HttpHeaders.SET_COOKIE, responseCookie.toString()); + this.cookieCustomizer.accept(cookieBuilder); - // Send custom header to client with token (only if token not empty) - // We send our token via a custom header because client can be on a different domain. + // Custom for DSpace: also send custom header to client with token. + // We send our token via a custom header because client may be on a different domain. // Cookies cannot be reliably sent cross-domain. if (StringUtils.hasLength(tokenValue)) { - response.setHeader("DSPACE-XSRF-TOKEN", tokenValue); + response.setHeader(DSPACE_CSRF_HEADER_NAME, tokenValue); + } + + Cookie cookie = mapToCookie(cookieBuilder.build()); + response.addCookie(cookie); + + // Set request attribute to signal that response has blank cookie value, + // which allows loadToken to return null when token has been removed + if (!StringUtils.hasLength(tokenValue)) { + request.setAttribute(CSRF_TOKEN_REMOVED_ATTRIBUTE_NAME, Boolean.TRUE); + } else { + request.removeAttribute(CSRF_TOKEN_REMOVED_ATTRIBUTE_NAME); } } + /** + * Method is copied from {@link CookieCsrfTokenRepository#loadToken(HttpServletRequest)} + */ @Override public CsrfToken loadToken(HttpServletRequest request) { + // Return null when token has been removed during the current request + // which allows loadDeferredToken to re-generate the token + if (Boolean.TRUE.equals(request.getAttribute(CSRF_TOKEN_REMOVED_ATTRIBUTE_NAME))) { + return null; + } Cookie cookie = WebUtils.getCookie(request, this.cookieName); if (cookie == null) { return null; @@ -146,104 +176,124 @@ public CsrfToken loadToken(HttpServletRequest request) { if (!StringUtils.hasLength(token)) { return null; } - return new DefaultCsrfToken(this.headerName, this.parameterName, token); } - /** - * Sets the name of the HTTP request parameter that should be used to provide a token. - * - * @param parameterName the name of the HTTP request parameter that should be used to - * provide a token + * Method is copied from {@link CookieCsrfTokenRepository#setParameterName(String)} */ public void setParameterName(String parameterName) { - Assert.notNull(parameterName, "parameterName is not null"); + Assert.notNull(parameterName, "parameterName cannot be null"); this.parameterName = parameterName; } /** - * Sets the name of the HTTP header that should be used to provide the token. - * - * @param headerName the name of the HTTP header that should be used to provide the - * token + * Method is copied from {@link CookieCsrfTokenRepository#setHeaderName(String)} */ public void setHeaderName(String headerName) { - Assert.notNull(headerName, "headerName is not null"); + Assert.notNull(headerName, "headerName cannot be null"); this.headerName = headerName; } /** - * Sets the name of the cookie that the expected CSRF token is saved to and read from. - * - * @param cookieName the name of the cookie that the expected CSRF token is saved to - * and read from + * Method is copied from {@link CookieCsrfTokenRepository#setCookieName(String)} */ public void setCookieName(String cookieName) { - Assert.notNull(cookieName, "cookieName is not null"); + Assert.notNull(cookieName, "cookieName cannot be null"); this.cookieName = cookieName; } /** - * Sets the HttpOnly attribute on the cookie containing the CSRF token. - * Defaults to true. - * - * @param cookieHttpOnly true sets the HttpOnly attribute, false does not set it + * Method is copied from {@link CookieCsrfTokenRepository#setCookieHttpOnly(boolean)} + * @deprecated Use {@link #setCookieCustomizer(Consumer)} instead. */ + @Deprecated public void setCookieHttpOnly(boolean cookieHttpOnly) { this.cookieHttpOnly = cookieHttpOnly; } + /** + * Method is copied from {@link CookieCsrfTokenRepository} + */ private String getRequestContext(HttpServletRequest request) { String contextPath = request.getContextPath(); - return contextPath.length() > 0 ? contextPath : "/"; + return (contextPath.length() > 0) ? contextPath : "/"; } /** - * Factory method to conveniently create an instance that has - * {@link #setCookieHttpOnly(boolean)} set to false. - * - * @return an instance of CookieCsrfTokenRepository with - * {@link #setCookieHttpOnly(boolean)} set to false + * Method is copied from {@link CookieCsrfTokenRepository} + * (and only modified to return the DSpaceCsrfTokenRepository instead) */ public static DSpaceCsrfTokenRepository withHttpOnlyFalse() { DSpaceCsrfTokenRepository result = new DSpaceCsrfTokenRepository(); - result.setCookieHttpOnly(false); + result.cookieHttpOnly = false; return result; } + /** + * Method is copied from {@link CookieCsrfTokenRepository} + */ private String createNewToken() { return UUID.randomUUID().toString(); } /** - * Set the path that the Cookie will be created with. This will override the default functionality which uses the - * request context as the path. - * - * @param path the path to use + * Method is copied from {@link CookieCsrfTokenRepository} + */ + private Cookie mapToCookie(ResponseCookie responseCookie) { + Cookie cookie = new Cookie(responseCookie.getName(), responseCookie.getValue()); + cookie.setSecure(responseCookie.isSecure()); + cookie.setPath(responseCookie.getPath()); + cookie.setMaxAge((int) responseCookie.getMaxAge().getSeconds()); + cookie.setHttpOnly(responseCookie.isHttpOnly()); + if (StringUtils.hasLength(responseCookie.getDomain())) { + cookie.setDomain(responseCookie.getDomain()); + } + if (StringUtils.hasText(responseCookie.getSameSite())) { + cookie.setAttribute("SameSite", responseCookie.getSameSite()); + } + return cookie; + } + + /** + * Method is copied from {@link CookieCsrfTokenRepository#setCookiePath(String)} */ public void setCookiePath(String path) { this.cookiePath = path; } /** - * Get the path that the CSRF cookie will be set to. - * - * @return the path to be used. + * Method is copied from {@link CookieCsrfTokenRepository#getCookiePath()} */ public String getCookiePath() { return this.cookiePath; } /** - * Sets the domain of the cookie that the expected CSRF token is saved to and read from. - * - * @since 5.2 - * @param cookieDomain the domain of the cookie that the expected CSRF token is saved to - * and read from + * Method is copied from {@link CookieCsrfTokenRepository#setCookieDomain(String)} + * @deprecated Use {@link #setCookieCustomizer(Consumer)} instead. */ + @Deprecated public void setCookieDomain(String cookieDomain) { this.cookieDomain = cookieDomain; } + /** + * Method is copied from {@link CookieCsrfTokenRepository#setSecure(Boolean)} + * @deprecated Use {@link #setCookieCustomizer(Consumer)} instead. + */ + @Deprecated + public void setSecure(Boolean secure) { + this.secure = secure; + } + + /** + * Method is copied from {@link CookieCsrfTokenRepository#setCookieMaxAge(int)} + * @deprecated Use {@link #setCookieCustomizer(Consumer)} instead. + */ + @Deprecated + public void setCookieMaxAge(int cookieMaxAge) { + Assert.isTrue(cookieMaxAge != 0, "cookieMaxAge cannot be zero"); + this.cookieMaxAge = cookieMaxAge; + } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRequestHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRequestHandler.java new file mode 100644 index 000000000000..f8af92fa5868 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRequestHandler.java @@ -0,0 +1,66 @@ +/** + * 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.security; + +import java.util.function.Supplier; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; +import org.springframework.security.web.csrf.CsrfTokenRequestHandler; +import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler; +import org.springframework.util.StringUtils; + +/** + * A custom Spring Security CsrfTokenRequestAttributeHandler which uses the Spring Security BREACH protection + * (provided by XorCsrfTokenRequestAttributeHandler) *only* when the CSRF token is sent as a "_csrf" request parameter. + * In all other scenarios, the CsrfTokenRequestAttributeHandler is used instead. + *

+ * NOTE: The DSpace UI always sends the CSRF Token as a request header. It does NOT send it as a "_csrf" request + * paramter. So, this BREACH protection would ONLY be triggered for custom clients (not the DSpace UI). + * Therefore, if using this custom class becomes problematic, we could revert to using the default + * CsrfTokenRequestAttributeHandler without any negative impact on the DSpace UI. + *

+ * This code is copied from the example "SpaCsrfTokenRequestHandler" (for single page applications) from the Spring + * Security docs at + * https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#csrf-integration-javascript-spa-configuration + */ +public final class DSpaceCsrfTokenRequestHandler extends CsrfTokenRequestAttributeHandler { + private final CsrfTokenRequestHandler delegate = new XorCsrfTokenRequestAttributeHandler(); + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, Supplier csrfToken) { + /* + * Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of + * the CsrfToken when it is rendered in the response body. + * NOTE: This should never occur from the DSpace UI, so it is only applicable for custom clients. + */ + this.delegate.handle(request, response, csrfToken); + } + + @Override + public String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) { + /* + * If the request contains a request header, use CsrfTokenRequestAttributeHandler + * to resolve the CsrfToken. This applies to the DSpace UI which always includes + * the raw CsrfToken in an HTTP Header. + */ + if (StringUtils.hasText(request.getHeader(csrfToken.getHeaderName()))) { + return super.resolveCsrfTokenValue(request, csrfToken); + } + /* + * In all other cases (e.g. if the request contains a request parameter), use + * XorCsrfTokenRequestAttributeHandler to resolve the CsrfToken. This applies + * when a server-side rendered form includes the _csrf request parameter as a + * hidden input. + * NOTE: This should never occur from the DSpace UI, so it is only applicable for custom clients. + */ + return this.delegate.resolveCsrfTokenValue(request, csrfToken); + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpacePermissionEvaluator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpacePermissionEvaluator.java index b801830d916f..d6e162b30a46 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpacePermissionEvaluator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpacePermissionEvaluator.java @@ -38,13 +38,13 @@ public class DSpacePermissionEvaluator implements PermissionEvaluator { * expression system. This corresponds to the DSpace action. Not null. * @return true if the permission is granted by one of the plugins, false otherwise */ + @Override public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { for (RestPermissionEvaluatorPlugin permissionEvaluatorPlugin : permissionEvaluatorPluginList) { if (permissionEvaluatorPlugin.hasPermission(authentication, targetDomainObject, permission)) { return true; } } - return false; } @@ -59,6 +59,7 @@ public boolean hasPermission(Authentication authentication, Object targetDomainO * expression system. This corresponds to the DSpace action. Not null. * @return true if the permission is granted by one of the plugins, false otherwise */ + @Override public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { for (RestPermissionEvaluatorPlugin permissionEvaluatorPlugin : permissionEvaluatorPluginList) { 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 a515c6407b10..d66ecd547274 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 @@ -15,9 +15,9 @@ import java.util.LinkedList; import java.util.List; import java.util.Objects; -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EPersonRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EPersonRestPermissionEvaluatorPlugin.java index bd2a71288b92..c3e1cc68ae96 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EPersonRestPermissionEvaluatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EPersonRestPermissionEvaluatorPlugin.java @@ -11,8 +11,8 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -61,6 +61,9 @@ public boolean hasDSpacePermission(Authentication authentication, Serializable t if (Constants.getTypeID(targetType) != Constants.EPERSON) { return false; } + if (targetId == null) { + return false; + } Request request = requestService.getCurrentRequest(); Context context = ContextUtil.obtainContext(request.getHttpServletRequest()); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExtractorOfAInprogressSubmissionInformations.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExtractorOfAInprogressSubmissionInformations.java index dd2c8602d891..cbe685f9fe48 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExtractorOfAInprogressSubmissionInformations.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExtractorOfAInprogressSubmissionInformations.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.Objects; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.dspace.app.rest.model.WorkflowItemRest; import org.dspace.app.rest.model.WorkspaceItemRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/GroupRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/GroupRestPermissionEvaluatorPlugin.java index f15efcccb058..ad34cede6bf4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/GroupRestPermissionEvaluatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/GroupRestPermissionEvaluatorPlugin.java @@ -59,6 +59,9 @@ public boolean hasDSpacePermission(Authentication authentication, Serializable t || Constants.getTypeID(targetType) != Constants.GROUP) { return false; } + if (targetId == null) { + return false; + } Request request = requestService.getCurrentRequest(); Context context = ContextUtil.obtainContext(request.getHttpServletRequest()); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MethodSecurityConfig.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MethodSecurityConfig.java index 5ee308c73ed8..90a8f013e259 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MethodSecurityConfig.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MethodSecurityConfig.java @@ -8,28 +8,31 @@ package org.dspace.app.rest.security; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.access.PermissionEvaluator; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +/** + * This EnableMethodSecurity configuration enables Spring Security annotation checks on all methods + * (e.g. @PreAuthorize, @PostAuthorize annotations, etc.) + */ @Configuration -@EnableGlobalMethodSecurity(prePostEnabled = true) -public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { - +@EnableMethodSecurity +public class MethodSecurityConfig { @Autowired private PermissionEvaluator dSpacePermissionEvaluator; - @Autowired - private ApplicationContext applicationContext; - - @Override - protected MethodSecurityExpressionHandler createExpressionHandler() { + /** + * Tell Spring to use our custom PermissionEvaluator as part of method security. + * This allows DSpacePermissionEvaluator to be used in @PreAuthorize annotations (and similar). + * @see org.dspace.app.rest.security.DSpacePermissionEvaluator + */ + @Bean + MethodSecurityExpressionHandler methodSecurityExpressionHandler() { DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - expressionHandler.setApplicationContext(applicationContext); expressionHandler.setPermissionEvaluator(dSpacePermissionEvaluator); return expressionHandler; } 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..28c67314c5ca 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,26 +10,27 @@ import static org.dspace.authenticate.OidcAuthenticationBean.OIDC_AUTH_ATTRIBUTE; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; /** - * This class will filter openID Connect requests and try and authenticate them. + * This class will filter OpenID Connect (OIDC) requests and try and authenticate them. + * In this case, the actual authentication is performed by OIDC. After authentication succeeds, OIDC will send + * the authentication data to this filter in order for it to be processed by DSpace. * * @author Pasquale Cavallo (pasquale.cavallo at 4science dot it) */ - public class OidcLoginFilter extends StatelessLoginFilter { - public OidcLoginFilter(String url, AuthenticationManager authenticationManager, + public OidcLoginFilter(String url, String httpMethod, AuthenticationManager authenticationManager, RestAuthenticationService restAuthenticationService) { - super(url, authenticationManager, restAuthenticationService); + super(url, httpMethod, authenticationManager, restAuthenticationService); } @Override diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/OrcidLoginFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/OrcidLoginFilter.java index 9fdef6b050f7..70496b9dba23 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/OrcidLoginFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/OrcidLoginFilter.java @@ -9,11 +9,11 @@ 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 jakarta.servlet.FilterChain; +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.LogManager; import org.apache.logging.log4j.Logger; @@ -32,6 +32,8 @@ /** * This class will filter ORCID requests and try and authenticate them. + * In this case, the actual authentication is performed by ORCID. After authentication succeeds, ORCID will send + * the authentication data to this filter in order for it to be processed by DSpace. * * @author Luca Giamminonni (luca.giamminonni at 4science.it) */ @@ -45,9 +47,9 @@ public class OrcidLoginFilter extends StatelessLoginFilter { private OrcidAuthenticationBean orcidAuthentication = new DSpace().getServiceManager() .getServiceByName("orcidAuthentication", OrcidAuthenticationBean.class); - public OrcidLoginFilter(String url, AuthenticationManager authenticationManager, + public OrcidLoginFilter(String url, String httpMethod, AuthenticationManager authenticationManager, RestAuthenticationService restAuthenticationService) { - super(url, authenticationManager, restAuthenticationService); + super(url, httpMethod, authenticationManager, restAuthenticationService); } @Override @@ -57,7 +59,7 @@ public Authentication attemptAuthentication(HttpServletRequest req, HttpServletR if (!OrcidAuthentication.isEnabled()) { throw new ProviderNotFoundException("Orcid login is disabled."); } - + // NOTE: because this authentication is implicit, we pass in an empty DSpaceAuthentication return authenticationManager.authenticate(new DSpaceAuthentication()); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResearcherProfileRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResearcherProfileRestPermissionEvaluatorPlugin.java index 0e0f60807855..5cad1b33535a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResearcherProfileRestPermissionEvaluatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ResearcherProfileRestPermissionEvaluatorPlugin.java @@ -13,8 +13,8 @@ import java.io.Serializable; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.model.ResearcherProfileRest; import org.dspace.app.rest.utils.ContextUtil; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RestAuthenticationService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RestAuthenticationService.java index dd464edfcdee..e021344b15f0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RestAuthenticationService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RestAuthenticationService.java @@ -8,9 +8,9 @@ package org.dspace.app.rest.security; import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.model.wrapper.AuthenticationToken; import org.dspace.authenticate.service.AuthenticationService; import org.dspace.core.Context; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ShibbolethLoginFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ShibbolethLoginFilter.java index e10fc49eccad..886706713238 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ShibbolethLoginFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ShibbolethLoginFilter.java @@ -9,11 +9,11 @@ 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 jakarta.servlet.FilterChain; +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.LogManager; import org.apache.logging.log4j.Logger; @@ -56,9 +56,9 @@ public class ShibbolethLoginFilter extends StatelessLoginFilter { private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); - public ShibbolethLoginFilter(String url, AuthenticationManager authenticationManager, + public ShibbolethLoginFilter(String url, String httpMethod, AuthenticationManager authenticationManager, RestAuthenticationService restAuthenticationService) { - super(url, authenticationManager, restAuthenticationService); + super(url, httpMethod, authenticationManager, restAuthenticationService); } @Override diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessAuthenticationFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessAuthenticationFilter.java index c774c1836452..c328928afafb 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessAuthenticationFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessAuthenticationFilter.java @@ -11,11 +11,11 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.utils.ContextUtil; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessLoginFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessLoginFilter.java index 7dd5ee3beab1..cfae6bfcb42b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessLoginFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessLoginFilter.java @@ -8,11 +8,11 @@ package org.dspace.app.rest.security; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.security.authentication.AuthenticationManager; @@ -41,9 +41,20 @@ public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter public void afterPropertiesSet() { } - public StatelessLoginFilter(String url, AuthenticationManager authenticationManager, + /** + * Initialize a StatelessLoginFilter for the given URL and HTTP method. This login filter will ONLY attempt + * authentication for requests that match this URL and method. The URL & method are defined in the configuration + * in WebSecurityConfiguration. + * @see org.dspace.app.rest.security.WebSecurityConfiguration + * @param url URL path to attempt to authenticate (e.g. "/api/authn/login") + * @param httpMethod HTTP method to attempt to authentication (e.g. "POST") + * @param authenticationManager Spring Security AuthenticationManager to use for authentication + * @param restAuthenticationService DSpace RestAuthenticationService to use for authentication + */ + public StatelessLoginFilter(String url, String httpMethod, AuthenticationManager authenticationManager, RestAuthenticationService restAuthenticationService) { - super(new AntPathRequestMatcher(url)); + // NOTE: attemptAuthentication() below will only be triggered by requests that match both this URL and method + super(new AntPathRequestMatcher(url, httpMethod)); this.authenticationManager = authenticationManager; this.restAuthenticationService = restAuthenticationService; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityConfiguration.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityConfiguration.java index b29f52939d20..6fb8f285d1a4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityConfiguration.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityConfiguration.java @@ -19,15 +19,15 @@ import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutFilter; -import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; import org.springframework.security.web.csrf.CsrfTokenRepository; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @@ -40,7 +40,7 @@ @EnableWebSecurity @Configuration @EnableConfigurationProperties(SecurityProperties.class) -public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { +public class WebSecurityConfiguration { public static final String ADMIN_GRANT = "ADMIN"; public static final String AUTHENTICATED_GRANT = "AUTHENTICATED"; @@ -67,101 +67,100 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Value("${management.endpoints.web.base-path:/actuator}") private String actuatorBasePath; - @Override - public void configure(WebSecurity webSecurity) throws Exception { - // Define URL patterns which Spring Security will ignore entirely. - webSecurity - .ignoring() - // These /login request types are purposefully unsecured, as they all throw errors. - .antMatchers(HttpMethod.GET, "/api/authn/login") - .antMatchers(HttpMethod.PUT, "/api/authn/login") - .antMatchers(HttpMethod.PATCH, "/api/authn/login") - .antMatchers(HttpMethod.DELETE, "/api/authn/login"); + /** + * Create a Spring Security AuthenticationManager with our custom AuthenticationProvider + * @return AuthenticationManager + */ + @Bean + public AuthenticationManager authenticationManager() { + ProviderManager manager = new ProviderManager(ePersonRestAuthenticationProvider); + return manager; + } + /** + * Bean to customize security on specific endpoints + * @param http HttpSecurity + */ + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + // Get the current AuthenticationManager (defined above) to apply filters below + AuthenticationManager authenticationManager = authenticationManager(); - @Override - protected void configure(HttpSecurity http) throws Exception { // Configure authentication requirements for ${dspace.server.url}/api/ URL only // NOTE: REST API is hardcoded to respond on /api/. Other modules (OAI, SWORD, IIIF, etc) use other root paths. - http.requestMatchers() - .antMatchers("/api/**", "/iiif/**", actuatorBasePath + "/**", "/signposting/**") - .and() - // Enable Spring Security authorization on these paths - .authorizeRequests() - // Allow POST by anyone on the login endpoint - .antMatchers(HttpMethod.POST,"/api/authn/login").permitAll() - // Everyone can call GET on the status endpoint (used to check your authentication status) - .antMatchers(HttpMethod.GET, "/api/authn/status").permitAll() - .antMatchers(HttpMethod.GET, actuatorBasePath + "/info").hasAnyAuthority(ADMIN_GRANT) - .and() + http.securityMatcher("/api/**", "/iiif/**", actuatorBasePath + "/**", "/signposting/**") + .authorizeHttpRequests((requests) -> requests + // Ensure /actuator/info endpoint is restricted to admins + .requestMatchers(new AntPathRequestMatcher(actuatorBasePath + "/info", HttpMethod.GET.name())) + .hasAnyAuthority(ADMIN_GRANT) + // All other requests should be permitted at this layer because we check permissions on each method + // via @PreAuthorize annotations. As this code runs first, we must permitAll() here in order to pass + // the request on to those annotations. + .anyRequest().permitAll()) // Tell Spring to not create Sessions - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // Anonymous requests should have the "ANONYMOUS" security grant - .anonymous().authorities(ANONYMOUS_GRANT).and() + .anonymous((anonymous) -> anonymous.authorities(ANONYMOUS_GRANT)) // Wire up the HttpServletRequest with the current SecurityContext values - .servletApi().and() + .servletApi(Customizer.withDefaults()) // Enable CORS for Spring Security (see CORS settings in Application and ApplicationConfig) - .cors().and() + .cors(Customizer.withDefaults()) // Enable CSRF protection with custom csrfTokenRepository and custom sessionAuthenticationStrategy // (both are defined below as methods). // While we primarily use JWT in headers, CSRF protection is needed because we also support JWT via Cookies - .csrf() + .csrf((csrf) -> csrf .csrfTokenRepository(this.csrfTokenRepository()) - .sessionAuthenticationStrategy(this.sessionAuthenticationStrategy()) - .and() - .exceptionHandling() + .sessionAuthenticationStrategy(this.dSpaceCsrfAuthenticationStrategy()) + .csrfTokenRequestHandler(new DSpaceCsrfTokenRequestHandler())) + .exceptionHandling((exceptionHandling) -> exceptionHandling // Return 401 on authorization failures with a correct WWWW-Authenticate header .authenticationEntryPoint(new DSpace401AuthenticationEntryPoint(restAuthenticationService)) // Custom handler for AccessDeniedExceptions, including CSRF exceptions .accessDeniedHandler(accessDeniedHandler) - .and() - + ) // Logout configuration - .logout() + .logout((logout) -> logout // On logout, clear the "session" salt .addLogoutHandler(customLogoutHandler) // Configure the logout entry point & require POST .logoutRequestMatcher(new AntPathRequestMatcher("/api/authn/logout", HttpMethod.POST.name())) // When logout is successful, return OK (204) status .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.NO_CONTENT)) - // Everyone can call this endpoint - .permitAll() - .and() - + ) // Add a filter before any request to handle DSpace IP-based authorization/authentication // (e.g. anonymous users may be added to special DSpace groups if they are in a given IP range) - .addFilterBefore(new AnonymousAdditionalAuthorizationFilter(authenticationManager(), authenticationService), + .addFilterBefore(new AnonymousAdditionalAuthorizationFilter(authenticationManager, authenticationService), StatelessAuthenticationFilter.class) - // Add a filter before our login endpoints to do the authentication based on the data in the HTTP request - .addFilterBefore(new StatelessLoginFilter("/api/authn/login", authenticationManager(), - restAuthenticationService), + // Add a filter before our login endpoints to do the authentication based on the data in the HTTP request. + // This login endpoint only responds to POST as it is used for PasswordAuthentication + .addFilterBefore(new StatelessLoginFilter("/api/authn/login", HttpMethod.POST.name(), + authenticationManager, restAuthenticationService), LogoutFilter.class) - // Add a filter before our shibboleth endpoints to do the authentication based on the data in the - // HTTP request - .addFilterBefore(new ShibbolethLoginFilter("/api/authn/shibboleth", authenticationManager(), - restAuthenticationService), + // Add a filter before our shibboleth endpoints to do the authentication based on the data in the HTTP + // request. This endpoint only responds to GET as the actual authentication is performed by Shibboleth, + // which then redirects to this endpoint to forward the authentication data to DSpace. + .addFilterBefore(new ShibbolethLoginFilter("/api/authn/shibboleth", HttpMethod.GET.name(), + authenticationManager, restAuthenticationService), LogoutFilter.class) - //Add a filter before our ORCID endpoints to do the authentication based on the data in the - // HTTP request - .addFilterBefore(new OrcidLoginFilter("/api/authn/orcid", authenticationManager(), - restAuthenticationService), + // Add a filter before our ORCID endpoints to do the authentication based on the data in the HTTP request. + // This endpoint only responds to GET as the actual authentication is performed by ORCID, which then + // redirects to this endpoint to forward the authentication data to DSpace. + .addFilterBefore(new OrcidLoginFilter("/api/authn/orcid", HttpMethod.GET.name(), + authenticationManager, restAuthenticationService), LogoutFilter.class) - //Add a filter before our OIDC endpoints to do the authentication based on the data in the - // HTTP request - .addFilterBefore(new OidcLoginFilter("/api/authn/oidc", authenticationManager(), - restAuthenticationService), + // Add a filter before our OIDC endpoints to do the authentication based on the data in the HTTP request. + // This endpoint only responds to GET as the actual authentication is performed by OIDC, which then + // redirects to this endpoint to forward the authentication data to DSpace. + .addFilterBefore(new OidcLoginFilter("/api/authn/oidc", HttpMethod.GET.name(), + authenticationManager, restAuthenticationService), LogoutFilter.class) // Add a custom Token based authentication filter based on the token previously given to the client // before each URL - .addFilterBefore(new StatelessAuthenticationFilter(authenticationManager(), restAuthenticationService, + .addFilterBefore(new StatelessAuthenticationFilter(authenticationManager, restAuthenticationService, ePersonRestAuthenticationProvider, requestService), StatelessLoginFilter.class); - } - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.authenticationProvider(ePersonRestAuthenticationProvider); + return http.build(); } /** @@ -187,8 +186,13 @@ public CsrfTokenRepository csrfTokenRepository() { /** * Returns a custom DSpaceCsrfAuthenticationStrategy, which ensures that (after authenticating) the CSRF token * is only refreshed when it is used (or attempted to be used) by the client. + * + * This is defined as a bean so that it can also be used in other code to reset CSRF Tokens, see + * JWTTokenRestAuthenticationServiceImpl */ - private SessionAuthenticationStrategy sessionAuthenticationStrategy() { + @Lazy + @Bean + public DSpaceCsrfAuthenticationStrategy dSpaceCsrfAuthenticationStrategy() { return new DSpaceCsrfAuthenticationStrategy(csrfTokenRepository()); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java index 364e93e297d8..35772e41fd67 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java @@ -8,10 +8,10 @@ package org.dspace.app.rest.security; import java.util.List; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.core.GenericTypeResolver; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/AuthenticationMethodClaimProvider.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/AuthenticationMethodClaimProvider.java index dd22a8a1deb7..6e1469fa9153 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/AuthenticationMethodClaimProvider.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/AuthenticationMethodClaimProvider.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.text.ParseException; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jwt.JWTClaimsSet; +import jakarta.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.authenticate.service.AuthenticationService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/EPersonClaimProvider.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/EPersonClaimProvider.java index 39b61427b7bd..9a9142fbd1b1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/EPersonClaimProvider.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/EPersonClaimProvider.java @@ -9,9 +9,9 @@ import java.sql.SQLException; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jwt.JWTClaimsSet; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTClaimProvider.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTClaimProvider.java index f8ee6a44de3a..64df3b20eaf6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTClaimProvider.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTClaimProvider.java @@ -8,9 +8,9 @@ package org.dspace.app.rest.security.jwt; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jwt.JWTClaimsSet; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTTokenHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTTokenHandler.java index 6143361a373e..727267744fb1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTTokenHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/JWTTokenHandler.java @@ -11,7 +11,6 @@ import java.text.ParseException; import java.util.Date; import java.util.List; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jose.CompressionAlgorithm; import com.nimbusds.jose.EncryptionMethod; @@ -31,6 +30,7 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import com.nimbusds.jwt.util.DateUtils; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; 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 aace04af1eae..a2928fc96fb1 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 @@ -11,17 +11,18 @@ import java.sql.SQLException; import java.text.ParseException; import java.util.Iterator; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.HttpHeaders; import com.nimbusds.jose.JOSEException; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.ws.rs.core.HttpHeaders; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.model.wrapper.AuthenticationToken; import org.dspace.app.rest.security.DSpaceAuthentication; +import org.dspace.app.rest.security.DSpaceCsrfAuthenticationStrategy; import org.dspace.app.rest.security.RestAuthenticationService; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.authenticate.AuthenticationMethod; @@ -33,8 +34,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.http.ResponseCookie; -import org.springframework.security.web.csrf.CsrfToken; -import org.springframework.security.web.csrf.CsrfTokenRepository; import org.springframework.stereotype.Component; /** @@ -67,7 +66,7 @@ public class JWTTokenRestAuthenticationServiceImpl implements RestAuthentication @Lazy @Autowired - private CsrfTokenRepository csrfTokenRepository; + private DSpaceCsrfAuthenticationStrategy dspaceCsrfAuthenticationStrategy; @Override public void afterPropertiesSet() throws Exception { @@ -332,11 +331,8 @@ private boolean hasAuthorizationCookie(HttpServletRequest request) { * @param response current response */ private void resetCSRFToken(HttpServletRequest request, HttpServletResponse response) { - // Remove current CSRF token & generate a new one - // We do this as we want the token to change anytime you login or logout - csrfTokenRepository.saveToken(null, request, response); - CsrfToken newToken = csrfTokenRepository.generateToken(request); - csrfTokenRepository.saveToken(newToken, request, response); + // Use our custom CsrfAuthenticationStrategy class to force reset the CSRF token in Spring Security + dspaceCsrfAuthenticationStrategy.resetCSRFToken(request, response); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/ShortLivedJWTTokenHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/ShortLivedJWTTokenHandler.java index fc4ab39407a4..ac7a73a796ef 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/ShortLivedJWTTokenHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/ShortLivedJWTTokenHandler.java @@ -8,7 +8,6 @@ package org.dspace.app.rest.security.jwt; import java.util.Date; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.JWSVerifier; @@ -16,6 +15,7 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import com.nimbusds.jwt.util.DateUtils; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.dspace.core.Context; import org.dspace.eperson.EPerson; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProvider.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProvider.java index bed8b9a58b5c..970bd812d3d8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProvider.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProvider.java @@ -13,9 +13,9 @@ import java.util.List; import java.util.UUID; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jwt.JWTClaimsSet; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.collections4.CollectionUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/controller/LinksetRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/controller/LinksetRestController.java index 2a940d79aba4..b1731fb10bb7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/controller/LinksetRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/controller/LinksetRestController.java @@ -16,9 +16,9 @@ import java.util.List; import java.util.UUID; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.signposting.converter.LinksetRestMessageConverter; import org.dspace.app.rest.signposting.model.Linkset; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/SignPostingProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/SignPostingProcessor.java index efcfd50ab512..a5cadf4627df 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/SignPostingProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/SignPostingProcessor.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; 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..97eb9f2a546d 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 @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor.bitstream; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; 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..32928dfa8892 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 @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor.bitstream; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; 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..8889a415d327 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 @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor.bitstream; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; 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..f3a9e35198a7 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 @@ -14,8 +14,8 @@ import java.text.MessageFormat; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; 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..0b91e57f7b3f 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 @@ -9,8 +9,8 @@ import java.sql.SQLException; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; 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..20091e6d0992 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 @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor.item; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemIdentifierProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemIdentifierProcessor.java index c5ebe958d97d..ba4794f37813 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemIdentifierProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/item/ItemIdentifierProcessor.java @@ -12,8 +12,8 @@ import java.text.MessageFormat; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; 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..b60ee35d7fe4 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 @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor.item; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; 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..2d09e5616171 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 @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor.item; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; 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..49b3612cd92c 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 @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor.item; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.dspace.app.rest.signposting.model.LinksetNode; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/metadata/MetadataDescribesSignpostingProcessor.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/metadata/MetadataDescribesSignpostingProcessor.java index baae16b88389..8bf123dd0478 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/metadata/MetadataDescribesSignpostingProcessor.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/processor/metadata/MetadataDescribesSignpostingProcessor.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.processor.metadata; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.app.rest.signposting.model.LinksetRelationType; import org.dspace.content.Item; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/LinksetService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/LinksetService.java index 33d0c10b7415..c6ad757e4e92 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/LinksetService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/signposting/service/LinksetService.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.signposting.service; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.signposting.model.LinksetNode; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; 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..5b28817c9438 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 @@ -11,8 +11,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.dspace.app.rest.security.BitstreamMetadataReadPermissionEvaluatorPlugin; import org.dspace.app.rest.signposting.model.LinksetNode; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/DataProcessingStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/DataProcessingStep.java index f8aeacbf08a4..660d677cdde5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/DataProcessingStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/DataProcessingStep.java @@ -10,8 +10,8 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.ErrorRest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.submit.step.validation.Validation; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/SubmissionService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/SubmissionService.java index 93d3867d9205..66df73e7cd70 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/SubmissionService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/SubmissionService.java @@ -10,10 +10,11 @@ import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.converter.ConverterService; @@ -26,9 +27,11 @@ import org.dspace.app.rest.model.CheckSumRest; import org.dspace.app.rest.model.ErrorRest; import org.dspace.app.rest.model.MetadataValueRest; +import org.dspace.app.rest.model.PotentialDuplicateRest; import org.dspace.app.rest.model.WorkspaceItemRest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.step.DataCCLicense; +import org.dspace.app.rest.model.step.DataDuplicateDetection; import org.dspace.app.rest.model.step.DataUpload; import org.dspace.app.rest.model.step.UploadBitstreamRest; import org.dspace.app.rest.projection.Projection; @@ -47,11 +50,14 @@ import org.dspace.content.MetadataValue; import org.dspace.content.WorkspaceItem; import org.dspace.content.service.CollectionService; +import org.dspace.content.service.DuplicateDetectionService; import org.dspace.content.service.ItemService; import org.dspace.content.service.WorkspaceItemService; +import org.dspace.content.virtual.PotentialDuplicate; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.Utils; +import org.dspace.discovery.SearchServiceException; import org.dspace.license.service.CreativeCommonsService; import org.dspace.services.ConfigurationService; import org.dspace.services.RequestService; @@ -64,6 +70,7 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.data.rest.webmvc.json.patch.PatchException; import org.springframework.jdbc.datasource.init.UncategorizedScriptException; import org.springframework.stereotype.Component; @@ -101,6 +108,8 @@ public class SubmissionService { @Autowired private org.dspace.app.rest.utils.Utils utils; private SubmissionConfigService submissionConfigService; + @Autowired + private DuplicateDetectionService duplicateDetectionService; public SubmissionService() throws SubmissionConfigReaderException { submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService(); @@ -313,6 +322,51 @@ public DataCCLicense getDataCCLicense(InProgressSubmission obj) return result; } + /** + * Prepare section data containing a list of potential duplicates, for use in submission steps. + * This method belongs in SubmissionService and not DuplicateDetectionService because it depends on + * the DataDuplicateDetection class which only appears in the REST project. + * + * @param context DSpace context + * @param obj The in-progress submission object + * @return A DataDuplicateDetection object which implements SectionData for direct use in + * a submission step (see DuplicateDetectionStep) + * @throws SearchServiceException if an error is encountered during Discovery search + */ + public DataDuplicateDetection getDataDuplicateDetection(Context context, InProgressSubmission obj) + throws SearchServiceException { + // Test for a valid object or throw a not found exception + if (obj == null) { + throw new ResourceNotFoundException("Duplicate data step could not find valid in-progress submission obj"); + } + // Initialise an empty section data object + DataDuplicateDetection data = new DataDuplicateDetection(); + + // Get the item for this submission object, throw a not found exception if null + Item item = obj.getItem(); + if (item == null) { + throw new ResourceNotFoundException("Duplicate data step could not find valid item for the" + + " current in-progress submission obj id=" + obj.getID()); + } + // Initialise empty list of PotentialDuplicateRest objects for use in the section data object + List potentialDuplicateRestList = new LinkedList<>(); + + // Get discovery search result for a duplicate detection search based on this item and populate + // the list of REST objects + List potentialDuplicates = duplicateDetectionService.getPotentialDuplicates(context, item); + for (PotentialDuplicate potentialDuplicate : potentialDuplicates) { + // Convert and add the potential duplicate to the list + potentialDuplicateRestList.add(converter.toRest( + potentialDuplicate, utils.obtainProjection())); + } + + // Set the final duplicates list of the section data object + data.setPotentialDuplicates(potentialDuplicateRestList); + + // Return section data + return data; + } + /** * Utility method used by the {@link WorkspaceItemRestRepository} and * {@link WorkflowItemRestRepository} to deal with the upload in an inprogress diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionAddPatchOperation.java index 750c50524d3e..ae8040136f39 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionAddPatchOperation.java @@ -12,8 +12,8 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.AccessConditionDTO; import org.dspace.app.rest.model.patch.LateObjectEvaluator; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionDiscoverableReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionDiscoverableReplacePatchOperation.java index bcc0dce65fac..188a5e8dbe86 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionDiscoverableReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionDiscoverableReplacePatchOperation.java @@ -7,8 +7,8 @@ */ package org.dspace.app.rest.submit.factory.impl; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.BooleanUtils; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.content.InProgressSubmission; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionRemovePatchOperation.java index 61ed7e28c9ac..894a8234dc4b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionRemovePatchOperation.java @@ -7,8 +7,8 @@ */ package org.dspace.app.rest.submit.factory.impl; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.AccessConditionDTO; import org.dspace.authorize.ResourcePolicy; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionReplacePatchOperation.java index 22ea6a45af4f..ff34559a903b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AccessConditionReplacePatchOperation.java @@ -14,8 +14,8 @@ import java.util.Date; import java.util.List; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AddPatchOperation.java index 354208c3e536..d903325edaff 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/AddPatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.content.InProgressSubmission; import org.dspace.core.Context; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueAddPatchOperation.java index f9ef16fa58c3..e74a2835368d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueAddPatchOperation.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.factory.impl; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.LateObjectEvaluator; import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils; @@ -67,10 +67,11 @@ void add(Context context, HttpServletRequest currentRequest, InProgressSubmissio // call with "-" or "index-based" we should receive only single // object member MetadataValueRest object = evaluateSingleObject((LateObjectEvaluator) value); + String mdString = split[3]; // check if is not empty List metadataByMetadataString = - bitstreamService.getMetadataByMetadataString(b,split[3]); - Assert.notEmpty(metadataByMetadataString); + bitstreamService.getMetadataByMetadataString(b,mdString); + Assert.notEmpty(metadataByMetadataString, "No metadata fields match ".concat(mdString)); if (split.length > 4) { String controlChar = split[4]; switch (controlChar) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueMovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueMovePatchOperation.java index 2726363b4c0e..4020cdeeb458 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueMovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueMovePatchOperation.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.factory.impl; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueRemovePatchOperation.java index 6bbb7bb0328a..5efa36edcdc4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueRemovePatchOperation.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.factory.impl; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueReplacePatchOperation.java index 842771538c8b..2f0e9025daa7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMetadataValueReplacePatchOperation.java @@ -9,8 +9,8 @@ import java.sql.SQLException; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.LateObjectEvaluator; import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils; @@ -67,7 +67,7 @@ private void replace(Context context, Bitstream b, String[] split, Object value) throws SQLException, IllegalArgumentException, IllegalAccessException { String mdString = split[3]; List metadataByMetadataString = bitstreamService.getMetadataByMetadataString(b, mdString); - Assert.notEmpty(metadataByMetadataString); + Assert.notEmpty(metadataByMetadataString, "No metadata fields match ".concat(mdString)); int index = Integer.parseInt(split[4]); // if split size is one so we have a call to initialize or replace diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMovePatchOperation.java index 27d01a8581dc..5b6842b8e708 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamMovePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.InProgressSubmission; import org.dspace.content.service.BundleService; import org.dspace.content.service.ItemService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamRemovePatchOperation.java index 706834930027..ec9d178f14ec 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamRemovePatchOperation.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.factory.impl; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.InProgressSubmission; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyAddPatchOperation.java index 5e6274d78f1e..158ef4b613d9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyAddPatchOperation.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.collections.CollectionUtils; import org.dspace.app.rest.model.AccessConditionDTO; import org.dspace.app.rest.model.patch.LateObjectEvaluator; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyRemovePatchOperation.java index e936b0b0c7e9..986d6062bcd6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyRemovePatchOperation.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.factory.impl; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.AccessConditionDTO; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.service.ResourcePolicyService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyReplacePatchOperation.java index 19acc7b9f293..565287e9454a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/BitstreamResourcePolicyReplacePatchOperation.java @@ -11,8 +11,8 @@ import java.util.Date; import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.ResourcePolicyRest; import org.dspace.app.rest.model.patch.LateObjectEvaluator; import org.dspace.authorize.ResourcePolicy; 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 ec4dff9f6c51..c93a74443dd0 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 @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CCLicenseRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CCLicenseRemovePatchOperation.java index b17749fe4e04..57d9b60e3135 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CCLicenseRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CCLicenseRemovePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CollectionReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CollectionReplacePatchOperation.java index 3cadb443d9cc..a26982c37760 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CollectionReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/CollectionReplacePatchOperation.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.factory.impl; import java.sql.SQLException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.util.DCInputsReaderException; import org.dspace.content.Collection; import org.dspace.content.InProgressSubmission; 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..54dfa6b02c04 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 @@ -12,8 +12,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.UnprocessableEntityException; @@ -103,10 +103,11 @@ void add(Context context, HttpServletRequest currentRequest, InProgressSubmissio // call with "-" or "index-based" we should receive only single // object member MetadataValueRest object = evaluateSingleObject((LateObjectEvaluator) value); + String mdString = split[0]; // check if is not empty List metadataByMetadataString = itemService.getMetadataByMetadataString(source.getItem(), - split[0]); - Assert.notEmpty(metadataByMetadataString); + mdString); + Assert.notEmpty(metadataByMetadataString, "No metadata fields match ".concat(mdString)); if (split.length > 1) { String controlChar = split[1]; switch (controlChar) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueMovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueMovePatchOperation.java index 17712f71482c..d38a5346429b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueMovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueMovePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; import org.dspace.content.service.ItemService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueRemovePatchOperation.java index 95206bc5ca9a..cf62f641b940 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueRemovePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; import org.dspace.content.service.ItemService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueReplacePatchOperation.java index 148984cbfd4d..415c5b6712ab 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueReplacePatchOperation.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.factory.impl; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.LateObjectEvaluator; import org.dspace.content.InProgressSubmission; @@ -53,10 +53,10 @@ public class ItemMetadataValueReplacePatchOperation extends MetadataValueReplace void replace(Context context, HttpServletRequest currentRequest, InProgressSubmission source, String path, Object value) throws Exception { String[] split = getAbsolutePath(path).split("/"); - + String mdString = split[0]; List metadataByMetadataString = itemService.getMetadataByMetadataString(source.getItem(), - split[0]); - Assert.notEmpty(metadataByMetadataString); + mdString); + Assert.notEmpty(metadataByMetadataString, "No metadata fields match ".concat(mdString)); int index = Integer.parseInt(split[1]); // if split size is one so we have a call to initialize or replace diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseAddPatchOperation.java index 6bbd4aae7572..bae40565294f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseAddPatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.BooleanUtils; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseRemovePatchOperation.java index 39ffdbbd67d9..75c244bf9c6f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseRemovePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; import org.dspace.content.service.ItemService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseReplacePatchOperation.java index bdb3051010a0..699b27ab0e22 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/LicenseReplacePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.BooleanUtils; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/MovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/MovePatchOperation.java index 750a2bc71ba1..fc6bc2736e60 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/MovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/MovePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.MoveOperation; import org.dspace.app.rest.model.patch.Operation; import org.dspace.content.InProgressSubmission; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceAddPatchOperation.java index 94f5e94d9b81..ff63fc49fb9c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceAddPatchOperation.java @@ -12,8 +12,8 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.ldn.NotifyPatternToTrigger; import org.dspace.app.ldn.NotifyServiceEntity; import org.dspace.app.ldn.service.NotifyPatternToTriggerService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceRemovePatchOperation.java index c1304f0b91f1..4c8a440a5643 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceRemovePatchOperation.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.factory.impl; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.ldn.NotifyPatternToTrigger; import org.dspace.app.ldn.service.NotifyPatternToTriggerService; import org.dspace.app.rest.exception.UnprocessableEntityException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceReplacePatchOperation.java index d7988da0029d..23946221fb68 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/NotifyServiceReplacePatchOperation.java @@ -9,8 +9,8 @@ import java.util.List; import java.util.Set; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.ldn.NotifyPatternToTrigger; import org.dspace.app.ldn.NotifyServiceEntity; import org.dspace.app.ldn.service.NotifyPatternToTriggerService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PatchOperation.java index 230d931e83f7..e01a4e5f430e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PatchOperation.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.LateObjectEvaluator; import org.dspace.app.rest.model.patch.Operation; import org.dspace.content.InProgressSubmission; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamAddPatchOperation.java index 5653678a502a..6704c8c2bbcc 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamAddPatchOperation.java @@ -13,8 +13,8 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamRemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamRemovePatchOperation.java index 57b688898adc..c6c8f4d6c5ee 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamRemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamRemovePatchOperation.java @@ -10,8 +10,8 @@ import static org.dspace.core.Constants.CONTENT_BUNDLE_NAME; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.content.Bundle; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamReplacePatchOperation.java index abd59101f448..8ebeb78d341b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/PrimaryBitstreamReplacePatchOperation.java @@ -13,8 +13,8 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/RemovePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/RemovePatchOperation.java index 0fa50562b3f4..b90fd1875f4e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/RemovePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/RemovePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.content.InProgressSubmission; import org.dspace.core.Context; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ReplacePatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ReplacePatchOperation.java index b5ca61f54359..f24fbde59aaa 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ReplacePatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ReplacePatchOperation.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.factory.impl; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.content.InProgressSubmission; import org.dspace.core.Context; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/AccessConditionStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/AccessConditionStep.java index 070e4a3cbfeb..29353d0ffdf4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/AccessConditionStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/AccessConditionStep.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.AccessConditionDTO; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/CCLicenseStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/CCLicenseStep.java index 34ae259090e9..357c0c48dd26 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/CCLicenseStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/CCLicenseStep.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.step; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.step.DataCCLicense; import org.dspace.app.rest.submit.AbstractProcessingStep; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/CollectionStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/CollectionStep.java index 09e19f298012..b7b93fe2d3ff 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/CollectionStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/CollectionStep.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.step; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.submit.DataProcessingStep; import org.dspace.app.rest.submit.SubmissionService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/DescribeStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/DescribeStep.java index ee81d14ca7a6..5d1f104b92e4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/DescribeStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/DescribeStep.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.UnprocessableEntityException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/DuplicateDetectionStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/DuplicateDetectionStep.java new file mode 100644 index 000000000000..032a27f83cea --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/DuplicateDetectionStep.java @@ -0,0 +1,112 @@ +/** + * 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.submit.step; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.model.step.DataDuplicateDetection; +import org.dspace.app.rest.submit.AbstractProcessingStep; +import org.dspace.app.rest.submit.SubmissionService; +import org.dspace.app.rest.utils.ContextUtil; +import org.dspace.app.util.SubmissionStepConfig; +import org.dspace.content.InProgressSubmission; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.core.Context; +import org.dspace.handle.service.HandleService; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.services.model.Request; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Submission processing step to detect potential duplicates of this item and list them so that + * the submitter can choose to cancel or continue with their submission + * + * @author Kim Shepherd + */ +public class DuplicateDetectionStep extends AbstractProcessingStep { + + private static final Logger log = LogManager.getLogger(DuplicateDetectionStep.class); + + @Autowired(required = true) + protected HandleService handleService; + @Autowired(required = true) + protected ContentServiceFactory contentServiceFactory; + + /** + * Override DataProcessing.getData, return a list of potential duplicates + * + * @param submissionService The submission service + * @param obj The workspace or workflow item + * @param config The submission step configuration + * @return A simple DataIdentifiers bean containing doi, handle and list of other identifiers + */ + @Override + public DataDuplicateDetection getData(SubmissionService submissionService, InProgressSubmission obj, + SubmissionStepConfig config) throws Exception { + // Validate in progress submission object and wrapped item + if (obj == null) { + throw new IllegalArgumentException("Null in-progress wrapper object"); + } + if (obj.getItem() == null) { + throw new IllegalArgumentException("Null in-progress item"); + } + // Immediately return an empty if this feature is not configured + if (!configurationService.getBooleanProperty("duplicate.enable", false)) { + log.debug("Duplicate detection is not enabled, returning empty section"); + return new DataDuplicateDetection(); + } + // Validate context + Context context = getContext(); + if (context == null) { + throw new ServletException("Null context"); + } + + // Return the constructed data section + return submissionService.getDataDuplicateDetection(context, obj); + } + + /** + * Utility method to get DSpace context from the HTTP request + * @return DSpace context + */ + private Context getContext() { + Context context; + Request currentRequest = DSpaceServicesFactory.getInstance().getRequestService().getCurrentRequest(); + if (currentRequest != null) { + HttpServletRequest request = currentRequest.getHttpServletRequest(); + context = ContextUtil.obtainContext(request); + } else { + context = new Context(); + } + + return context; + } + + /** + * This step is currently just for displaying identifiers and does not take additional patch operations + * @param context + * the DSpace context + * @param currentRequest + * the http request + * @param source + * the in progress submission + * @param op + * the json patch operation + * @param stepConf + * @throws Exception + */ + @Override + public void doPatchProcessing(Context context, HttpServletRequest currentRequest, InProgressSubmission source, + Operation op, SubmissionStepConfig stepConf) throws Exception { + log.warn("Not implemented"); + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/LicenseStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/LicenseStep.java index 053530d862fa..f374dcd7881c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/LicenseStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/LicenseStep.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.step; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.atteo.evo.inflector.English; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.BitstreamRest; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/NotifyStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/NotifyStep.java index b3e3d06c4727..e6297217a458 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/NotifyStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/NotifyStep.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.submit.step; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.step.DataNotify; import org.dspace.app.rest.submit.AbstractProcessingStep; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/SherpaPolicyStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/SherpaPolicyStep.java index d37182904bf0..206b3fab5974 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/SherpaPolicyStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/SherpaPolicyStep.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.submit.step; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.step.SherpaPolicy; import org.dspace.app.rest.submit.AbstractProcessingStep; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/ShowIdentifiersStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/ShowIdentifiersStep.java index e63d38ab2e36..47eac49f499c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/ShowIdentifiersStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/ShowIdentifiersStep.java @@ -10,8 +10,8 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; 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 1dea6bbeeb7a..479e307bd229 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,8 +11,8 @@ import java.io.InputStream; import java.util.List; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.UnprocessableEntityException; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ContextUtil.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ContextUtil.java index 73813c01b528..3ba853dbd62e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ContextUtil.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ContextUtil.java @@ -10,10 +10,10 @@ import java.sql.SQLException; import java.util.Enumeration; import java.util.Locale; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.core.Context; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DSpaceAPIRequestLoggingFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DSpaceAPIRequestLoggingFilter.java index 6dfebe320354..36888a740376 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DSpaceAPIRequestLoggingFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DSpaceAPIRequestLoggingFilter.java @@ -8,8 +8,8 @@ package org.dspace.app.rest.utils; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.ThreadContext; import org.dspace.services.ConfigurationService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/HttpHeadersInitializer.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/HttpHeadersInitializer.java index 662223d187f5..d1b80c36750b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/HttpHeadersInitializer.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/HttpHeadersInitializer.java @@ -7,17 +7,17 @@ */ package org.dspace.app.rest.utils; +import static jakarta.mail.internet.MimeUtility.encodeText; import static java.util.Objects.isNull; import static java.util.Objects.nonNull; -import static javax.mail.internet.MimeUtility.encodeText; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.Objects; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; 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 8db5a74eefba..b358e785c3b3 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 @@ -27,6 +27,12 @@ private RegexUtils(){} public static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID = "/{uuid:" + REGEX_UUID + "}"; + /** + * Regular expression in the request mapping to accept LDN identifiers + */ + public static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_URN_UUID = + "/{id:^urn:uuid:" + REGEX_UUID + "}"; + /** * Regular expression in the request mapping to accept a string as identifier but not the other kind of * identifier (digits or uuid) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java index c08d5a04a781..f66d794a8fe0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java @@ -43,10 +43,10 @@ import java.util.Set; import java.util.TreeSet; import java.util.UUID; -import javax.annotation.Nullable; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/test-discovery.xml b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/test-discovery.xml index ea654ac55cd4..dd78bffda337 100644 --- a/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/test-discovery.xml +++ b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/test-discovery.xml @@ -89,7 +89,9 @@ - + + + @@ -1115,4 +1117,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:LDNMessageEntity + + + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_INCOMING} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_OUTGOING} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rdf/RdfIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rdf/RdfIT.java index 85ab3dcadd78..8db30d4ffb03 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rdf/RdfIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rdf/RdfIT.java @@ -117,7 +117,7 @@ public void serializationTest() throws Exception { // Turtle response should include the RDF identifier of Community assertThat(response.getBody(), containsString(communityIdentifier)); // Turtle response should also note that this Community is part of our Site object - assertThat(response.getBody(), containsString("dspace:isPartOfRepository <" + siteIdentifier + "> ;")); + assertThat(response.getBody(), containsString("dspace:isPartOfRepository <" + siteIdentifier + ">;")); } @Test 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 4878cdecab83..892e83c79da0 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 @@ -17,8 +17,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthenticationRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthenticationRestControllerIT.java index 1da807ad7180..9edb0a2a9f40 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthenticationRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthenticationRestControllerIT.java @@ -22,7 +22,6 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -36,11 +35,11 @@ import java.text.ParseException; import java.util.Base64; import java.util.Map; -import javax.servlet.http.Cookie; import com.fasterxml.jackson.databind.ObjectMapper; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; +import jakarta.servlet.http.Cookie; import org.apache.commons.codec.CharEncoding; import org.apache.commons.io.IOUtils; import org.dspace.app.rest.authorization.Authorization; @@ -791,7 +790,7 @@ public void testRefreshTokenWithInvalidCSRF() throws Exception { // POSTing to /login should be a valid request...it just refreshes your token (see testRefreshToken()) // However, in this case, we are POSTing with an *INVALID* CSRF Token in Header. - getClient().perform(post("/api/authn/login").with(csrf().useInvalidToken().asHeader()) + getClient().perform(post("/api/authn/login").with(invalidCsrfToken()) .secure(true) .cookie(cookies)) // Should return a 403 Forbidden, for an invalid CSRF token @@ -1401,7 +1400,7 @@ public void testShortLivedTokenWithCSRFSentViaParam() throws Exception { // Same request as prior method, but this time we are sending the CSRF token as a querystring param. // NOTE: getClient() method defaults to sending CSRF tokens as Headers, so we are overriding its behavior here - getClient(token).perform(post("/api/authn/shortlivedtokens").with(csrf())) + getClient(token).perform(post("/api/authn/shortlivedtokens").with(validCsrfTokenViaParam())) // BECAUSE we sent the CSRF token on querystring, it should be regenerated & a new token // is sent back (in cookie and header). .andExpect(cookie().exists("DSPACE-XSRF-COOKIE")) 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 049b9b4318f7..713d8b87f673 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 @@ -7,8 +7,8 @@ */ package org.dspace.app.rest; +import static jakarta.mail.internet.MimeUtility.encodeText; import static java.util.UUID.randomUUID; -import static javax.mail.internet.MimeUtility.encodeText; import static org.apache.commons.codec.CharEncoding.UTF_8; import static org.apache.commons.collections.CollectionUtils.isEmpty; import static org.apache.commons.io.IOUtils.toInputStream; 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 864acf1a56f5..886218993deb 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 @@ -7,8 +7,8 @@ */ package org.dspace.app.rest; -import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; -import static javax.servlet.http.HttpServletResponse.SC_OK; +import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; +import static jakarta.servlet.http.HttpServletResponse.SC_OK; import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata; import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist; import static org.dspace.app.rest.repository.patch.operation.BitstreamRemoveOperation.OPERATION_PATH_BITSTREAM_REMOVE; @@ -30,8 +30,8 @@ import java.util.Comparator; import java.util.List; import java.util.UUID; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.codec.CharEncoding; import org.apache.commons.io.IOUtils; import org.dspace.app.rest.matcher.BitstreamFormatMatcher; @@ -1308,7 +1308,7 @@ public void patchReplaceMultipleDescriptionBitstream() throws Exception { getClient(token) .perform(patch("/api/core/bitstreams/" + bitstream.getID()) .content(requestBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect( jsonPath("$.metadata", diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java index 259580f8c081..c8f1b0513008 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java @@ -22,9 +22,9 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import javax.ws.rs.core.MediaType; 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.dspace.app.rest.matcher.BitstreamMatcher; @@ -567,7 +567,7 @@ public void patchReplaceMultipleDescriptionBundle() throws Exception { getClient(token) .perform(patch("/api/core/bundles/" + bundle1.getID()) .content(requestBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect( jsonPath("$.metadata", diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CCLicenseAddPatchOperationIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CCLicenseAddPatchOperationIT.java index f07c816b9c98..1311bf33cb93 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CCLicenseAddPatchOperationIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CCLicenseAddPatchOperationIT.java @@ -18,8 +18,8 @@ import java.util.ArrayList; import java.util.List; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CCLicenseRemovePatchOperationIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CCLicenseRemovePatchOperationIT.java index 8e01678899a5..73b2d929014b 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CCLicenseRemovePatchOperationIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CCLicenseRemovePatchOperationIT.java @@ -17,8 +17,8 @@ import java.util.ArrayList; import java.util.List; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.patch.RemoveOperation; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java index ee522db170c7..a34ab0dec14f 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java @@ -3152,7 +3152,7 @@ public void patchReplaceMultipleDescriptionCollection() throws Exception { getClient(token) .perform(patch("/api/core/collections/" + col.getID()) .content(requestBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect( jsonPath("$.metadata", @@ -3210,7 +3210,7 @@ public void patchMetadataCheckReindexingTest() throws Exception { String patchBody = getPatchContent(updateTitle); getClient(adminToken).perform(patch("/api/core/collections/" + col.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.metadata['dc.title'][0].value", is("New Name"))); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java index 910dee3bec74..d4f59527eb89 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java @@ -1993,7 +1993,7 @@ public void patchReplaceMultipleDescriptionCommunity() throws Exception { getClient(token) .perform(patch("/api/core/communities/" + parentCommunity.getID()) .content(requestBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect( jsonPath("$.metadata", diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ConfigurationRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ConfigurationRestRepositoryIT.java index 1eab1ef68eb7..45a98a203944 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ConfigurationRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ConfigurationRestRepositoryIT.java @@ -51,5 +51,10 @@ public void getNonExposedValue() throws Exception { public void getAll() throws Exception { getClient().perform(get("/api/config/properties/")) .andExpect(status().isMethodNotAllowed()); + + // Sanity check - Verify same result with no trailing slash, as DSpace should not care whether this + // findAll endpoint ends in a slash or not. + getClient().perform(get("/api/config/properties")) + .andExpect(status().isMethodNotAllowed()); } } 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..863fd1f753d1 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 @@ -17,8 +17,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CsrfRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CsrfRestControllerIT.java new file mode 100644 index 000000000000..1bfdc8feaff0 --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CsrfRestControllerIT.java @@ -0,0 +1,60 @@ +/** + * 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; + +import static org.junit.Assert.assertNotEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.dspace.app.rest.security.DSpaceCsrfTokenRepository; +import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; + +/** + * Integration test for the /api/security/csrf endpoint + *

+ * NOTE: This test will autoconfigure the MockMvc (@AutoConfigureMockMvc) in order to avoid using + * AbstractControllerIntegrationTest.getClient() because that method may use this /api/security/csrf endpoint to + * obtain a CSRF token. + **/ +@AutoConfigureMockMvc +public class CsrfRestControllerIT extends AbstractControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void getCsrf() throws Exception { + // NOTE: We avoid using getClient() here because that method may also call this "/api/security/csrf" endpoint. + String headerToken = mockMvc.perform(get("/api/security/csrf")) + .andExpect(status().isNoContent()) + // Expect this endpoint to send back the proper HTTP Header & Cookie + // as set by DSpaceCsrfTokenRepository + .andExpect(cookie().exists(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME)) + .andExpect(header().exists(DSpaceCsrfTokenRepository.DSPACE_CSRF_HEADER_NAME)) + .andReturn().getResponse() + .getHeader(DSpaceCsrfTokenRepository.DSPACE_CSRF_HEADER_NAME); + + // Call the endpoint again, and verify we get a new token again. Endpoint should ALWAYS change the CSRF token + String headerToken2 = mockMvc.perform(get("/api/security/csrf")) + .andExpect(status().isNoContent()) + // Expect this endpoint to send back the proper HTTP Header & Cookie + // as set by DSpaceCsrfTokenRepository + .andExpect(cookie().exists(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME)) + .andExpect(header().exists(DSpaceCsrfTokenRepository.DSPACE_CSRF_HEADER_NAME)) + .andReturn().getResponse() + .getHeader(DSpaceCsrfTokenRepository.DSPACE_CSRF_HEADER_NAME); + + assertNotEquals("CSRF Tokens should not be the same in separate requests", headerToken, headerToken2); + } +} 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 83ebc40c7966..569e1ea94e85 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 @@ -15,8 +15,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java index aeaecd8a0e7a..c0cc014e4832 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java @@ -26,14 +26,18 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.InputStream; +import java.nio.charset.Charset; import java.time.Period; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.matchers.JsonPathMatchers; import org.apache.commons.codec.CharEncoding; import org.apache.commons.io.IOUtils; +import org.dspace.app.ldn.NotifyServiceEntity; +import org.dspace.app.ldn.model.Notification; import org.dspace.app.rest.matcher.AppliedFilterMatcher; import org.dspace.app.rest.matcher.FacetEntryMatcher; import org.dspace.app.rest.matcher.FacetValueMatcher; @@ -52,6 +56,8 @@ import org.dspace.builder.EPersonBuilder; import org.dspace.builder.GroupBuilder; import org.dspace.builder.ItemBuilder; +import org.dspace.builder.LDNMessageBuilder; +import org.dspace.builder.NotifyServiceBuilder; import org.dspace.builder.PoolTaskBuilder; import org.dspace.builder.SupervisionOrderBuilder; import org.dspace.builder.WorkflowItemBuilder; @@ -6892,4 +6898,131 @@ public void discoverSearchObjectsSupervisionConfigurationTest() throws Exception .andExpect(jsonPath("$._links.self.href", containsString("/api/discover/search/objects"))); } + @Test + public void discoverSearchObjectsNOTIFYIncomingConfigurationTest() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + + context.turnOffAuthorisationSystem(); + + Community community = CommunityBuilder.createCommunity(context) + .withName("community") + .build(); + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("collection") + .build(); + + Item item = ItemBuilder.createItem(context, collection) + .withTitle("item title") + .build(); + + String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); + + NotifyServiceEntity notifyService = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") + .withDescription("service description") + .withUrl("service url") + .withLdnUrl("https://overlay-journal.com/inbox/") + .build(); + + InputStream announceEndorsementStream = getClass().getResourceAsStream("ldn_announce_endorsement.json"); + String announceEndorsement = IOUtils.toString(announceEndorsementStream, Charset.defaultCharset()); + announceEndorsementStream.close(); + + String message = announceEndorsement.replaceAll("<>", object); + message = message.replaceAll("<>", object); + Notification notification = mapper.readValue(message, Notification.class); + LDNMessageBuilder.createNotifyServiceBuilder(context, notification).build(); + + context.restoreAuthSystemState(); + + String adminToken = getAuthToken(admin.getEmail(), password); + getClient(adminToken) + .perform(get("/api/discover/search/objects").param("configuration", "NOTIFY.incoming")) + //** THEN ** + //The status has to be 200 OK + .andExpect(status().isOk()) + //The type has to be 'discover' + .andExpect(jsonPath("$.type", is("discover"))) + //There needs to be a page object that shows the total pages and total elements as well as the + // size and the current page (number) + .andExpect(jsonPath("$._embedded.searchResult.page", is( + PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 1) + ))) + .andExpect(jsonPath("$._embedded.facets", Matchers.containsInAnyOrder( + FacetEntryMatcher.relatedItemFacet(false), + FacetEntryMatcher.originFacet(false), + FacetEntryMatcher.targetFacet(false), + FacetEntryMatcher.queueStatusFacet(false), + FacetEntryMatcher.activityStreamTypeFacet(false), + FacetEntryMatcher.coarNotifyTypeFacet(false), + FacetEntryMatcher.notificationTypeFacet(false) + ))) + //There always needs to be a self link + .andExpect(jsonPath("$._links.self.href", containsString("/api/discover/search/objects"))); + } + + @Test + public void discoverSearchObjectsNOTIFYOutgoingConfigurationTest() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + + context.turnOffAuthorisationSystem(); + + Community community = CommunityBuilder.createCommunity(context) + .withName("community") + .build(); + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("collection") + .build(); + + Item item = ItemBuilder.createItem(context, collection) + .withTitle("item title") + .build(); + + String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); + + NotifyServiceEntity notifyService = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") + .withDescription("service description") + .withUrl("service url") + .withLdnUrl("https://generic-service.com/system/inbox/") + .build(); + + InputStream announceReviewStream = getClass().getResourceAsStream("ldn_announce_review.json"); + String announceReview = IOUtils.toString(announceReviewStream, Charset.defaultCharset()); + announceReviewStream.close(); + + + String message = announceReview.replaceAll("<>", object); + message = message.replaceAll("<>", object); + Notification notification = mapper.readValue(message, Notification.class); + LDNMessageBuilder.createNotifyServiceBuilder(context, notification).build(); + + context.restoreAuthSystemState(); + + String adminToken = getAuthToken(admin.getEmail(), password); + getClient(adminToken) + .perform(get("/api/discover/search/objects").param("configuration", "NOTIFY.outgoing")) + //** THEN ** + //The status has to be 200 OK + .andExpect(status().isOk()) + //The type has to be 'discover' + .andExpect(jsonPath("$.type", is("discover"))) + //There needs to be a page object that shows the total pages and total elements as well as the + // size and the current page (number) + .andExpect(jsonPath("$._embedded.searchResult.page", is( + PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 1) + ))) + .andExpect(jsonPath("$._embedded.facets", Matchers.containsInAnyOrder( + FacetEntryMatcher.relatedItemFacet(false), + FacetEntryMatcher.originFacet(false), + FacetEntryMatcher.targetFacet(false), + FacetEntryMatcher.queueStatusFacet(false), + FacetEntryMatcher.activityStreamTypeFacet(false), + FacetEntryMatcher.coarNotifyTypeFacet(false), + FacetEntryMatcher.notificationTypeFacet(false) + ))) + //There always needs to be a self link + .andExpect(jsonPath("$._links.self.href", containsString("/api/discover/search/objects"))); + } + } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DuplicateDetectionRestIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DuplicateDetectionRestIT.java new file mode 100644 index 000000000000..f53f440fd154 --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DuplicateDetectionRestIT.java @@ -0,0 +1,407 @@ +/** + * 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; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.ws.rs.core.MediaType; +import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.model.patch.ReplaceOperation; +import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.authorize.service.AuthorizeService; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.EPersonBuilder; +import org.dspace.builder.ItemBuilder; +import org.dspace.builder.WorkflowItemBuilder; +import org.dspace.builder.WorkspaceItemBuilder; +import org.dspace.content.Collection; +import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; +import org.dspace.content.service.CollectionService; +import org.dspace.content.service.ItemService; +import org.dspace.content.service.WorkspaceItemService; +import org.dspace.core.I18nUtil; +import org.dspace.discovery.IndexingService; +import org.dspace.eperson.EPerson; +import org.dspace.eperson.service.EPersonService; +import org.dspace.handle.service.HandleService; +import org.dspace.identifier.service.IdentifierService; +import org.dspace.services.ConfigurationService; +import org.dspace.xmlworkflow.service.XmlWorkflowService; +import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; +import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Test item link and section data REST endpoints for duplicate detection. + * @see DuplicateDetectionTest (dspace-api) for lower level integration tests. + * + * @author Kim Shepherd + */ +public class DuplicateDetectionRestIT extends AbstractControllerIntegrationTest { + + @Autowired + ConfigurationService configurationService; + @Autowired + ItemService itemService; + @Autowired + IndexingService indexingService; + @Autowired + CollectionService collectionService; + @Autowired + HandleService handleService; + @Autowired + WorkspaceItemService workspaceItemService; + @Autowired + XmlWorkflowItemService workflowItemService; + @Autowired + IdentifierService identifierService; + @Autowired + AuthorizeService authorizeService; + @Autowired + XmlWorkflowService workflowService; + @Autowired + EPersonService ePersonService; + + private Collection col; + private Collection simpleCol; + private final String item1IssueDate = "2011-10-17"; + private final String item1Subject = "ExtraEntry 1"; + private final String item1Title = "Public item I"; + private final String item1Author = "Smith, Donald"; + private final String item2Subject = "ExtraEntry 2"; + private final String item2IssueDate = "2012-10-17"; + private EPerson anotherEPerson; + + @Override + public void setUp() throws Exception { + super.setUp(); + + // Temporarily enable duplicate detection and set comparison value distance to 1 + configurationService.setProperty("duplicate.enable", true); + configurationService.setProperty("duplicate.comparison.distance", 1); + configurationService.setProperty("duplicate.comparison.normalise.lowercase", true); + configurationService.setProperty("duplicate.comparison.normalise.whitespace", true); + configurationService.setProperty("duplicate.comparison.solr.field", "deduplication_keyword"); + configurationService.setProperty("duplicate.comparison.metadata.field", new String[]{"dc.title"}); + configurationService.setProperty("duplicate.preview.metadata.field", + new String[]{"dc.date.issued", "dc.subject"}); + + context.turnOffAuthorisationSystem(); + parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); + + col = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Test Collection") + .withWorkflowGroup(1, admin) + .build(); + simpleCol = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Test Collection without Workflow") + .build(); + eperson.setFirstName(context, "first"); + eperson.setLastName(context, "last"); + + anotherEPerson = EPersonBuilder.createEPerson(context) + .withEmail("test-another-user@email.com") + .withNameInMetadata("first", "last") + .withCanLogin(true) + .withLanguage(I18nUtil.getDefaultLocale().getLanguage()) + .withPassword(password) + .build(); + + context.restoreAuthSystemState(); + } + + @Test + public void searchDuplicatesBySearchMethodTest() throws Exception { + String token = getAuthToken(admin.getEmail(), password); + + context.turnOffAuthorisationSystem(); + + // Ingest three example items with slightly different titles + // item2 is 1 edit distance from item1 and item3 + // item1 and item3 are 2 edit distance from each other + WorkspaceItem workspaceItem1 = WorkspaceItemBuilder.createWorkspaceItem(context, simpleCol) + .withTitle(item1Title) + .withSubject(item1Subject) + .withIssueDate(item1IssueDate) + .withAuthor(item1Author) + .withSubmitter(eperson) + .build(); + WorkspaceItem workspaceItem2 = WorkspaceItemBuilder.createWorkspaceItem(context, simpleCol) + .withTitle("Public item II") + .withIssueDate(item2IssueDate) + .withAuthor("Smith, Donald X.") + .withSubject(item2Subject) + .withSubmitter(eperson) + .build(); + WorkspaceItem workspaceItem3 = WorkspaceItemBuilder.createWorkspaceItem(context, simpleCol) + .withTitle(item1Title) + .withTitle("Public item III") + .withIssueDate("2013-10-17") + .withAuthor("Smith, Donald Y.") + .withSubject("ExtraEntry 3") + .withSubmitter(eperson) + .build(); + + XmlWorkflowItem wfi1 = workflowService.start(context, workspaceItem1); + XmlWorkflowItem wfi2 = workflowService.start(context, workspaceItem2); + Item item1 = wfi1.getItem(); + Item item2 = wfi2.getItem(); + + context.restoreAuthSystemState(); + + getClient(token).perform(get("/api/submission/duplicates/search/findByItem?uuid=" + item1.getID())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + // Valid duplicates array + .andExpect(jsonPath("$._embedded.potentialDuplicateResources", Matchers.hasSize(1))) + // UUID of only array member matches item2 ID + .andExpect(jsonPath("$._embedded.potentialDuplicateResources[0].uuid") + .value(item2.getID().toString())) + // First item has subject and issue date metadata populated as expected + .andExpect(jsonPath("$._embedded.potentialDuplicateResources[0]" + + ".metadata['dc.subject'][0].value") + .value(item2Subject)) + .andExpect(jsonPath("$._embedded.potentialDuplicateResources[0]" + + ".metadata['dc.date.issued'][0].value") + .value(item2IssueDate)) + // Does NOT have other metadata e.g. author, title + .andExpect(jsonPath("$._embedded.potentialDuplicateResources[0]" + + ".metadata['dc.contributor.author']").doesNotExist()) + .andExpect(jsonPath("$._embedded.potentialDuplicateResources[0]" + + ".metadata['dc.title']").doesNotExist()); + } + + /** + * Duplicates should be accessible via section data. Data should update as comparison value (title) is changed. + * + * @throws Exception + */ + @Test + public void submissionSectionDataTest() throws Exception { + // Test publication + context.turnOffAuthorisationSystem(); + + Collection workspaceCollection = + CollectionBuilder.createCollection(context, parentCommunity, "123456789/test-duplicate-detection") + .withName("Test Collection Workspace").build(); + + // Ingest three example items with slightly different titles + // item2 is 1 edit distance from item1 and item3 + // item1 and item3 are 2 edit distance from each other + Item item1 = ItemBuilder.createItem(context, col) + .withTitle("Submission section test I") // Public item I + .withIssueDate(item1IssueDate) + .withAuthor(item1Author) + .withSubject(item1Subject) + .build(); + Item item2 = ItemBuilder.createItem(context, col) + .withTitle("Submission section test II") + .withIssueDate(item2IssueDate) + .withAuthor("Smith, Donald X.") + .withSubject(item2Subject) + .build(); + Item item3 = ItemBuilder.createItem(context, col) + .withTitle("Submission section test III") + .withIssueDate("2013-10-17") + .withAuthor("Smith, Donald Y.") + .withSubject("ExtraEntry 3") + .build(); + // Create a new workspace item with a similar title to Item 1 (1 edit distance). Reuse other items + // metadata for the rest, as it is not relevant. + WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, workspaceCollection) + .withTitle("Submission section test 1") + .withSubject(item2Subject) + .withIssueDate(item2IssueDate) + .withAuthor(item1Author) + .withSubmitter(eperson) + .build(); + String submitterToken = getAuthToken(eperson.getEmail(), password); + context.restoreAuthSystemState(); + + getClient(submitterToken).perform(get("/api/submission/workspaceitems/" + workspaceItem.getID())) + .andExpect(status().isOk()) + // The duplicates section is present + .andExpect(jsonPath("$.sections.duplicates").exists()) + // There is a potentialDuplicates array in the section data of size 1 + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates", Matchers.hasSize(1))) + // The UUID of the first duplicate matches item 1 (which is 1 distance from this new title) + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates[0].uuid") + .value(item1.getID().toString())) + // Metadata for subject and issue date is populated as expected + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates[0]" + + ".metadata['dc.subject'][0].value") + .value(item1Subject)) + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates[0]" + + ".metadata['dc.date.issued'][0].value") + .value(item1IssueDate)) + // Metadata for other metadata fields has not been copied across, as expected + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates[0]" + + ".metadata['dc.contributor.author']").doesNotExist()) + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates[0]" + + ".metadata['dc.title']").doesNotExist()); + + List updateOperations = new ArrayList(); + Map value = new HashMap(); + value.put("value", "Submission section test II"); + updateOperations.add(new ReplaceOperation("/sections/traditionalpageone/dc.title/0", value)); + String patchBody = getPatchContent(updateOperations); + getClient(submitterToken).perform(patch("/api/submission/workspaceitems/" + workspaceItem.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").doesNotExist()); + + // Now there should be 3 results + getClient(submitterToken).perform(get("/api/submission/workspaceitems/" + workspaceItem.getID())) + .andExpect(status().isOk()) + // The duplicates section is present + .andExpect(jsonPath("$.sections.duplicates").exists()) + // There is a potentialDuplicates array in the section data (even if empty) + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates", Matchers.hasSize(3))); + + // Now, change the title to something completely different + updateOperations = new ArrayList<>(); + value.put("value", "Research article"); + updateOperations.add(new ReplaceOperation("/sections/traditionalpageone/dc.title/0", value)); + patchBody = getPatchContent(updateOperations); + getClient(submitterToken).perform(patch("/api/submission/workspaceitems/" + workspaceItem.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").doesNotExist()); + + // Now there should be NO results + getClient(submitterToken).perform(get("/api/submission/workspaceitems/" + workspaceItem.getID())) + .andExpect(status().isOk()) + // The duplicates section is present + .andExpect(jsonPath("$.sections.duplicates").exists()) + // There is a potentialDuplicates array in the section data (even if empty) + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates", Matchers.hasSize(0))); + } + + /** + * If there is a potential duplicate that is also in submission (workspace item), it will + * ONLY be shown if the current user is the submitter / item owner. + * + * @throws Exception + */ + @Test + public void submissionSectionWorkspaceItemVisibilityTest() throws Exception { + // Test publication + context.turnOffAuthorisationSystem(); + // Create a new collection with handle that maps to teh test-duplicate-detection submission config + col = CollectionBuilder.createCollection(context, parentCommunity, "123456789/test-duplicate-detection") + .withName("Test Collection with Duplicate Detection") + .withWorkflowGroup(1, admin) + .build(); + // Create a new workspace item with a similar title to Item 1 (1 edit distance). Reuse other items + // metadata for the rest, as it is not relevant. + WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, col) + .withTitle("Unique title") + .withSubject(item1Subject) + .withIssueDate(item1IssueDate) + .withAuthor(item1Author) + .withSubmitter(eperson) + .build(); + WorkspaceItem workspaceItem2 = WorkspaceItemBuilder.createWorkspaceItem(context, col) + .withTitle("Unique title") + .withSubject(item2Subject) + .withIssueDate(item2IssueDate) + .withAuthor(item1Author) + .withSubmitter(eperson) + .build(); + WorkspaceItem workspaceItem3 = WorkspaceItemBuilder.createWorkspaceItem(context, col) + .withTitle("Unique title") + .withSubject("asdf") + .withIssueDate("2000-01-01") + .withAuthor("asdfasf") + .withSubmitter(admin) + .build(); + String submitterToken = getAuthToken(eperson.getEmail(), password); + + context.restoreAuthSystemState(); + + // Even though there are 3 items with the same title, this 'eperson' user should only see 1 duplicate + // as workspaceItem3 is owned by a different submitter, and self-references are skipped + getClient(submitterToken).perform(get("/api/submission/workspaceitems/" + workspaceItem.getID())) + .andExpect(status().isOk()) + // The duplicates section is present + .andExpect(jsonPath("$.sections.duplicates").exists()) + // There is a potentialDuplicates array in the section data of size 1 + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates", Matchers.hasSize(1))) + // The UUID of the first duplicate matches item 1 (which is 1 distance from this new title) + .andExpect(jsonPath("$.sections.duplicates.potentialDuplicates[0].uuid") + .value(workspaceItem2.getItem().getID().toString())); + } + + /** + * If there is a potential duplicate that is also in workflow, it will + * ONLY be shown if the current user is in a worflow group for step 1, 2, or 3, or is an admin, or otherwise + * has READ permission + * + * @throws Exception + */ + @Test + public void submissionSectionWorkflowItemVisibilityTest() throws Exception { + + context.turnOffAuthorisationSystem(); + // Create a new collection with handle that maps to teh test-duplicate-detection submission config + parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); + Collection workflowCol = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Test Collection with Duplicate Detection") + .withWorkflowGroup("reviewer", admin) + .build(); + + XmlWorkflowItem workflowItem1 = WorkflowItemBuilder.createWorkflowItem(context, workflowCol) + .withTitle("Unique title") + .withSubmitter(anotherEPerson) + .build(); + XmlWorkflowItem workflowItem2 = WorkflowItemBuilder.createWorkflowItem(context, workflowCol) + .withTitle("Unique title") + .withSubmitter(eperson) + .build(); + context.restoreAuthSystemState(); + + context.setCurrentUser(admin); + String reviewerToken = getAuthToken(admin.getEmail(), password); + + // The reviewer should be able to see the workflow item as a potential duplicate of the test item + getClient(reviewerToken).perform(get("/api/submission/duplicates/search/findByItem?uuid=" + + workflowItem1.getItem().getID())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + // Valid duplicates array + .andExpect(jsonPath("$._embedded.potentialDuplicateResources", Matchers.hasSize(1))) + // UUID of only array member matches the new workflow item ID + .andExpect(jsonPath("$._embedded.potentialDuplicateResources[0].uuid") + .value(workflowItem2.getItem().getID().toString())); + + // Another random user will NOT see this + getClient(getAuthToken(anotherEPerson.getEmail(), password)) + .perform(get("/api/submission/duplicates/search/findByItem?uuid=" + + workflowItem1.getItem().getID())) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + // Valid duplicates array + .andExpect(jsonPath("$._embedded.potentialDuplicateResources").doesNotExist()); + } + +} 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 091c932ad793..dfca8b4328f8 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 @@ -45,9 +45,9 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.exception.EPersonNameNotProvidedException; import org.dspace.app.rest.exception.RESTEmptyWorkflowGroupException; 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 4300c987589a..82170179fab4 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 @@ -33,9 +33,9 @@ import java.util.Locale; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MediaType; import org.dspace.app.rest.exception.GroupNameNotProvidedException; import org.dspace.app.rest.matcher.EPersonMatcher; import org.dspace.app.rest.matcher.GroupMatcher; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestControllerIT.java index 73c2c8a3fe59..16f7362ea9dd 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestControllerIT.java @@ -55,7 +55,7 @@ public void moveItemTestByAnonymous() throws Exception { context.restoreAuthSystemState(); //When we call this owningCollection/move endpoint getClient().perform( - put("/api/core/items/" + publicItem1.getID() + "/owningCollection/") + put("/api/core/items/" + publicItem1.getID() + "/owningCollection") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() @@ -91,7 +91,7 @@ public void moveItemTestByAuthorizedUser() throws Exception { //When we call this owningCollection/move endpoint getClient(token) - .perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/") + .perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() @@ -145,7 +145,7 @@ public void moveItemTestByMinimallyAuthorizedUser() throws Exception { String token = getAuthToken(itemMoveEperson.getEmail(), "test"); getClient(token) - .perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/") + .perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() @@ -191,7 +191,7 @@ public void moveItemTestByAuthorizedUserWithoutAdd() throws Exception { context.restoreAuthSystemState(); String token = getAuthToken(itemMoveEperson.getEmail(), "test"); - getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/") + getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() @@ -232,7 +232,7 @@ public void moveItemTestByAuthorizedUserWithoutAdmin() throws Exception { context.restoreAuthSystemState(); String token = getAuthToken(itemMoveEperson.getEmail(), "test"); - getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/") + getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() @@ -273,7 +273,7 @@ public void moveItemTestByAuthorizedUserWithoutWrite() throws Exception { context.restoreAuthSystemState(); String token = getAuthToken(itemMoveEperson.getEmail(), "test"); - getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/") + getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() @@ -310,7 +310,7 @@ public void moveItemForbiddenTest() throws Exception { String tokenEPerson = getAuthToken(eperson.getEmail(), password); - getClient(tokenEPerson).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/") + getClient(tokenEPerson).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content("https://localhost:8080/spring-rest/api/core/collections/" + col2.getID())) .andExpect(status().isForbidden()); 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 b25b323fd1f0..6f6895aa7f65 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 @@ -45,9 +45,9 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.CharEncoding; import org.dspace.app.rest.matcher.BitstreamMatcher; 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 1437c8dd62ef..82aa746c777f 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 @@ -73,8 +73,7 @@ public void ldnInboxAnnounceEndorsementTest() throws Exception { Item item = ItemBuilder.createItem(context, collection).build(); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("service url") .withLdnUrl("https://overlay-journal.com/inbox/") @@ -109,8 +108,8 @@ public void ldnInboxAnnounceReviewTest() throws Exception { Item item = ItemBuilder.createItem(context, collection).build(); InputStream announceReviewStream = getClass().getResourceAsStream("ldn_announce_review.json"); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); - NotifyServiceEntity notifyServiceEntity = NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceEntity notifyServiceEntity = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://review-service.com/inbox/about/") .withLdnUrl("https://review-service.com/inbox/") @@ -163,8 +162,8 @@ public void ldnInboxOfferReviewAndACKTest() throws Exception { Collection collection = CollectionBuilder.createCollection(context, community).build(); Item item = ItemBuilder.createItem(context, collection).build(); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); - NotifyServiceEntity notifyServiceEntity = NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceEntity notifyServiceEntity = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://review-service.com/inbox/about/") .withLdnUrl("https://review-service.com/inbox/") @@ -220,8 +219,8 @@ public void ldnInboxAnnounceReleaseTest() throws Exception { Item item = ItemBuilder.createItem(context, collection).build(); InputStream announceRelationshipStream = getClass().getResourceAsStream("ldn_announce_release.json"); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); - NotifyServiceEntity notifyServiceEntity = NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceEntity notifyServiceEntity = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://review-service.com/inbox/about/") .withLdnUrl("https://review-service.com/inbox/") @@ -283,8 +282,7 @@ public void ldnInboxAnnounceEndorsementInvalidIpTest() throws Exception { Item item = ItemBuilder.createItem(context, collection).build(); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("service url") .withLdnUrl("https://overlay-journal.com/inbox/") @@ -321,8 +319,7 @@ public void ldnInboxAnnounceEndorsementInvalidInboxTest() throws Exception { Item item = ItemBuilder.createItem(context, collection).build(); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("service url") .withLdnUrl("https://overlay-journal.com/inbox/") @@ -359,8 +356,7 @@ public void ldnInboxOutOfRangeIPwithDisabledCheckTest() throws Exception { configurationService.setProperty("ldn.notify.inbox.block-untrusted-ip", false); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("service url") .withLdnUrl("https://overlay-journal.com/inbox/") diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNMessageRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNMessageRestControllerIT.java new file mode 100644 index 000000000000..95cdd3c28fbc --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNMessageRestControllerIT.java @@ -0,0 +1,150 @@ +/** + * 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; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.InputStream; +import java.nio.charset.Charset; +import java.sql.SQLException; +import java.util.List; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.app.ldn.NotifyServiceEntity; +import org.dspace.app.ldn.model.Notification; +import org.dspace.app.ldn.service.LDNMessageService; +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.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.Item; +import org.dspace.services.ConfigurationService; +import org.junit.After; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Integration Tests against {@link LDNMessageRestController} + * + * @author Mohamed Eskander (mohamed.eskander at 4science.com) + */ +public class LDNMessageRestControllerIT extends AbstractControllerIntegrationTest { + + @Autowired + private ConfigurationService configurationService; + + @Autowired + private LDNMessageService ldnMessageService; + + @Test + public void findByItemUnAuthorizedTest() throws Exception { + getClient() + .perform(post("/api/ldn/messages/urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4/enqueueretry")) + .andExpect(status().isUnauthorized()); + } + + @Test + public void findByItemIsForbiddenTest() throws Exception { + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken) + .perform(post("/api/ldn/messages/urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4/enqueueretry")) + .andExpect(status().isForbidden()); + } + + @Test + public void findByItemNotFoundTest() throws Exception { + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken) + .perform(post("/api/ldn/messages/urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4/enqueueretry")) + .andExpect(status().isNotFound()); + } + + @Test + public void findByItemTest() 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("item title") + .build(); + + String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); + + NotifyServiceEntity notifyService = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") + .withDescription("service description") + .withUrl("service url") + .withLdnUrl("https://overlay-journal.com/inbox/") + .build(); + + context.restoreAuthSystemState(); + + InputStream announceEndorsementStream = getClass().getResourceAsStream("ldn_announce_endorsement.json"); + String announceEndorsement = IOUtils.toString(announceEndorsementStream, Charset.defaultCharset()); + announceEndorsementStream.close(); + String message = announceEndorsement.replaceAll("<>", object); + message = message.replaceAll("<>", object); + + ObjectMapper mapper = new ObjectMapper(); + Notification notification = mapper.readValue(message, Notification.class); + getClient() + .perform(post("/ldn/inbox") + .contentType("application/ld+json") + .content(message)) + .andExpect(status().isAccepted()); + + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken) + .perform(post("/api/ldn/messages/" + notification.getId() + "/enqueueretry")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(notification.getId()))) + .andExpect(jsonPath("$.notificationId", is(notification.getId()))) + .andExpect(jsonPath("$.queueStatus", is(7))) + .andExpect(jsonPath("$.queueStatusLabel", is("QUEUE_STATUS_QUEUED_FOR_RETRY"))) + .andExpect(jsonPath("$.context", is(item.getID().toString()))) + .andExpect(jsonPath("$.object", is(item.getID().toString()))) + .andExpect(jsonPath("$.target", nullValue())) + .andExpect(jsonPath("$.origin", is(notifyService.getID()))) + .andExpect(jsonPath("$.inReplyTo", nullValue())) + .andExpect(jsonPath("$.activityStreamType", is("Announce"))) + .andExpect(jsonPath("$.coarNotifyType", is("coar-notify:EndorsementAction"))) + .andExpect(jsonPath("$.queueAttempts", is(0))) + .andExpect(jsonPath("$.notificationType", is("Incoming"))); + + } + + @Override + @After + public void destroy() throws Exception { + List ldnMessageEntities = ldnMessageService.findAll(context); + if (CollectionUtils.isNotEmpty(ldnMessageEntities)) { + ldnMessageEntities.forEach(ldnMessage -> { + try { + ldnMessageService.delete(context, ldnMessage); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + super.destroy(); + } +} \ No newline at end of file diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNMessageRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNMessageRestRepositoryIT.java new file mode 100644 index 000000000000..5dba09c0f84a --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNMessageRestRepositoryIT.java @@ -0,0 +1,255 @@ +/** + * 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; + +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.InputStream; +import java.nio.charset.Charset; +import java.sql.SQLException; +import java.util.List; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.dspace.app.ldn.LDNMessageEntity; +import org.dspace.app.ldn.NotifyServiceEntity; +import org.dspace.app.ldn.model.Notification; +import org.dspace.app.ldn.service.LDNMessageService; +import org.dspace.app.rest.model.LDNMessageEntityRest; +import org.dspace.app.rest.repository.LDNMessageRestRepository; +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.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.Item; +import org.dspace.services.ConfigurationService; +import org.junit.After; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Integration Tests against {@link LDNMessageRestRepository} + * + * @author Mohamed Eskander (mohamed.eskander at 4science.com) + */ +public class LDNMessageRestRepositoryIT extends AbstractControllerIntegrationTest { + + @Autowired + private ConfigurationService configurationService; + + @Autowired + private LDNMessageService ldnMessageService; + + @Test + public void findOneUnAuthorizedTest() throws Exception { + getClient() + .perform(get("/api/ldn/messages/urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4")) + .andExpect(status().isUnauthorized()); + } + + @Test + public void findOneIsForbiddenTest() throws Exception { + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken) + .perform(get("/api/ldn/messages/urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4")) + .andExpect(status().isForbidden()); + } + + @Test + public void findOneIsNotFoundTest() throws Exception { + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken) + .perform(get("/api/ldn/messages/urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4")) + .andExpect(status().isNotFound()); + } + + @Test + public void findOneTest() 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("item title") + .build(); + + String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); + + NotifyServiceEntity notifyService = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") + .withDescription("service description") + .withUrl("service url") + .withLdnUrl("https://overlay-journal.com/inbox/") + .build(); + + context.restoreAuthSystemState(); + + InputStream announceEndorsementStream = getClass().getResourceAsStream("ldn_announce_endorsement.json"); + String announceEndorsement = IOUtils.toString(announceEndorsementStream, Charset.defaultCharset()); + announceEndorsementStream.close(); + String message = announceEndorsement.replaceAll("<>", object); + message = message.replaceAll("<>", object); + + ObjectMapper mapper = new ObjectMapper(); + Notification notification = mapper.readValue(message, Notification.class); + getClient() + .perform(post("/ldn/inbox") + .contentType("application/ld+json") + .content(message)) + .andExpect(status().isAccepted()); + + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken) + .perform(get("/api/ldn/messages/" + notification.getId())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(notification.getId()))) + .andExpect(jsonPath("$.notificationId", is(notification.getId()))) + .andExpect(jsonPath("$.queueStatus", is(1))) + .andExpect(jsonPath("$.queueStatusLabel", is("QUEUE_STATUS_QUEUED"))) + .andExpect(jsonPath("$.context", is(item.getID().toString()))) + .andExpect(jsonPath("$.object", is(item.getID().toString()))) + .andExpect(jsonPath("$.target", nullValue())) + .andExpect(jsonPath("$.origin", is(notifyService.getID()))) + .andExpect(jsonPath("$.inReplyTo", nullValue())) + .andExpect(jsonPath("$.activityStreamType", is("Announce"))) + .andExpect(jsonPath("$.coarNotifyType", is("coar-notify:EndorsementAction"))) + .andExpect(jsonPath("$.queueAttempts", is(0))) + .andExpect(jsonPath("$.notificationType", is("Incoming"))); + } + + @Test + public void findAllUnAuthorizedTest() throws Exception { + getClient().perform(get("/api/ldn/messages")) + .andExpect(status().isUnauthorized()); + } + + @Test + public void findAllIsForbiddenTest() throws Exception { + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform(get("/api/ldn/messages")) + .andExpect(status().isForbidden()); + } + + @Test + public void findAllTest() 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("item title") + .build(); + + String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); + + NotifyServiceEntity notifyService = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") + .withDescription("service description") + .withUrl("service url") + .withLdnUrl("https://overlay-journal.com/inbox/") + .build(); + + context.restoreAuthSystemState(); + + InputStream announceEndorsementStream = getClass().getResourceAsStream("ldn_announce_endorsement.json"); + String announceEndorsement = IOUtils.toString(announceEndorsementStream, Charset.defaultCharset()); + announceEndorsementStream.close(); + String message = announceEndorsement.replaceAll("<>", object); + message = message.replaceAll("<>", object); + + ObjectMapper mapper = new ObjectMapper(); + Notification notification = mapper.readValue(message, Notification.class); + getClient() + .perform(post("/ldn/inbox") + .contentType("application/ld+json") + .content(message)) + .andExpect(status().isAccepted()); + + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken) + .perform(get("/api/ldn/messages/")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.messages[0].id", is(notification.getId()))) + .andExpect(jsonPath("$._embedded.messages[0].notificationId", is(notification.getId()))) + .andExpect(jsonPath("$._embedded.messages[0].queueStatus", is(1))) + .andExpect(jsonPath("$._embedded.messages[0].queueStatusLabel", is("QUEUE_STATUS_QUEUED"))) + .andExpect(jsonPath("$._embedded.messages[0].context", is(item.getID().toString()))) + .andExpect(jsonPath("$._embedded.messages[0].object", is(item.getID().toString()))) + .andExpect(jsonPath("$._embedded.messages[0].target", nullValue())) + .andExpect(jsonPath("$._embedded.messages[0].origin", is(notifyService.getID()))) + .andExpect(jsonPath("$._embedded.messages[0].inReplyTo", nullValue())) + .andExpect(jsonPath("$._embedded.messages[0].activityStreamType", is("Announce"))) + .andExpect(jsonPath("$._embedded.messages[0].coarNotifyType", is("coar-notify:EndorsementAction"))) + .andExpect(jsonPath("$._embedded.messages[0].queueAttempts", is(0))) + .andExpect(jsonPath("$._embedded.messages[0].notificationType", is("Incoming"))); + } + + @Test + public void createLDNMessageTest() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + LDNMessageEntityRest data = new LDNMessageEntityRest(); + String authToken = getAuthToken(admin.getEmail(), password); + + getClient(authToken) + .perform(post("/api/ldn/messages") + .content(mapper.writeValueAsBytes(data)) + .contentType(contentType)) + .andExpect(status().isMethodNotAllowed()); + } + + @Test + public void deleteLDNMessageTest() throws Exception { + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken) + .perform(delete("/api/ldn/messages/urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4")) + .andExpect(status().isMethodNotAllowed()); + } + + @Test + public void patchLDNMessageTest() throws Exception { + String authToken = getAuthToken(admin.getEmail(), password); + getClient(authToken) + .perform(patch("/api/ldn/messages/urn:uuid:668f26e0-2c8d-4117-a0d2-ee713523bcb4") + .content(getPatchContent(List.of())) + .contentType(APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isMethodNotAllowed()); + } + + @Override + @After + public void destroy() throws Exception { + List ldnMessageEntities = ldnMessageService.findAll(context); + if (CollectionUtils.isNotEmpty(ldnMessageEntities)) { + ldnMessageEntities.forEach(ldnMessage -> { + try { + ldnMessageService.delete(context, ldnMessage); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + } + + super.destroy(); + } +} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/MappedCollectionRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/MappedCollectionRestRepositoryIT.java index f38f5ced75ff..a32886da2015 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/MappedCollectionRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/MappedCollectionRestRepositoryIT.java @@ -108,7 +108,7 @@ public void itemAndCollectionHaveOneMappingTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform( - post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() + "\n" @@ -164,7 +164,7 @@ public void itemAndTwoCollectionsHaveTwoMappingsTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken) - .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() + "\n" + @@ -229,7 +229,7 @@ public void itemHasNoDuplicatesInMappedCollectionAndCollectionHasNoDuplicatesInM String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken) - .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() + "\n" + @@ -283,7 +283,7 @@ public void itemHasNoOriginalCollectionInMappedCollectionAndCollectionHasNoOrigi String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken) - .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() + "\n" + @@ -335,7 +335,7 @@ public void removeMappedCollectionTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken) - .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() + "\n" + @@ -443,7 +443,7 @@ public void doNotAllowMappedCollectionIfGivenCollectionIsOwningCollectionOfGiven String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken) - .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content("https://localhost:8080/spring-rest/api/core/collections/" + col1.getID()) ) @@ -503,7 +503,7 @@ public void doNotAllowMappedCollectionWithATemplateItem() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken) - .perform(post("/api/core/items/" + templateItem.getID() + "/mappedCollections/") + .perform(post("/api/core/items/" + templateItem.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content("https://localhost:8080/spring-rest/api/core/collections/" + col2.getID()) ) @@ -563,14 +563,14 @@ public void mappedCollectionNeedsValidIDs() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken) - .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + .perform(post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content("https://localhost:8080/spring-rest/api/core/collections/" + "badCollectionID") ) .andExpect(status().isUnprocessableEntity()); getClient(adminToken) - .perform(post("/api/core/items/" + "badItemID" + "/mappedCollections/") + .perform(post("/api/core/items/" + "badItemID" + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content("https://localhost:8080/spring-rest/api/core/collections/" + col1.getID()) ) @@ -646,7 +646,7 @@ public void mappingNewCollectionCannotBeDoneAnonymouslyTest() throws Exception { // itemService.update(context, publicItem1); getClient().perform( - post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() @@ -686,7 +686,7 @@ public void removingMappedCollectionCannotBeDoneAnonymouslyTest() throws Excepti String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform( - post("/api/core/items/" + publicItem1.getID() + "/mappedCollections/") + post("/api/core/items/" + publicItem1.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + col2.getID() @@ -735,7 +735,7 @@ public void mappedItemAppearsInCollectionBrowseTest() throws Exception { // Map the item to the sink collection getClient(adminToken).perform( - post("/api/core/items/" + item.getID() + "/mappedCollections/") + post("/api/core/items/" + item.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + sink.getID() + "\n" @@ -782,7 +782,7 @@ public void unmappedItemIsRemovedFromCollectionBrowseTest() throws Exception { //3. The item mapped to the sink collection getClient(adminToken).perform( - post("/api/core/items/" + item.getID() + "/mappedCollections/") + post("/api/core/items/" + item.getID() + "/mappedCollections") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( "https://localhost:8080/spring-rest/api/core/collections/" + sink.getID() + "\n" diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyRequestStatusRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyRequestStatusRestControllerIT.java index a7077f20da18..5612786885b7 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyRequestStatusRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyRequestStatusRestControllerIT.java @@ -57,8 +57,8 @@ public void oneStatusReviewedTest() throws Exception { Collection collection = CollectionBuilder.createCollection(context, community).build(); Item item = ItemBuilder.createItem(context, collection).build(); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); - NotifyServiceEntity notifyServiceEntity = NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceEntity notifyServiceEntity = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://review-service.com/inbox/about/") .withLdnUrl("https://review-service.com/inbox/") @@ -103,8 +103,8 @@ public void oneStatusRejectedTest() throws Exception { Collection collection = CollectionBuilder.createCollection(context, community).build(); Item item = ItemBuilder.createItem(context, collection).build(); String object = configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle(); - NotifyServiceEntity notifyServiceEntity = NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceEntity notifyServiceEntity = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://review-service.com/inbox/about/") .withLdnUrl("https://review-service.com/inbox/") diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyServiceRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyServiceRestRepositoryIT.java index 984b9b573e5c..653850331a61 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyServiceRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyServiceRestRepositoryIT.java @@ -32,9 +32,9 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.RandomUtils; import org.dspace.app.ldn.NotifyServiceEntity; @@ -75,24 +75,21 @@ public void findAllUnAuthorizedTest() throws Exception { public void findAllTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntityOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withDescription("service description one") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceEntityTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withDescription("service description two") .withUrl("https://service2.ldn.org/about") .withLdnUrl("https://service2.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceEntityThree = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withDescription("service description three") .withUrl("https://service3.ldn.org/about") .withLdnUrl("https://service3.ldn.org/inbox") @@ -132,8 +129,7 @@ public void findOneNotFoundTest() throws Exception { public void findOneTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -238,6 +234,9 @@ public void createTest() throws Exception { matchNotifyServicePattern("patternB", null, false) ))) )); + + // Delete the created service + NotifyServiceBuilder.deleteNotifyService(idRef.get()); } @Test @@ -246,8 +245,7 @@ public void notifyServicePatchOperationForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -274,8 +272,7 @@ public void notifyServiceDescriptionAddOperationBadRequestTest() throws Exceptio context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -302,8 +299,7 @@ public void notifyServiceDescriptionAddOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") .isEnabled(false) @@ -333,8 +329,7 @@ public void notifyServiceDescriptionReplaceOperationBadRequestTest() throws Exce context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") .build(); @@ -360,8 +355,7 @@ public void notifyServiceDescriptionReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -392,8 +386,7 @@ public void notifyServiceDescriptionRemoveOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -424,8 +417,7 @@ public void notifyServiceUrlAddOperationBadRequestTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -452,8 +444,7 @@ public void notifyServiceUrlAddOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withLdnUrl("https://service.ldn.org/inbox") .build(); @@ -482,8 +473,7 @@ public void notifyServiceUrlReplaceOperationBadRequestTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withLdnUrl("https://service.ldn.org/inbox") .build(); @@ -509,8 +499,7 @@ public void notifyServiceUrlReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -541,8 +530,7 @@ public void notifyServiceUrlRemoveOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -566,13 +554,16 @@ public void notifyServiceUrlRemoveOperationTest() throws Exception { ); } + // TODO: Test is currently ignored as the code in this test is IDENTICAL to the code in + // "notifyServiceNameReplaceOperationTest". It's unclear WHY this should throw a 400 exception? @Test + @Ignore public void notifyServiceNameReplaceOperationBadRequestTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -599,8 +590,7 @@ public void notifyServiceNameReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -630,8 +620,7 @@ public void notifyServiceLdnUrlReplaceOperationBadRequestTest() throws Exception context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withUrl("https://service.ldn.org/about") .build(); context.restoreAuthSystemState(); @@ -656,8 +645,7 @@ public void notifyServiceLdnUrlReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -687,8 +675,7 @@ public void notifyServiceNameRemoveOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -720,8 +707,7 @@ public void notifyServiceLdnUrlRemoveOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -760,23 +746,20 @@ public void findByLdnUrlBadRequestTest() throws Exception { public void findByLdnUrlTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntityOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withDescription("service description one") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceEntityTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withDescription("service description two") .withUrl("https://service2.ldn.org/about") .withLdnUrl("https://service2.ldn.org/inbox") .build(); - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withDescription("service description three") .withUrl("https://service3.ldn.org/about") .withLdnUrl("https://service3.ldn.org/inbox") @@ -818,8 +801,7 @@ public void deleteNotFoundTest() throws Exception { public void deleteTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("service ldnUrl") @@ -842,8 +824,7 @@ public void NotifyServiceInboundPatternsAddOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -886,8 +867,7 @@ public void NotifyServiceInboundPatternsAddOperationBadRequestTest() throws Exce context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -937,8 +917,7 @@ public void NotifyServiceInboundPatternRemoveOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1001,8 +980,7 @@ public void NotifyServiceInboundPatternsRemoveOperationBadRequestTest() throws E context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1052,8 +1030,7 @@ public void NotifyServiceInboundPatternConstraintAddOperationTest() throws Excep context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1118,8 +1095,7 @@ public void NotifyServiceInboundPatternConstraintAddOperationBadRequestTest() th context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1175,8 +1151,7 @@ public void NotifyServiceInboundPatternConstraintReplaceOperationTest() throws E context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1241,8 +1216,7 @@ public void NotifyServiceInboundPatternConstraintReplaceOperationBadRequestTest( context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1298,8 +1272,7 @@ public void NotifyServiceInboundPatternConstraintRemoveOperationTest() throws Ex context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1363,8 +1336,7 @@ public void NotifyServiceInboundPatternConstraintRemoveOperationBadRequestTest() context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1414,8 +1386,7 @@ public void NotifyServiceInboundPatternPatternAddOperationTest() throws Exceptio context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1480,8 +1451,7 @@ public void NotifyServiceInboundPatternPatternAddOperationBadRequestTest() throw context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1537,8 +1507,7 @@ public void NotifyServiceInboundPatternPatternReplaceOperationTest() throws Exce context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1603,8 +1572,7 @@ public void NotifyServiceInboundPatternPatternReplaceOperationBadRequestTest() t context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1660,8 +1628,7 @@ public void NotifyServiceInboundPatternAutomaticReplaceOperationTest() throws Ex context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1726,8 +1693,7 @@ public void NotifyServiceInboundPatternAutomaticReplaceOperationBadRequestTest() context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1783,8 +1749,7 @@ public void NotifyServiceInboundPatternsReplaceOperationTest() throws Exception context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1850,8 +1815,7 @@ public void NotifyServiceInboundPatternsReplaceWithEmptyArrayOperationTest() thr context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1907,8 +1871,7 @@ public void NotifyServiceInboundPatternsReplaceOperationBadRequestTest() throws context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -1964,8 +1927,7 @@ public void NotifyServiceInboundPatternsRemoveOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -2020,8 +1982,7 @@ public void NotifyServiceInboundPatternReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -2101,24 +2062,21 @@ public void findManualServicesByInboundPatternTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntityOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withDescription("service description one") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceEntityTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withDescription("service description two") .withUrl("https://service2.ldn.org/about") .withLdnUrl("https://service2.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceEntityThree = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withDescription("service description") .withUrl("https://service3.ldn.org/about") .withLdnUrl("https://service3.ldn.org/inbox") @@ -2175,8 +2133,7 @@ public void NotifyServiceStatusReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -2204,8 +2161,7 @@ public void NotifyServiceStatusReplaceOperationTest() throws Exception { public void NotifyServiceScoreReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withScore(BigDecimal.ZERO) .withUrl("https://service.ldn.org/about") @@ -2235,8 +2191,7 @@ public void NotifyServiceScoreReplaceOperationTestUnprocessableTest() throws Exc context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("service url") .withLdnUrl("service ldn url") @@ -2264,8 +2219,7 @@ public void notifyServiceScoreAddOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("service url") .withLdnUrl("service ldn url") @@ -2315,8 +2269,7 @@ public void notifyServiceLowerIpReplaceOperationBadRequestTest() throws Exceptio context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withUrl("https://service.ldn.org/about") .build(); context.restoreAuthSystemState(); @@ -2341,8 +2294,7 @@ public void notifyServiceLowerIpReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -2375,8 +2327,7 @@ public void notifyServiceLowerIpRemoveOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -2405,8 +2356,7 @@ public void notifyServiceUpperIpReplaceOperationBadRequestTest() throws Exceptio context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withUrl("https://service.ldn.org/about") .build(); context.restoreAuthSystemState(); @@ -2431,8 +2381,7 @@ public void notifyServiceUpperIpReplaceOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") @@ -2465,8 +2414,7 @@ public void notifyServiceUpperIpRemoveOperationTest() throws Exception { context.turnOffAuthorisationSystem(); NotifyServiceEntity notifyServiceEntity = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://service.ldn.org/about") .withLdnUrl("https://service.ldn.org/inbox") diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OidcAuthenticationRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OidcAuthenticationRestControllerIT.java index aa1ecd5ebf48..b3a805fda548 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OidcAuthenticationRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OidcAuthenticationRestControllerIT.java @@ -25,10 +25,10 @@ import java.text.ParseException; import java.util.Map; -import javax.servlet.http.Cookie; import com.nimbusds.jose.JOSEException; import com.nimbusds.jwt.SignedJWT; +import jakarta.servlet.http.Cookie; import org.dspace.app.rest.model.AuthnRest; import org.dspace.app.rest.security.jwt.EPersonClaimProvider; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidLoginFilterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidLoginFilterIT.java index 4b441b1bc8fc..25ad884cfdf7 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidLoginFilterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidLoginFilterIT.java @@ -29,11 +29,11 @@ import java.sql.SQLException; import java.text.ParseException; import java.util.UUID; -import javax.servlet.http.Cookie; import com.jayway.jsonpath.JsonPath; import com.nimbusds.jose.JOSEException; import com.nimbusds.jwt.SignedJWT; +import jakarta.servlet.http.Cookie; import org.dspace.app.rest.model.AuthnRest; import org.dspace.app.rest.security.OrcidLoginFilter; import org.dspace.app.rest.security.jwt.EPersonClaimProvider; 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 58781cf589be..eec7ce95f8d4 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 @@ -89,8 +89,8 @@ private static final String getPath(Object element) { @Autowired private ConfigurationService configurationService; - private Collection collection; - private Collection collection2; + private Collection personCollection; + private Collection publicationCollection; private WorkspaceItem publicationWorkspaceItem; private Item publicationItem; private Item personItem1; @@ -116,12 +116,12 @@ public void setUp() throws Exception { Community community = CommunityBuilder.createCommunity(context) .withName("Parent community") .build(); - collection = CollectionBuilder.createCollection(context, community) - .withName("Collection") - .withEntityType("Person") - .build(); - collection2 = CollectionBuilder.createCollection(context, community) - .withName("Collection") + personCollection = CollectionBuilder.createCollection(context, community) + .withName("Person Collection") + .withEntityType("Person") + .build(); + publicationCollection = CollectionBuilder.createCollection(context, community) + .withName("Publication Collection") .withEntityType("Publication") .build(); @@ -160,17 +160,17 @@ private void initPersonPublicationWorkspace() throws Exception { context.turnOffAuthorisationSystem(); - personItem1 = ItemBuilder.createItem(context, collection) + personItem1 = ItemBuilder.createItem(context, personCollection) .withTitle("Person 1") .withPersonIdentifierFirstName("Sarah") .withPersonIdentifierLastName("Dahlen") .build(); - personItem2 = ItemBuilder.createItem(context, collection) + personItem2 = ItemBuilder.createItem(context, personCollection) .withTitle("Person 2") .withPersonIdentifierFirstName("Oliver") .withPersonIdentifierLastName("Linton") .build(); - publicationWorkspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection2) + publicationWorkspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, publicationCollection) .withTitle("Publication 1") .withEntityType("Publication") .build(); @@ -255,7 +255,7 @@ private void initSimplePublicationItem() throws Exception { context.turnOffAuthorisationSystem(); - publicationItem = ItemBuilder.createItem(context, collection) + publicationItem = ItemBuilder.createItem(context, publicationCollection) .withTitle("Publication 1") .build(); @@ -306,7 +306,7 @@ private void initPlainTextPublicationWorkspace() throws Exception { context.turnOffAuthorisationSystem(); - publicationWorkspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection) + publicationWorkspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, publicationCollection) .withTitle("Publication 1") .withEntityType("Publication") .build(); @@ -1229,7 +1229,7 @@ public void removeAllAuthorsOnTraditionalPageTest() throws Exception { getClient(token).perform(patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); String authorField = "dc.contributor.author"; @@ -1296,7 +1296,7 @@ public void patchAddAllAuthorsOnTraditionalPageNotExistentRelationTest() throws getClient(token).perform(patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isUnprocessableEntity()); } @@ -1456,7 +1456,7 @@ private void moveMetadataAuthorTest(List moves, List expected getClient(token).perform(patch("/api/core/items/" + publicationItem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); String authorField = "dc.contributor.author"; @@ -1517,7 +1517,7 @@ private void assertReplacementOrder(List expectedOrder, String patchBody .perform( patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON) ) .andExpect(status().isOk()); @@ -1561,7 +1561,7 @@ private void addTraditionalPageOneAuthorTest(String path, List expectedO getClient(token).perform(patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); String authorField = "dc.contributor.author"; @@ -1595,7 +1595,7 @@ private void removeTraditionalPageOneAuthorTest(int path, List expectedO getClient(token).perform(patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); String authorField = "dc.contributor.author"; @@ -1638,7 +1638,7 @@ private void patchAddEntireArray(List metadataValues) throws Exce getClient(token).perform(patch("/api/submission/workspaceitems/" + publicationWorkspaceItem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); final String authorField = "dc.contributor.author"; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/QAEventRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/QAEventRestRepositoryIT.java index 5cecff6ef493..e5bdff533024 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/QAEventRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/QAEventRestRepositoryIT.java @@ -33,9 +33,9 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MediaType; import org.dspace.app.ldn.NotifyServiceEntity; import org.dspace.app.rest.matcher.ItemMatcher; import org.dspace.app.rest.matcher.MetadataMatcher; @@ -865,8 +865,8 @@ public void recordDecisionNotifyTest() throws Exception { .withEntityType("Project").build(); Item item = ItemBuilder.createItem(context, colFunding).withTitle("Tracking Papyrus and Parchment Paths") .build(); - NotifyServiceEntity notifyServiceEntity = NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name") + NotifyServiceEntity notifyServiceEntity = + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name") .withDescription("service description") .withUrl("https://review-service.com/inbox/about/") .withLdnUrl("https://review-service.com/inbox/") diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RegistrationRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RegistrationRestRepositoryIT.java index 7bab342c18a6..1831fc6a8a85 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RegistrationRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RegistrationRestRepositoryIT.java @@ -24,9 +24,9 @@ import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.matcher.RegistrationMatcher; import org.dspace.app.rest.model.RegistrationRest; 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 ea164af7318a..3ab177e511e2 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 @@ -172,7 +172,6 @@ public void setUp() throws Exception { .withAuthor("Smith, Maria") .withPersonIdentifierLastName("Smith") .withPersonIdentifierFirstName("Maria") - .withMetadata("dspace", "entity", "type", "Person") .build(); author3 = ItemBuilder.createItem(context, col1) @@ -2632,7 +2631,7 @@ public void putRelationshipWithJsonMoveInFrontOtherMetadata() throws Exception { getClient(token).perform(patch("/api/core/items/" + publication1.getID()) .content(getPatchContent(ops)) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)); + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)); // Add another relationship mvcResult = getClient(token) 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..ea61db514504 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 @@ -15,7 +15,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -36,10 +35,10 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.servlet.http.Cookie; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; +import jakarta.servlet.http.Cookie; import org.dspace.app.requestitem.RequestItem; import org.dspace.app.requestitem.service.RequestItemService; import org.dspace.app.rest.converter.RequestItemConverter; @@ -127,8 +126,6 @@ public void init() @Test public void testFindAll() throws Exception { - System.out.println("findAll"); - getClient().perform(get(URI_ROOT)) .andExpect(status().isMethodNotAllowed()); } @@ -141,8 +138,6 @@ public void testFindAll() @Test public void testFindOneAuthenticated() throws Exception { - System.out.println("findOne (authenticated)"); - // Create a request. RequestItem request = RequestItemBuilder .createRequestItem(context, item, bitstream) @@ -166,8 +161,6 @@ public void testFindOneAuthenticated() @Test public void testFindOneNotAuthenticated() throws Exception { - System.out.println("findOne (not authenticated)"); - // Create a request. RequestItem request = RequestItemBuilder .createRequestItem(context, item, bitstream) @@ -190,8 +183,6 @@ public void testFindOneNotAuthenticated() @Test public void testFindOneNonexistent() throws Exception { - System.out.println("findOne (nonexistent request)"); - String uri = URI_ROOT + "/impossible"; getClient().perform(get(uri)) .andExpect(status().isNotFound()); @@ -207,8 +198,6 @@ public void testFindOneNonexistent() @Test public void testCreateAndReturnAuthenticated() throws SQLException, AuthorizeException, IOException, Exception { - System.out.println("createAndReturn (authenticated)"); - // Fake up a request in REST form. RequestItemRest rir = new RequestItemRest(); rir.setAllfiles(true); @@ -390,7 +379,6 @@ public void testCreateAndReturnBadRequest() @Test public void testCreateWithInvalidCSRF() throws Exception { - System.out.println("testCreateWithInvalidCSRF"); // Login via password to retrieve a valid token String token = getAuthToken(eperson.getEmail(), password); @@ -415,7 +403,7 @@ public void testCreateWithInvalidCSRF() getClient().perform(post(URI_ROOT) .content(mapper.writeValueAsBytes(rir)) .contentType(contentType) - .with(csrf().useInvalidToken().asHeader()) + .with(invalidCsrfToken()) .secure(true) .cookie(cookies)) // Should return a 403 Forbidden, for an invalid CSRF token @@ -549,8 +537,6 @@ public void testPutUnauthenticated() @Test public void testPutBadRequest() throws Exception { - System.out.println("put bad requests"); - // Create an item request to approve. RequestItem itemRequest = RequestItemBuilder .createRequestItem(context, item, bitstream) @@ -577,7 +563,6 @@ public void testPutBadRequest() @Test public void testPutCompletedRequest() throws Exception { - System.out.println("put completed request"); // Create an item request that is already denied. RequestItem itemRequest = RequestItemBuilder @@ -605,7 +590,6 @@ public void testPutCompletedRequest() */ @Test public void testGetDomainClass() { - System.out.println("getDomainClass"); RequestItemRepository instance = new RequestItemRepository(); Class instanceClass = instance.getDomainClass(); assertEquals("Wrong domain class", RequestItemRest.class, instanceClass); 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 02834607113d..8a40ed956cb6 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 @@ -29,9 +29,9 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.matcher.ResourcePolicyMatcher; import org.dspace.app.rest.model.ResourcePolicyRest; 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 aafc75a065a1..c12eff1f176e 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 @@ -17,8 +17,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SiteRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SiteRestRepositoryIT.java index 26b01071d179..724e785ba2ab 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SiteRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SiteRestRepositoryIT.java @@ -133,7 +133,7 @@ public void patchReplaceMultipleDescriptionSite() throws Exception { getClient(token) .perform(patch("/api/core/sites/" + site.getID()) .content(requestBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect( jsonPath("$.metadata", diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SitemapRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SitemapRestControllerIT.java index 04d22718e846..681e9bf16b04 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SitemapRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SitemapRestControllerIT.java @@ -14,8 +14,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import javax.servlet.ServletException; - import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.builder.CollectionBuilder; @@ -131,18 +129,20 @@ public void testSitemap_notValidSiteMapFile() throws Exception { .andExpect(status().isNotFound()); } - @Test(expected = ServletException.class) + @Test public void testSitemap_fileSystemTraversal_dspaceCfg() throws Exception { //** WHEN ** //We attempt to use endpoint for malicious file system traversal - getClient().perform(get("/" + SITEMAPS_ENDPOINT + "/%2e%2e/config/dspace.cfg")); + getClient().perform(get("/" + SITEMAPS_ENDPOINT + "/%2e%2e/config/dspace.cfg")) + .andExpect(status().isBadRequest()); } - @Test(expected = ServletException.class) + @Test public void testSitemap_fileSystemTraversal_dspaceCfg2() throws Exception { //** WHEN ** //We attempt to use endpoint for malicious file system traversal - getClient().perform(get("/" + SITEMAPS_ENDPOINT + "/%2e%2e%2fconfig%2fdspace.cfg")); + getClient().perform(get("/" + SITEMAPS_ENDPOINT + "/%2e%2e%2fconfig%2fdspace.cfg")) + .andExpect(status().isBadRequest()); } @Test diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/StatisticsRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/StatisticsRestRepositoryIT.java index 5544ecdb032b..adb161b0a986 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/StatisticsRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/StatisticsRestRepositoryIT.java @@ -135,13 +135,13 @@ public void usagereports_withoutId_NotImplementedException() throws Exception { @Test public void usagereports_notProperUUIDAndReportId_Exception() throws Exception { getClient(adminToken).perform(get("/api/statistics/usagereports/notProperUUIDAndReportId")) - .andExpect(status().is(HttpStatus.BAD_REQUEST.value())); + .andExpect(status().isNotFound()); } @Test public void usagereports_nonValidUUIDpart_Exception() throws Exception { getClient(adminToken).perform(get("/api/statistics/usagereports/notAnUUID" + "_" + TOTAL_VISITS_REPORT_ID)) - .andExpect(status().is(HttpStatus.BAD_REQUEST.value())); + .andExpect(status().isNotFound()); } @Test @@ -828,7 +828,7 @@ public void TotalDownloadsReport_Item_NotVisited() throws Exception { public void TotalDownloadsReport_NotSupportedDSO_Collection() throws Exception { getClient(adminToken) .perform(get("/api/statistics/usagereports/" + collectionVisited.getID() + "_" + TOTAL_DOWNLOADS_REPORT_ID)) - .andExpect(status().is(HttpStatus.BAD_REQUEST.value())); + .andExpect(status().isNotFound()); } /** 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 3b8c87ce5f2c..a6f3999b94ac 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 @@ -32,6 +32,11 @@ */ public class SubmissionDefinitionsControllerIT extends AbstractControllerIntegrationTest { + // 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 = 11; + @Test public void findAll() throws Exception { //When we call the root endpoint as anonymous user @@ -258,10 +263,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=1"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=" + (totalDefinitions - 1)), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(0))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -284,10 +289,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=1"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=" + (totalDefinitions - 1)), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(1))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -310,10 +315,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=2"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=" + (totalDefinitions - 1)), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(2))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -336,10 +341,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=3"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=" + (totalDefinitions - 1)), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(3))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -362,10 +367,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=4"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=" + (totalDefinitions - 1)), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(4))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -388,10 +393,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=5"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=" + (totalDefinitions - 1)), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(5))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -414,10 +419,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=5"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=10"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(5))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -440,10 +445,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=6"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=10"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(6))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -466,10 +471,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=7"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=10"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(7))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -492,10 +497,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=8"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=10"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(8))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -515,10 +520,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=9"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=9"), Matchers.containsString("size=1")))) + Matchers.containsString("page=10"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(10))) - .andExpect(jsonPath("$.page.totalPages", is(10))) + .andExpect(jsonPath("$.page.totalElements", is(totalDefinitions))) + .andExpect(jsonPath("$.page.totalPages", is(totalDefinitions))) .andExpect(jsonPath("$.page.number", is(9))); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SupervisionOrderRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SupervisionOrderRestRepositoryIT.java index 27b436b6bc76..cd8f8344133b 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SupervisionOrderRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SupervisionOrderRestRepositoryIT.java @@ -25,8 +25,8 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.dspace.app.rest.matcher.WorkflowItemMatcher; import org.dspace.app.rest.matcher.WorkspaceItemMatcher; import org.dspace.app.rest.model.patch.ReplaceOperation; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/TaskRestRepositoriesIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/TaskRestRepositoriesIT.java index 3a8480a2a7b2..d017703d6267 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/TaskRestRepositoriesIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/TaskRestRepositoriesIT.java @@ -2738,7 +2738,7 @@ public void unclaimedTaskTest_Patch_EditMetadataOptionAllowed() throws Exception getClient(authToken).perform(patch("/api/workflow/workflowitems/" + witem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isUnprocessableEntity()); } @@ -2892,7 +2892,7 @@ public void patchTest_ClaimedTask_EditMetadataOptionNotAllowed() throws Exceptio getClient(authToken).perform(patch("/api/workflow/workflowitems/" + witem.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isUnprocessableEntity()); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/VersionRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/VersionRestRepositoryIT.java index ed3e811db2ce..daec24d29e70 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/VersionRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/VersionRestRepositoryIT.java @@ -931,7 +931,7 @@ public void patchReplaceSummaryTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.allOf( hasJsonPath("$.version", is(v2.getVersionNumber())), @@ -979,7 +979,7 @@ public void patchRemoveSummaryTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.allOf( hasJsonPath("$.version", is(v2.getVersionNumber())), @@ -1027,7 +1027,7 @@ public void patchAddSummaryTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.allOf( hasJsonPath("$.version", is(v2.getVersionNumber())), @@ -1054,7 +1054,7 @@ public void patchVersionNotFoundTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform(patch("/api/versioning/versions/" + Integer.MAX_VALUE) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isNotFound()); } @@ -1089,7 +1089,7 @@ public void patchAddSummaryBadRequestTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isBadRequest()); } @@ -1124,7 +1124,7 @@ public void patchWrongPathUnprocessableEntityTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isUnprocessableEntity()); } @@ -1159,7 +1159,7 @@ public void patchReplaceVersionUnprocessableEntityTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isUnprocessableEntity()); } @@ -1194,7 +1194,7 @@ public void patchReplaceSummaryUnauthorizedTest() throws Exception { getClient().perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isUnauthorized()); } @@ -1227,7 +1227,7 @@ public void patchRemoveSummaryUnauthorizedTest() throws Exception { getClient().perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isUnauthorized()); } @@ -1261,7 +1261,7 @@ public void patchRemoveSummaryForbiddenTest() throws Exception { String epersonToken = getAuthToken(eperson.getEmail(), password); getClient(epersonToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isForbidden()); } @@ -1297,7 +1297,7 @@ public void patchReplaceSummaryByCollectionAdminTest() throws Exception { String colAdminToken = getAuthToken(eperson.getEmail(), password); getClient(colAdminToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.allOf( hasJsonPath("$.version", is(v2.getVersionNumber())), @@ -1359,7 +1359,7 @@ public void patchReplaceSummaryByCommunityAdminTest() throws Exception { getClient(adminCommBToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isForbidden()); getClient(adminCommAToken).perform(get("/api/versioning/versions/" + v2.getID())) @@ -1368,7 +1368,7 @@ public void patchReplaceSummaryByCommunityAdminTest() throws Exception { getClient(adminCommAToken).perform(patch("/api/versioning/versions/" + v2.getID()) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); getClient(adminCommAToken).perform(get("/api/versioning/versions/" + v2.getID())) @@ -1412,17 +1412,17 @@ public void patchReplaceSummaryWithVersioningDisabledTest() throws Exception { getClient(adminToken).perform(patch("/api/versioning/versions/" + Integer.MAX_VALUE) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isForbidden()); getClient(epersonToken).perform(patch("/api/versioning/versions/" + Integer.MAX_VALUE) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isForbidden()); getClient().perform(patch("/api/versioning/versions/" + Integer.MAX_VALUE) .content(patchBody) - .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .contentType(jakarta.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isUnauthorized()); } 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 c3063ca23459..76512272444d 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 @@ -17,8 +17,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import javax.el.MethodNotFoundException; +import jakarta.el.MethodNotFoundException; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; 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..6275360b3c5b 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 @@ -28,8 +28,8 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.io.IOUtils; import org.dspace.app.rest.matcher.CollectionMatcher; import org.dspace.app.rest.matcher.ItemMatcher; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java index 84cf6ef0508a..3c44fa3c4a30 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java @@ -46,10 +46,10 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.matchers.JsonPathMatchers; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.time.DateUtils; import org.dspace.app.ldn.NotifyServiceEntity; @@ -8622,18 +8622,17 @@ public void testSubmissionWithCOARNotifyServicesSection() throws Exception { // create three notify services NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withLdnUrl("https://service2.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceThree = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withLdnUrl("https://service3.ldn.org/inbox") .build(); @@ -8675,18 +8674,17 @@ public void patchCOARNotifyServiceAddTest() throws Exception { NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withLdnUrl("https://service2.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceThree = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withLdnUrl("https://service3.ldn.org/inbox") .build(); @@ -8754,18 +8752,17 @@ public void patchCOARNotifyServiceAddWithInCompatibleServicesTest() throws Excep NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withLdnUrl("https://service2.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceThree = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withLdnUrl("https://service3.ldn.org/inbox") .build(); @@ -8817,8 +8814,7 @@ public void patchCOARNotifyServiceAddWithInvalidPatternTest() throws Exception { NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); @@ -8860,8 +8856,7 @@ public void patchCOARNotifyServiceAddWithInvalidServiceIdTest() throws Exception NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); @@ -8911,18 +8906,17 @@ public void patchCOARNotifyServiceReplaceTest() throws Exception { NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withLdnUrl("https://service2.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceThree = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withLdnUrl("https://service3.ldn.org/inbox") .build(); @@ -8996,18 +8990,17 @@ public void patchCOARNotifyServiceReplaceWithInCompatibleServicesTest() throws E NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withLdnUrl("https://service2.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceThree = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withLdnUrl("https://service3.ldn.org/inbox") .build(); @@ -9059,13 +9052,12 @@ public void patchCOARNotifyServiceRemoveTest() throws Exception { NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withLdnUrl("https://service2.ldn.org/inbox") .build(); @@ -9120,18 +9112,17 @@ public void submissionCOARNotifyServicesSectionWithValidationErrorsTest() throws NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceTwo = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name two") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name two") .withLdnUrl("https://service2.ldn.org/inbox") .build(); NotifyServiceEntity notifyServiceThree = - NotifyServiceBuilder.createNotifyServiceBuilder(context).withName("service name three") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name three") .withLdnUrl("https://service3.ldn.org/inbox") .build(); @@ -9200,8 +9191,7 @@ public void submissionCOARNotifyServicesSectionWithoutValidationErrorsTest() thr NotifyServiceEntity notifyServiceOne = - NotifyServiceBuilder.createNotifyServiceBuilder(context) - .withName("service name one") + NotifyServiceBuilder.createNotifyServiceBuilder(context, "service name one") .withLdnUrl("https://service.ldn.org/inbox") .build(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ComColAdminFeatureIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ComColAdminFeatureIT.java index a3b73717937c..e50553cc5734 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ComColAdminFeatureIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ComColAdminFeatureIT.java @@ -102,8 +102,10 @@ public void testAdmin() throws Exception { String token = getAuthToken(admin.getEmail(), password); // Verify the general admin has this feature + // Filter by "feature" ID because Admins may have >20 features enabled & cause this endpoint to paginate. getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/sites/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/sites/" + siteService.findSite(context).getID() + + "&feature=isComColAdmin")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='isComColAdmin')]") @@ -175,8 +177,10 @@ public void testSubGroupOfAdminGroup() throws Exception { String token = getAuthToken(eperson.getEmail(), password); // Verify an ePerson in a subgroup of the site administrators has this feature + // Filter by "feature" ID because Admins may have >20 features enabled & cause this endpoint to paginate. getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/sites/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/sites/" + siteService.findSite(context).getID() + + "&feature=isComColAdmin")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='isComColAdmin')]") @@ -284,8 +288,10 @@ public void testSubSubGroupOfAdminGroup() throws Exception { String token = getAuthToken(eperson.getEmail(), password); // Verify an ePerson in a sub-subgroup of the site administrators has this feature + // Filter by "feature" ID because Admins may have >20 features enabled & cause this endpoint to paginate. getClient(token).perform(get("/api/authz/authorizations/search/object?embed=feature&uri=" - + "http://localhost/api/core/sites/" + siteService.findSite(context).getID())) + + "http://localhost/api/core/sites/" + siteService.findSite(context).getID() + + "&feature=isComColAdmin")) .andExpect(status().isOk()) .andExpect( jsonPath("$._embedded.authorizations[?(@._embedded.feature.id=='isComColAdmin')]") diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/eperson/DeleteEPersonSubmitterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/eperson/DeleteEPersonSubmitterIT.java index d1679ae1d20b..05d83de20ac6 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/eperson/DeleteEPersonSubmitterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/eperson/DeleteEPersonSubmitterIT.java @@ -22,8 +22,8 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.requestitem.RequestItemAuthor; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/iiif/IIIFControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/iiif/IIIFControllerIT.java index d17db108bab6..ae509e42c5a5 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/iiif/IIIFControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/iiif/IIIFControllerIT.java @@ -16,8 +16,8 @@ import java.io.InputStream; import java.util.UUID; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.codec.CharEncoding; import org.apache.commons.io.IOUtils; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java index 6483758802c5..cc15700b924e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java @@ -169,4 +169,75 @@ public static Matcher entityTypeFacet(boolean hasNext) { hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/entityType")) ); } + + public static Matcher relatedItemFacet(boolean b) { + return allOf( + hasJsonPath("$.name", is("relateditem")), + hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", any(Integer.class)), + hasJsonPath("$._links.self.href", containsString("api/discover/facets/relateditem")), + hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/relateditem")) + ); + } + + public static Matcher originFacet(boolean b) { + return allOf( + hasJsonPath("$.name", is("origin")), + hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", any(Integer.class)), + hasJsonPath("$._links.self.href", containsString("api/discover/facets/origin")), + hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/origin")) + ); + } + + public static Matcher targetFacet(boolean b) { + return allOf( + hasJsonPath("$.name", is("target")), + hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", any(Integer.class)), + hasJsonPath("$._links.self.href", containsString("api/discover/facets/target")), + hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/target")) + ); + } + + public static Matcher queueStatusFacet(boolean b) { + return allOf( + hasJsonPath("$.name", is("queue_status")), + hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", any(Integer.class)), + hasJsonPath("$._links.self.href", containsString("api/discover/facets/queue_status")), + hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/queue_status")) + ); + } + + public static Matcher activityStreamTypeFacet(boolean b) { + return allOf( + hasJsonPath("$.name", is("activity_stream_type")), + hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", any(Integer.class)), + hasJsonPath("$._links.self.href", containsString("api/discover/facets/activity_stream_type")), + hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/activity_stream_type")) + ); + } + + public static Matcher coarNotifyTypeFacet(boolean b) { + return allOf( + hasJsonPath("$.name", is("coar_notify_type")), + hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", any(Integer.class)), + hasJsonPath("$._links.self.href", containsString("api/discover/facets/coar_notify_type")), + hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/coar_notify_type")) + ); + } + + public static Matcher notificationTypeFacet(boolean b) { + return allOf( + hasJsonPath("$.name", is("notification_type")), + hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", any(Integer.class)), + hasJsonPath("$._links.self.href", containsString("api/discover/facets/notification_type")), + hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/notification_type")) + ); + } + } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/ResourcePolicyMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/ResourcePolicyMatcher.java index d80fb638cdd3..caae7bb7c0e6 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/ResourcePolicyMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/ResourcePolicyMatcher.java @@ -14,8 +14,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import javax.annotation.Nullable; - +import jakarta.annotation.Nullable; import org.dspace.authorize.ResourcePolicy; import org.dspace.content.DSpaceObject; import org.dspace.core.Constants; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/projection/MockProjection.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/projection/MockProjection.java index 780cc90cfbcf..a74462e1ebe0 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/projection/MockProjection.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/projection/MockProjection.java @@ -7,8 +7,7 @@ */ package org.dspace.app.rest.projection; -import javax.annotation.Nullable; - +import jakarta.annotation.Nullable; import org.dspace.app.rest.model.LinkRest; import org.dspace.app.rest.model.MockObject; import org.dspace.app.rest.model.MockObjectRest; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/AbstractMockObjectChildLinkRepository.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/AbstractMockObjectChildLinkRepository.java index 0b9babda6874..2e974e47e9ea 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/AbstractMockObjectChildLinkRepository.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/AbstractMockObjectChildLinkRepository.java @@ -9,9 +9,9 @@ import java.util.ArrayList; import java.util.List; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.app.rest.model.MockObject; import org.dspace.app.rest.model.MockObjectRest; import org.dspace.app.rest.projection.Projection; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/DSpaceCsrfTokenRepositoryTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/DSpaceCsrfTokenRepositoryTest.java index 0b9964fe6ab4..95ce6bb37ff1 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/DSpaceCsrfTokenRepositoryTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/DSpaceCsrfTokenRepositoryTest.java @@ -8,11 +8,13 @@ package org.dspace.app.rest.security; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; -import java.util.List; -import javax.servlet.http.Cookie; -import javax.ws.rs.core.HttpHeaders; - +import jakarta.servlet.http.Cookie; +import jakarta.ws.rs.core.HttpHeaders; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -20,10 +22,11 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.DeferredCsrfToken; /** - * This is almost an exact copy of Spring Security's CookieCsrfTokenRepositoryTests - * https://github.com/spring-projects/spring-security/blob/5.2.x/web/src/test/java/org/springframework/security/web/csrf/CookieCsrfTokenRepositoryTests.java + * This is almost an exact copy of Spring Security's DSpaceCsrfTokenRepositoryTests + * https://github.com/spring-projects/spring-security/blob/6.2.x/web/src/test/java/org/springframework/security/web/csrf/CookieCsrfTokenRepositoryTests.java * * The only modifications are: * - Updating these tests to use our custom DSpaceCsrfTokenRepository @@ -46,12 +49,9 @@ public void setup() { @Test public void generateToken() { CsrfToken generateToken = this.repository.generateToken(this.request); - assertThat(generateToken).isNotNull(); - assertThat(generateToken.getHeaderName()) - .isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_HEADER_NAME); - assertThat(generateToken.getParameterName()) - .isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_PARAMETER_NAME); + assertThat(generateToken.getHeaderName()).isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_HEADER_NAME); + assertThat(generateToken.getParameterName()).isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_PARAMETER_NAME); assertThat(generateToken.getToken()).isNotEmpty(); } @@ -61,9 +61,7 @@ public void generateTokenCustom() { String parameterName = "paramName"; this.repository.setHeaderName(headerName); this.repository.setParameterName(parameterName); - CsrfToken generateToken = this.repository.generateToken(this.request); - assertThat(generateToken).isNotNull(); assertThat(generateToken.getHeaderName()).isEqualTo(headerName); assertThat(generateToken.getParameterName()).isEqualTo(parameterName); @@ -74,17 +72,21 @@ public void generateTokenCustom() { public void saveToken() { CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); - - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); - + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.getMaxAge()).isEqualTo(-1); - assertThat(tokenCookie.getName()) - .isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getName()).isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.getPath()).isEqualTo(this.request.getContextPath()); assertThat(tokenCookie.getSecure()).isEqualTo(this.request.isSecure()); assertThat(tokenCookie.getValue()).isEqualTo(token.getToken()); - assertThat(tokenCookie.isHttpOnly()).isEqualTo(true); + assertThat(tokenCookie.isHttpOnly()).isTrue(); + } + + @Test + public void saveTokenShouldUseResponseAddCookie() { + CsrfToken token = this.repository.generateToken(this.request); + MockHttpServletResponse spyResponse = spy(this.response); + this.repository.saveToken(token, this.request, spyResponse); + verify(spyResponse).addCookie(any(Cookie.class)); } @Test @@ -92,30 +94,73 @@ public void saveTokenSecure() { this.request.setSecure(true); CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getSecure()).isTrue(); - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + // DSpace Custom assert to verify SameSite attribute is "None" when cookie is secure + assertThat(tokenCookie.getAttribute("SameSite")).containsIgnoringCase("None"); + } + + // Custom test for DSpace to verify behavior for non-secure requests + @Test + public void saveTokenNotSecure() { + this.request.setSecure(false); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getSecure()).isFalse(); + // DSpace Custom assert to verify SameSite attribute is "Lax" when cookie is NOT secure + assertThat(tokenCookie.getAttribute("SameSite")).containsIgnoringCase("Lax"); + } + + @Test + public void saveTokenSecureFlagTrue() { + this.request.setSecure(false); + this.repository.setSecure(Boolean.TRUE); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.getSecure()).isTrue(); - // DSpace Custom assert to verify SameSite attribute is set - // The Cookie class doesn't yet support SameSite, so we have to re-read - // the cookie from our headers, and check it. - List headers = this.response.getHeaders(HttpHeaders.SET_COOKIE); - assertThat(headers.size()).isEqualTo(1); - assertThat(headers.get(0)).containsIgnoringCase("SameSite=None"); } @Test - public void saveTokenNull() { + public void saveTokenSecureFlagTrueUsingCustomizer() { + this.request.setSecure(false); + this.repository.setCookieCustomizer((customizer) -> customizer.secure(Boolean.TRUE)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getSecure()).isTrue(); + } + + @Test + public void saveTokenSecureFlagFalse() { this.request.setSecure(true); - this.repository.saveToken(null, this.request, this.response); + this.repository.setSecure(Boolean.FALSE); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getSecure()).isFalse(); + } - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + @Test + public void saveTokenSecureFlagFalseUsingCustomizer() { + this.request.setSecure(true); + this.repository.setCookieCustomizer((customizer) -> customizer.secure(Boolean.FALSE)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getSecure()).isFalse(); + } + @Test + public void saveTokenNull() { + this.request.setSecure(true); + this.repository.saveToken(null, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.getMaxAge()).isZero(); - assertThat(tokenCookie.getName()) - .isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getName()).isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.getPath()).isEqualTo(this.request.getContextPath()); assertThat(tokenCookie.getSecure()).isEqualTo(this.request.isSecure()); assertThat(tokenCookie.getValue()).isEmpty(); @@ -126,10 +171,16 @@ public void saveTokenHttpOnlyTrue() { this.repository.setCookieHttpOnly(true); CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.isHttpOnly()).isTrue(); + } - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); - + @Test + public void saveTokenHttpOnlyTrueUsingCustomizer() { + this.repository.setCookieCustomizer((customizer) -> customizer.httpOnly(true)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.isHttpOnly()).isTrue(); } @@ -138,10 +189,16 @@ public void saveTokenHttpOnlyFalse() { this.repository.setCookieHttpOnly(false); CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.isHttpOnly()).isFalse(); + } - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); - + @Test + public void saveTokenHttpOnlyFalseUsingCustomizer() { + this.repository.setCookieCustomizer((customizer) -> customizer.httpOnly(false)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.isHttpOnly()).isFalse(); } @@ -150,10 +207,7 @@ public void saveTokenWithHttpOnlyFalse() { this.repository = DSpaceCsrfTokenRepository.withHttpOnlyFalse(); CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); - - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); - + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.isHttpOnly()).isFalse(); } @@ -163,10 +217,7 @@ public void saveTokenCustomPath() { this.repository.setCookiePath(customPath); CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); - - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); - + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.getPath()).isEqualTo(this.repository.getCookiePath()); } @@ -176,10 +227,7 @@ public void saveTokenEmptyCustomPath() { this.repository.setCookiePath(customPath); CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); - - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); - + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.getPath()).isEqualTo(this.request.getContextPath()); } @@ -189,10 +237,7 @@ public void saveTokenNullCustomPath() { this.repository.setCookiePath(customPath); CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); - - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); - + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); assertThat(tokenCookie.getPath()).isEqualTo(this.request.getContextPath()); } @@ -200,14 +245,80 @@ public void saveTokenNullCustomPath() { public void saveTokenWithCookieDomain() { String domainName = "example.com"; this.repository.setCookieDomain(domainName); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getDomain()).isEqualTo(domainName); + } + + @Test + public void saveTokenWithCookieDomainUsingCustomizer() { + String domainName = "example.com"; + this.repository.setCookieCustomizer((customizer) -> customizer.domain(domainName)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getDomain()).isEqualTo(domainName); + } + @Test + public void saveTokenWithCookieMaxAge() { + int maxAge = 1200; + this.repository.setCookieMaxAge(maxAge); CsrfToken token = this.repository.generateToken(this.request); this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getMaxAge()).isEqualTo(maxAge); + } - Cookie tokenCookie = this.response - .getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + @Test + public void saveTokenWithCookieMaxAgeUsingCustomizer() { + int maxAge = 1200; + this.repository.setCookieCustomizer((customizer) -> customizer.maxAge(maxAge)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getMaxAge()).isEqualTo(maxAge); + } - assertThat(tokenCookie.getDomain()).isEqualTo(domainName); + @Test + public void saveTokenWithSameSiteNull() { + String sameSitePolicy = null; + this.repository.setCookieCustomizer((customizer) -> customizer.sameSite(sameSitePolicy)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getAttribute("SameSite")).isNull(); + } + + @Test + public void saveTokenWithSameSiteStrict() { + String sameSitePolicy = "Strict"; + this.repository.setCookieCustomizer((customizer) -> customizer.sameSite(sameSitePolicy)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getAttribute("SameSite")).isEqualTo(sameSitePolicy); + } + + @Test + public void saveTokenWithSameSiteLax() { + String sameSitePolicy = "Lax"; + this.repository.setCookieCustomizer((customizer) -> customizer.sameSite(sameSitePolicy)); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getAttribute("SameSite")).isEqualTo(sameSitePolicy); + } + + @Test + public void saveTokenWithExistingSetCookieThenDoesNotOverwrite() { + this.response.setHeader(HttpHeaders.SET_COOKIE, "MyCookie=test"); + this.repository = new DSpaceCsrfTokenRepository(); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + assertThat(this.response.getCookie("MyCookie")).isNotNull(); + assertThat(this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME)).isNotNull(); } @Test @@ -218,32 +329,24 @@ public void loadTokenNoCookiesNull() { @Test public void loadTokenCookieIncorrectNameNull() { this.request.setCookies(new Cookie("other", "name")); - assertThat(this.repository.loadToken(this.request)).isNull(); } @Test public void loadTokenCookieValueEmptyString() { - this.request.setCookies( - new Cookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, "")); - + this.request.setCookies(new Cookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, "")); assertThat(this.repository.loadToken(this.request)).isNull(); } @Test public void loadToken() { CsrfToken generateToken = this.repository.generateToken(this.request); - this.request - .setCookies(new Cookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, - generateToken.getToken())); - + .setCookies(new Cookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, generateToken.getToken())); CsrfToken loadToken = this.repository.loadToken(this.request); - assertThat(loadToken).isNotNull(); assertThat(loadToken.getHeaderName()).isEqualTo(generateToken.getHeaderName()); - assertThat(loadToken.getParameterName()) - .isEqualTo(generateToken.getParameterName()); + assertThat(loadToken.getParameterName()).isEqualTo(generateToken.getParameterName()); assertThat(loadToken.getToken()).isNotEmpty(); } @@ -256,32 +359,95 @@ public void loadTokenCustom() { this.repository.setHeaderName(headerName); this.repository.setParameterName(parameterName); this.repository.setCookieName(cookieName); - this.request.setCookies(new Cookie(cookieName, value)); - CsrfToken loadToken = this.repository.loadToken(this.request); - assertThat(loadToken).isNotNull(); assertThat(loadToken.getHeaderName()).isEqualTo(headerName); assertThat(loadToken.getParameterName()).isEqualTo(parameterName); assertThat(loadToken.getToken()).isEqualTo(value); } - @Test(expected = IllegalArgumentException.class) + @Test + public void loadDeferredTokenWhenDoesNotExistThenGeneratedAndSaved() { + DeferredCsrfToken deferredCsrfToken = this.repository.loadDeferredToken(this.request, this.response); + CsrfToken csrfToken = deferredCsrfToken.get(); + assertThat(csrfToken).isNotNull(); + assertThat(deferredCsrfToken.isGenerated()).isTrue(); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie).isNotNull(); + assertThat(tokenCookie.getMaxAge()).isEqualTo(-1); + assertThat(tokenCookie.getName()).isEqualTo(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie.getPath()).isEqualTo(this.request.getContextPath()); + assertThat(tokenCookie.getSecure()).isEqualTo(this.request.isSecure()); + assertThat(tokenCookie.getValue()).isEqualTo(csrfToken.getToken()); + assertThat(tokenCookie.isHttpOnly()).isEqualTo(true); + } + + @Test + public void loadDeferredTokenWhenExistsAndNullSavedThenGeneratedAndSaved() { + CsrfToken generatedToken = this.repository.generateToken(this.request); + this.request + .setCookies(new Cookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, generatedToken.getToken())); + this.repository.saveToken(null, this.request, this.response); + DeferredCsrfToken deferredCsrfToken = this.repository.loadDeferredToken(this.request, this.response); + CsrfToken csrfToken = deferredCsrfToken.get(); + assertThat(csrfToken).isNotNull(); + assertThat(generatedToken).isNotEqualTo(csrfToken); + assertThat(deferredCsrfToken.isGenerated()).isTrue(); + } + + @Test + public void cookieCustomizer() { + String domainName = "example.com"; + String customPath = "/custompath"; + String sameSitePolicy = "Strict"; + this.repository.setCookieCustomizer((customizer) -> { + customizer.domain(domainName); + customizer.secure(false); + customizer.path(customPath); + customizer.sameSite(sameSitePolicy); + }); + CsrfToken token = this.repository.generateToken(this.request); + this.repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie).isNotNull(); + assertThat(tokenCookie.getMaxAge()).isEqualTo(-1); + assertThat(tokenCookie.getDomain()).isEqualTo(domainName); + assertThat(tokenCookie.getPath()).isEqualTo(customPath); + assertThat(tokenCookie.isHttpOnly()).isEqualTo(Boolean.TRUE); + assertThat(tokenCookie.getAttribute("SameSite")).isEqualTo(sameSitePolicy); + } + + @Test + public void withHttpOnlyFalseWhenCookieCustomizerThenStillDefaultsToFalse() { + DSpaceCsrfTokenRepository repository = DSpaceCsrfTokenRepository.withHttpOnlyFalse(); + repository.setCookieCustomizer((customizer) -> customizer.maxAge(1000)); + CsrfToken token = repository.generateToken(this.request); + repository.saveToken(token, this.request, this.response); + Cookie tokenCookie = this.response.getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + assertThat(tokenCookie).isNotNull(); + assertThat(tokenCookie.getMaxAge()).isEqualTo(1000); + assertThat(tokenCookie.isHttpOnly()).isEqualTo(Boolean.FALSE); + } + + @Test public void setCookieNameNullIllegalArgumentException() { - this.repository.setCookieName(null); + assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setCookieName(null)); } - @Test(expected = IllegalArgumentException.class) + @Test public void setParameterNameNullIllegalArgumentException() { - this.repository.setParameterName(null); + assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setParameterName(null)); } - @Test(expected = IllegalArgumentException.class) + @Test public void setHeaderNameNullIllegalArgumentException() { - this.repository.setHeaderName(null); + assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setHeaderName(null)); } - + @Test + public void setCookieMaxAgeZeroIllegalArgumentException() { + assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setCookieMaxAge(0)); + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ShibbolethLoginFilterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ShibbolethLoginFilterIT.java index a8422ec10671..f48c58b2ee2f 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ShibbolethLoginFilterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ShibbolethLoginFilterIT.java @@ -16,8 +16,8 @@ import java.util.ArrayList; import java.util.List; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.dspace.app.rest.authorization.AuthorizationFeature; import org.dspace.app.rest.authorization.AuthorizationFeatureService; import org.dspace.app.rest.authorization.impl.CanChangePasswordFeature; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/EPersonClaimProviderTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/EPersonClaimProviderTest.java index 8ca6bbcc3bf3..461c8747d349 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/EPersonClaimProviderTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/EPersonClaimProviderTest.java @@ -13,9 +13,9 @@ import static org.mockito.Mockito.when; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jwt.JWTClaimsSet; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/JWTTokenHandlerTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/JWTTokenHandlerTest.java index 66bb68ad8102..f28cee14a38c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/JWTTokenHandlerTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/JWTTokenHandlerTest.java @@ -16,10 +16,10 @@ import java.util.Base64; import java.util.Date; import java.util.List; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/ShortLivedJWTTokenHandlerTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/ShortLivedJWTTokenHandlerTest.java index 70497218652e..d5a72ea9a5cd 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/ShortLivedJWTTokenHandlerTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/ShortLivedJWTTokenHandlerTest.java @@ -14,10 +14,10 @@ import java.text.ParseException; import java.util.Base64; import java.util.Date; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.junit.Before; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProviderTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProviderTest.java index 42ac74be85dc..95064368099c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProviderTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProviderTest.java @@ -14,9 +14,9 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; import com.nimbusds.jwt.JWTClaimsSet; +import jakarta.servlet.http.HttpServletRequest; import org.dspace.core.Context; import org.junit.After; import org.junit.Before; 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 4ec66fb00081..c4ab14250bca 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 @@ -7,7 +7,6 @@ */ package org.dspace.app.rest.test; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -17,14 +16,18 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.List; -import javax.servlet.Filter; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.Filter; +import jakarta.servlet.http.Cookie; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.Logger; import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.app.TestApplication; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.security.DSpaceCsrfTokenRepository; import org.dspace.app.rest.utils.DSpaceConfigurationInitializer; import org.dspace.app.rest.utils.DSpaceKernelInitializer; import org.junit.Assert; @@ -44,6 +47,8 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.RequestPostProcessor; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; @@ -80,6 +85,8 @@ mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS) public class AbstractControllerIntegrationTest extends AbstractIntegrationTestWithDatabase { + private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(); + protected static final String AUTHORIZATION_HEADER = "Authorization"; protected static final String AUTHORIZATION_COOKIE = "Authorization-cookie"; @@ -137,26 +144,20 @@ public MockMvc getClient(String authToken) throws SQLException { context.commit(); } - DefaultMockMvcBuilder mockMvcBuilder = webAppContextSetup(webApplicationContext) - //Always log the response to debug - .alwaysDo(MockMvcResultHandlers.print()) - //Add all filter implementations - .addFilters(new ErrorPageFilter()) - .addFilters(requestFilters.toArray(new Filter[requestFilters.size()])) - // Enable/Integrate Spring Security with MockMVC - .apply(springSecurity()); + DefaultMockMvcBuilder mockMvcBuilder = setupDefaultMockMvcBuilder(true); + + // Default to performing a GET request to the root path + MockHttpServletRequestBuilder defaultRequest = get("/"); - // Make sure all MockMvc requests (in all tests) include a valid CSRF token (in header) by default. // If an authToken was passed in, also make sure request sends the authToken in the "Authorization" header if (StringUtils.isNotBlank(authToken)) { - mockMvcBuilder.defaultRequest( - get("/").with(csrf().asHeader()).header(AUTHORIZATION_HEADER, AUTHORIZATION_TYPE + authToken)); - } else { - mockMvcBuilder.defaultRequest(get("/").with(csrf().asHeader())); + defaultRequest.header(AUTHORIZATION_HEADER, AUTHORIZATION_TYPE + authToken); } - return mockMvcBuilder - .build(); + // Make sure all MockMvc requests (in all tests) include a valid CSRF token by default. + defaultRequest.with(validCsrfToken()); + + return mockMvcBuilder.defaultRequest(defaultRequest).build(); } public MockHttpServletResponse getAuthResponse(String user, String password) throws Exception { @@ -205,4 +206,162 @@ public static RequestPostProcessor ip(final String ipAddress) { return request; }; } + + /** + * Adds a *valid* CSRF token to the current mock request. This is useful for tests + * that need to verify behavior when an valid CSRF token is sent. + * Usage: .with(validCsrfToken()) + *

+ * TODO: Ideally this would be replaced by Spring Security's "csrf().asHeader()". But, at this time + * that post processor doesn't fully support CookieCsrfTokenRepository's (which is what DSpace uses) + * See https://stackoverflow.com/a/77368421 and https://github.com/spring-projects/spring-security/issues/12774 + * @return RequestPostProcessor with invalid token added + */ + public RequestPostProcessor validCsrfToken() { + return request -> { + // Obtain the current CSRF token cookie from the (mock) backend via GET request + // TODO: This method may be expensive for ITs as it GETs a new token for every request. We may want to + // investigate if caching the CSRF token would work without causing random test failures. + Cookie csrfCookie = getCsrfTokenCookie(); + + if (csrfCookie != null) { + // Get any currently set cookies & append CSRF cookie to list + Cookie[] cookies = request.getCookies(); + + // To the current request, add the obtained CSRF cookie and matching CSRF header + request.setCookies(ArrayUtils.add(cookies, csrfCookie)); + request.addHeader(DSpaceCsrfTokenRepository.DEFAULT_CSRF_HEADER_NAME, csrfCookie.getValue()); + return request; + } else { + log.warn("Could not obtain CSRFToken to add it to the current mock request"); + return request; + } + }; + } + + /** + * Adds a *valid* CSRF token to the current mock request via a request parameter. This is useful for tests + * that need to verify behavior when an valid CSRF token is sent via a request param (e.g. ?_csrf=[token]). + * Usage: .with(validCsrfTokenViaParam()) + *

+ * This method is identical to validCsrfToken() except it sends the CSRF token as a request parameter instead of + * an HTTP Header. + *

+ * TODO: Ideally this would be replaced by Spring Security's "csrf()". But, at this time + * that post processor doesn't fully support CookieCsrfTokenRepository's (which is what DSpace uses) + * See https://stackoverflow.com/a/77368421 and https://github.com/spring-projects/spring-security/issues/12774 + * @return RequestPostProcessor with invalid token added + */ + public RequestPostProcessor validCsrfTokenViaParam() { + return request -> { + // Obtain the current CSRF token cookie from the (mock) backend via GET request + // TODO: This method may be expensive for ITs as it GETs a new token for every request. We may want to + // investigate if caching the CSRF token would work without causing random test failures. + Cookie csrfCookie = getCsrfTokenCookie(); + + if (csrfCookie != null) { + // Get any currently set cookies & append CSRF cookie to list + Cookie[] cookies = request.getCookies(); + + // If an CSRF cookie already exists in this list of cookies, remove it. We'll replace it below. + // (This is necessary because our tests all default to calling validCsrfToken()) + cookies = Arrays.stream(cookies) + .filter(c -> !c.getName() + .equalsIgnoreCase( + DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME)) + .toArray(Cookie[]::new); + + // Also remove CSRF header if it is already set. We'll send the CSRF token via a request parameter + request.removeHeader(DSpaceCsrfTokenRepository.DEFAULT_CSRF_HEADER_NAME); + + // To the current request, add the obtained CSRF cookie and matching CSRF parameter + request.setCookies(ArrayUtils.add(cookies, csrfCookie)); + request.addParameter(DSpaceCsrfTokenRepository.DEFAULT_CSRF_PARAMETER_NAME, csrfCookie.getValue()); + return request; + } else { + log.warn("Could not obtain CSRFToken to add it to the current mock request"); + return request; + } + }; + } + + /** + * Adds an invalid CSRF token to the current mock request. This is useful for tests which need to verify behavior + * when an invalid CSRF token is sent. + *

+ * Usage: .with(invalidCsrfToken()) + * @return RequestPostProcessor with invalid token added + */ + public RequestPostProcessor invalidCsrfToken() { + return request -> { + // Get any currently set request Cookies + Cookie[] cookies = request.getCookies(); + + // If an CSRF cookie already exists in this list of cookies, remove it. We'll replace it below. + // (This is necessary because our tests all default to sending a *valid* CSRF token) + cookies = Arrays.stream(cookies) + .filter(c -> !c.getName() + .equalsIgnoreCase( + DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME)) + .toArray(Cookie[]::new); + + // Also remove CSRF header if it is already set. We'll replace it below. + request.removeHeader(DSpaceCsrfTokenRepository.DEFAULT_CSRF_HEADER_NAME); + + // To the current mock request, add a fake CSRF cookie and header that do NOT match. + request.setCookies(ArrayUtils.add(cookies, + new Cookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME, + "fake-csrf-token"))); + request.addHeader(DSpaceCsrfTokenRepository.DEFAULT_CSRF_HEADER_NAME, "not-a-valid-csrf-token"); + return request; + }; + } + + + /** + * Setup our DefaultMockMvcBuilder for DSpace. This is centralized in a private method as it's used in + * multiple places in this class. + * @param enableLogging whether to default to logging the MockMvc request or not. + * @return DefaultMockMvcBuilder + */ + private DefaultMockMvcBuilder setupDefaultMockMvcBuilder(boolean enableLogging) { + DefaultMockMvcBuilder defaultMockMvcBuilder = webAppContextSetup(webApplicationContext) + // Add all filter implementations + .addFilters(new ErrorPageFilter()) + .addFilters(requestFilters.toArray(new Filter[requestFilters.size()])) + // Enable/Integrate Spring Security with MockMVC + .apply(springSecurity()); + + if (enableLogging) { + // Always log the MockMvc request/response, to allow for easier debugging. + return defaultMockMvcBuilder.alwaysDo(MockMvcResultHandlers.print()); + } else { + return defaultMockMvcBuilder; + } + } + + + /** + * Return the Cookie set by Spring Security which contains the CSRF token. + * The value() of the cookie is the CSRF Token. + * @return Cookie with CSRF token + * @throws Exception + */ + public Cookie getCsrfTokenCookie() { + try { + // Set up a non-logging MockMvc builder to obtain the CSRF cookie + // This call is not logged by default to avoid cluttering logs of ITs, but you can switch this to "true" + // if you wish it to be logged. + MockMvc mockMvc = setupDefaultMockMvcBuilder(false).build(); + + // Perform a GET request to our CSRF endpoint to obtain the current CSRF token + MvcResult mvcResult = mockMvc.perform(get("/api/security/csrf")).andReturn(); + + // Read and return the Cookie which contains the CSRF token for DSpace + return mvcResult.getResponse().getCookie(DSpaceCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME); + } catch (Exception e) { + log.error("Could not obtain the CSRF token cookie for Integration Tests", e); + } + return null; + } } 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 54339aa1d6f0..7745fba96c3f 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 @@ -16,7 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpEntity; import org.springframework.http.RequestEntity; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java index 423a4cbe3513..b22a74a33f3c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java @@ -11,10 +11,9 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import javax.ws.rs.core.MediaType; - import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MediaType; import org.junit.Assert; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/sword2/Swordv2IT.java b/dspace-server-webapp/src/test/java/org/dspace/app/sword2/Swordv2IT.java index 64e3db7dfc1a..a6dcfde49cae 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/sword2/Swordv2IT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/sword2/Swordv2IT.java @@ -237,7 +237,7 @@ public void depositAndEditViaSwordTest() throws Exception { String editLink = response.getHeaders().getLocation().toString(); // Body should include that link as the rel="edit" URL - assertThat(response.getBody(), containsString("")); + assertThat(response.getBody(), containsString(" - ${agnostic.build.dir}/test-classes/ + ${agnostic.build.dir}/test-classes @@ -97,13 +97,13 @@ - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided com.sun.mail - javax.mail + jakarta.mail org.mockito @@ -148,8 +148,8 @@ commons-io - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java b/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java index 313f676c5f6a..ce5e91576f6d 100644 --- a/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java +++ b/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java @@ -20,8 +20,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import org.apache.commons.lang3.ArrayUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -226,17 +226,12 @@ public void shutdown() { if (applicationContext != null) { try { + // This both closes the context and destroys all beans related to it applicationContext.close(); } catch (Exception e) { // keep going anyway log.warn("Exception closing ApplicationContext: {}", e.getMessage(), e); } - try { - applicationContext.destroy(); - } catch (Exception e) { - // keep going anyway - log.warn("Exception destroying ApplicationContext: {}", e.getMessage(), e); - } applicationContext = null; } diff --git a/dspace-services/src/main/java/org/dspace/services/EmailService.java b/dspace-services/src/main/java/org/dspace/services/EmailService.java index 1d09f06c1368..08dfd52815d6 100644 --- a/dspace-services/src/main/java/org/dspace/services/EmailService.java +++ b/dspace-services/src/main/java/org/dspace/services/EmailService.java @@ -8,7 +8,7 @@ package org.dspace.services; -import javax.mail.Session; +import jakarta.mail.Session; /** * @author mwood diff --git a/dspace-services/src/main/java/org/dspace/services/RequestService.java b/dspace-services/src/main/java/org/dspace/services/RequestService.java index d28a04ecf623..78233f9bdb35 100644 --- a/dspace-services/src/main/java/org/dspace/services/RequestService.java +++ b/dspace-services/src/main/java/org/dspace/services/RequestService.java @@ -8,9 +8,9 @@ package org.dspace.services; import java.util.UUID; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import org.dspace.services.model.Request; import org.dspace.services.model.RequestInterceptor; diff --git a/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java b/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java index 878e34cfade1..e26954ff0259 100644 --- a/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java +++ b/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java @@ -8,15 +8,15 @@ package org.dspace.services.email; import java.util.Properties; -import javax.annotation.PostConstruct; -import javax.mail.Authenticator; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; import javax.naming.InitialContext; import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.naming.NoInitialContextException; +import jakarta.annotation.PostConstruct; +import jakarta.mail.Authenticator; +import jakarta.mail.PasswordAuthentication; +import jakarta.mail.Session; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -26,7 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired; /** - * Provides mail sending services through JavaMail. If a {@link javax.mail.Session} + * Provides mail sending services through JavaMail. If a {@link jakarta.mail.Session} * instance is provided through JNDI, it will be used. If not, then a session * will be created from DSpace configuration data ({@code mail.server} etc.) * diff --git a/dspace-services/src/main/java/org/dspace/services/events/SystemEventService.java b/dspace-services/src/main/java/org/dspace/services/events/SystemEventService.java index 4cd4a523cd3d..401e0c7fc1d6 100644 --- a/dspace-services/src/main/java/org/dspace/services/events/SystemEventService.java +++ b/dspace-services/src/main/java/org/dspace/services/events/SystemEventService.java @@ -10,8 +10,8 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import org.apache.commons.lang3.ArrayUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-services/src/main/java/org/dspace/services/model/Request.java b/dspace-services/src/main/java/org/dspace/services/model/Request.java index ed9fb298b808..14a8207ca6b7 100644 --- a/dspace-services/src/main/java/org/dspace/services/model/Request.java +++ b/dspace-services/src/main/java/org/dspace/services/model/Request.java @@ -7,10 +7,10 @@ */ package org.dspace.services.model; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; public interface Request { public String getRequestId(); diff --git a/dspace-services/src/main/java/org/dspace/services/model/Session.java b/dspace-services/src/main/java/org/dspace/services/model/Session.java index 78b5f5c58671..ad6f6f032b25 100644 --- a/dspace-services/src/main/java/org/dspace/services/model/Session.java +++ b/dspace-services/src/main/java/org/dspace/services/model/Session.java @@ -8,7 +8,8 @@ package org.dspace.services.model; import java.util.Map; -import javax.servlet.http.HttpSession; + +import jakarta.servlet.http.HttpSession; /** * Represents a user's session (login session) in the system. Can hold diff --git a/dspace-services/src/main/java/org/dspace/services/sessions/StatelessRequestServiceImpl.java b/dspace-services/src/main/java/org/dspace/services/sessions/StatelessRequestServiceImpl.java index 9b67cd4bfcc6..9910b05dfaa1 100644 --- a/dspace-services/src/main/java/org/dspace/services/sessions/StatelessRequestServiceImpl.java +++ b/dspace-services/src/main/java/org/dspace/services/sessions/StatelessRequestServiceImpl.java @@ -15,11 +15,11 @@ import java.util.Objects; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/dspace-services/src/main/java/org/dspace/services/sessions/model/HttpRequestImpl.java b/dspace-services/src/main/java/org/dspace/services/sessions/model/HttpRequestImpl.java index 184285704214..e2b79c5b3ef1 100644 --- a/dspace-services/src/main/java/org/dspace/services/sessions/model/HttpRequestImpl.java +++ b/dspace-services/src/main/java/org/dspace/services/sessions/model/HttpRequestImpl.java @@ -7,11 +7,10 @@ */ package org.dspace.services.sessions.model; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.services.model.Request; public final class HttpRequestImpl extends AbstractRequestImpl implements Request { diff --git a/dspace-services/src/main/java/org/dspace/services/sessions/model/InternalRequestImpl.java b/dspace-services/src/main/java/org/dspace/services/sessions/model/InternalRequestImpl.java index ffc78daa0ac4..9b5b065991df 100644 --- a/dspace-services/src/main/java/org/dspace/services/sessions/model/InternalRequestImpl.java +++ b/dspace-services/src/main/java/org/dspace/services/sessions/model/InternalRequestImpl.java @@ -9,11 +9,11 @@ import java.util.HashMap; import java.util.Map; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dspace.services.model.Request; public final class InternalRequestImpl extends AbstractRequestImpl implements Request { diff --git a/dspace-services/src/main/java/org/dspace/utils/servlet/DSpaceWebappServletFilter.java b/dspace-services/src/main/java/org/dspace/utils/servlet/DSpaceWebappServletFilter.java index 8707eb5e4c27..f5126fbb6c31 100644 --- a/dspace-services/src/main/java/org/dspace/utils/servlet/DSpaceWebappServletFilter.java +++ b/dspace-services/src/main/java/org/dspace/utils/servlet/DSpaceWebappServletFilter.java @@ -8,14 +8,14 @@ package org.dspace.utils.servlet; import java.io.IOException; -import javax.annotation.Priority; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import jakarta.annotation.Priority; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import org.dspace.kernel.DSpaceKernel; import org.dspace.kernel.DSpaceKernelManager; import org.dspace.services.RequestService; @@ -35,7 +35,7 @@ public final class DSpaceWebappServletFilter implements Filter { /* (non-Javadoc) - * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) + * @see jakarta.servlet.Filter#init(jakarta.servlet.FilterConfig) */ @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -53,7 +53,7 @@ public void init(FilterConfig filterConfig) throws ServletException { } /* (non-Javadoc) - * @see javax.servlet.Filter#destroy() + * @see jakarta.servlet.Filter#destroy() */ @Override public void destroy() { @@ -63,8 +63,8 @@ public void destroy() { } /* (non-Javadoc) - * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet - * .FilterChain) + * @see jakarta.servlet.Filter#doFilter(jakarta.servlet.ServletRequest, jakarta.servlet.ServletResponse, + * jakarta.servlet.FilterChain) */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) diff --git a/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java b/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java index f66d32bb3b15..3c0c8610f165 100644 --- a/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java +++ b/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java @@ -16,9 +16,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import org.dspace.servicemanager.config.DSpaceConfigurationService; import org.dspace.servicemanager.example.ConcreteExample; import org.dspace.servicemanager.fakeservices.FakeService1; diff --git a/dspace-services/src/test/java/org/dspace/servicemanager/SampleAnnotationBean.java b/dspace-services/src/test/java/org/dspace/servicemanager/SampleAnnotationBean.java index e3d08100a4f1..f72d8b9c34e6 100644 --- a/dspace-services/src/test/java/org/dspace/servicemanager/SampleAnnotationBean.java +++ b/dspace-services/src/test/java/org/dspace/servicemanager/SampleAnnotationBean.java @@ -7,9 +7,8 @@ */ package org.dspace.servicemanager; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import org.dspace.servicemanager.example.ConcreteExample; import org.dspace.servicemanager.example.ServiceExample; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dspace-services/src/test/java/org/dspace/servicemanager/fakeservices/FakeService1.java b/dspace-services/src/test/java/org/dspace/servicemanager/fakeservices/FakeService1.java index eafbd8ac8b80..ba580f20853b 100644 --- a/dspace-services/src/test/java/org/dspace/servicemanager/fakeservices/FakeService1.java +++ b/dspace-services/src/test/java/org/dspace/servicemanager/fakeservices/FakeService1.java @@ -10,9 +10,9 @@ import java.io.Serializable; import java.util.List; import java.util.Map; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import org.dspace.kernel.mixins.ConfigChangeListener; import org.dspace.kernel.mixins.ServiceChangeListener; import org.dspace.services.ConfigurationService; diff --git a/dspace-services/src/test/java/org/dspace/servicemanager/fakeservices/FakeService2.java b/dspace-services/src/test/java/org/dspace/servicemanager/fakeservices/FakeService2.java index 5a9024b9a792..399029ad9b04 100644 --- a/dspace-services/src/test/java/org/dspace/servicemanager/fakeservices/FakeService2.java +++ b/dspace-services/src/test/java/org/dspace/servicemanager/fakeservices/FakeService2.java @@ -8,7 +8,8 @@ package org.dspace.servicemanager.fakeservices; import java.io.Serializable; -import javax.annotation.PostConstruct; + +import jakarta.annotation.PostConstruct; /** * Simple fake service 2 diff --git a/dspace-services/src/test/java/org/dspace/services/email/EmailServiceImplTest.java b/dspace-services/src/test/java/org/dspace/services/email/EmailServiceImplTest.java index 958e4f810641..97656af2f402 100644 --- a/dspace-services/src/test/java/org/dspace/services/email/EmailServiceImplTest.java +++ b/dspace-services/src/test/java/org/dspace/services/email/EmailServiceImplTest.java @@ -12,10 +12,9 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import javax.mail.MessagingException; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; - +import jakarta.mail.MessagingException; +import jakarta.mail.PasswordAuthentication; +import jakarta.mail.Session; import org.dspace.services.ConfigurationService; import org.dspace.services.EmailService; import org.dspace.test.DSpaceAbstractKernelTest; diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index 3ddf4d1a839c..c866774c4f60 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -45,11 +45,6 @@ - - org.dspace - dspace-api-lang - - org.springframework.boot @@ -68,18 +63,13 @@ jaxen - - - commons-fileupload - commons-fileupload - org.apache.httpcomponents httpclient - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided @@ -96,10 +86,10 @@ org.apache.logging.log4j log4j-core - + org.apache.logging.log4j log4j-web - + xom diff --git a/dspace-sword/src/main/java/org/purl/sword/base/Deposit.java b/dspace-sword/src/main/java/org/purl/sword/base/Deposit.java index 2473d28e4a00..b771ffc5afc4 100644 --- a/dspace-sword/src/main/java/org/purl/sword/base/Deposit.java +++ b/dspace-sword/src/main/java/org/purl/sword/base/Deposit.java @@ -10,8 +10,8 @@ import java.io.File; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.Logger; /** diff --git a/dspace-sword/src/main/java/org/purl/sword/base/HttpHeaders.java b/dspace-sword/src/main/java/org/purl/sword/base/HttpHeaders.java index 9a5aacc5a3bb..44233138c744 100644 --- a/dspace-sword/src/main/java/org/purl/sword/base/HttpHeaders.java +++ b/dspace-sword/src/main/java/org/purl/sword/base/HttpHeaders.java @@ -7,7 +7,7 @@ */ package org.purl.sword.base; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; /** * Definition of the additional HTTP Header tags that will be used in diff --git a/dspace-sword/src/main/java/org/purl/sword/client/ServletClient.java b/dspace-sword/src/main/java/org/purl/sword/client/ServletClient.java deleted file mode 100644 index 963e9637dd72..000000000000 --- a/dspace-sword/src/main/java/org/purl/sword/client/ServletClient.java +++ /dev/null @@ -1,455 +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) 2008, 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; -import java.io.IOException; -import java.net.URL; -import java.util.Iterator; -import java.util.List; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.purl.sword.base.DepositResponse; -import org.purl.sword.base.SWORDEntry; -import org.purl.sword.base.ServiceDocument; - -/** - * Example client that runs as a Servlet. - * - * @author Stuart Lewis - */ -public class ServletClient extends HttpServlet { - - /** - * The user agent name of this library - */ - public static final String userAgent = "SWORDAPP Java Client: SWORD version 1.3 compatible (http://sourceforge" + - ".net/projects/sword-app/)"; - - /** - * Temporary directory. - */ - private String tempDirectory; - - /** - * List of urls for the destination services to access. - */ - private String[] urls; - - /** - * Used to determine if a proxy value should be set. - */ - private boolean useProxy = false; - - /** - * The proxy host name. - */ - private String pHost; - - /** - * The proxy port name. - */ - private int pPort; - - /** Counter used during Deposit information. */ - private static int counter = 0; - - /** - * Initialise the servlet. - */ - public void init() { - tempDirectory = getServletContext().getInitParameter( - "upload-temp-directory"); - if ((tempDirectory == null) || (tempDirectory.equals(""))) { - tempDirectory = System.getProperty("java.io.tmpdir"); - } - String lots = getServletContext().getInitParameter("client-urls"); - urls = lots.split(","); - - pHost = getServletContext().getInitParameter("proxy-host"); - String pPortstr = getServletContext().getInitParameter("proxy-port"); - if (((pHost != null) && (!pHost.equals(""))) - && ((pPortstr != null) && (!pPortstr.equals("")))) { - try { - pPort = Integer.parseInt(pPortstr); - useProxy = true; - } catch (Exception e) { - // Port number not numeric - } - } - } - - /** - * Handle a get request. Simply show the default form (form.jsp) - * - * @param request The request details - * @param response The response to write to. - * - * @throws ServletException - * An exception that provides information on a database access error or other errors. - * @throws IOException - * A general class of exceptions produced by failed or interrupted I/O operations. - */ - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - // Get request, so show the default page - request.setAttribute("urls", urls); - request.getRequestDispatcher("form.jsp").forward(request, response); - } - - /** - * Process the post. Determine if the request is for a post or service - * document. Then, dispatch the request to the appropriate handler. - * - * @param request The request details. - * @param response The response to write to. - * - * @throws ServletException - * An exception that provides information on a database access error or other errors. - * @throws IOException - * A general class of exceptions produced by failed or interrupted I/O operations. - */ - - protected void doPost(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - if (request.getParameter("servicedocument") != null) { - this.doServiceDocument(request, response); - } else if (request.getParameter("deposit") != null) { - request.setAttribute("url", request.getParameter("url")); - request.setAttribute("u", request.getParameter("u")); - request.setAttribute("p", request.getParameter("p")); - request.setAttribute("obo", request.getParameter("obo")); - request.setAttribute("abstract", request.getParameter("abstract")); - request.setAttribute("policy", request.getParameter("policy")); - request.setAttribute("treatment", request.getParameter("treatment")); - request.setAttribute("mediation", request.getParameter("mediation")); - request.setAttribute("accepts", request.getParameter("accepts")); - request.setAttribute("acceptsp", request.getParameter("acceptsp")); - request.setAttribute("maxuploadsize", request.getParameter("maxuploadsize")); - request.getRequestDispatcher("depositform.jsp").forward(request, response); - } else if (ServletFileUpload.isMultipartContent(request)) { - this.doDeposit(request, response); - } else { - request.setAttribute("urls", urls); - request.getRequestDispatcher("form.jsp").forward(request, response); - } - } - - /** - * Process the request for a service document. - * - * @param request The request details. - * @param response The response to write to. - * - * @throws ServletException - * An exception that provides information on a database access error or other errors. - * @throws IOException - * A general class of exceptions produced by failed or interrupted I/O operations. - */ - - private void doServiceDocument(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - // Get the service document - Client client = new Client(); - // Which URL do we want? - URL url = new URL(request.getParameter("url")); - String theUrl = request.getParameter("url"); - - if ((request.getParameter("ownurl") != null) - && (!request.getParameter("ownurl").equals(""))) { - url = new URL(request.getParameter("ownurl")); - theUrl = request.getParameter("ownurl"); - } - - int port = url.getPort(); - if (port == -1) { - port = 80; - } - - // Set up the server - client.setServer(url.getHost(), port); - client.setCredentials(request.getParameter("u"), request.getParameter("p")); - if (useProxy) { - client.setProxy(pHost, pPort); - } - - try { - ServiceDocument sd = client.getServiceDocument(theUrl, - request.getParameter("obo")); - - // Set the status - Status status = client.getStatus(); - request.setAttribute("status", status.toString()); - if (status.getCode() == 200) { - // Set the debug response - String xml = sd.marshall(); - - String validateXml = xml; - validateXml = validateXml.replaceAll("&", "&"); - validateXml = validateXml.replaceAll("<", "<"); - validateXml = validateXml.replaceAll(">", ">"); - validateXml = validateXml.replaceAll("\"", """); - validateXml = validateXml.replaceAll("'", "'"); - request.setAttribute("xmlValidate", validateXml); // for passing to validation - - xml = xml.replaceAll("<", "<"); - xml = xml.replaceAll(">", ">"); - request.setAttribute("xml", xml); - - // Set the ServiceDocument and associated values - request.setAttribute("sd", sd); - request.setAttribute("sdURL", theUrl); - request.setAttribute("u", request.getParameter("u")); - request.setAttribute("p", request.getParameter("p")); - request.setAttribute("sdOBO", request.getParameter("obo")); - request.getRequestDispatcher("servicedocument.jsp").forward( - request, response); - return; - } else { - request.setAttribute("error", status.getCode() + " " - + status.getMessage()); - request.setAttribute("urls", urls); - request.getRequestDispatcher("form.jsp").forward(request, - response); - return; - } - } catch (SWORDClientException e) { - e.printStackTrace(); - request.setAttribute("error", e.toString()); - request.setAttribute("urls", urls); - request.getRequestDispatcher("form.jsp").forward(request, response); - } - } - - /** - * Process a deposit. - * - * @param request The request details. - * @param response The response to output to. - * - * @throws ServletException - * An exception that provides information on a database access error or other errors. - * @throws IOException - * A general class of exceptions produced by failed or interrupted I/O operations. - */ - private void doDeposit(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - // Do the deposit - Client client = new Client(); - try { - PostMessage message = new PostMessage(); - message.setUserAgent(ClientConstants.SERVICE_NAME); - - // Get the file - FileItemFactory factory = new DiskFileItemFactory(); - - // Create a new file upload handler - ServletFileUpload upload = new ServletFileUpload(factory); - - // Parse the request - List items = upload.parseRequest(request); - Iterator iter = items.iterator(); - String u = null; - String p = null; - String contentDisposition = null; - String filetype = null; - boolean useMD5 = false; - boolean errorMD5 = false; - boolean verbose = false; - boolean noOp = false; - boolean login = false; - while (iter.hasNext()) { - FileItem item = iter.next(); - if (item.isFormField()) { - String name = item.getFieldName(); - String value = item.getString(); - if (name.equals("url")) { - message.setDestination(value); - URL url = new URL(value); - int port = url.getPort(); - if (port == -1) { - port = 80; - } - client.setServer(url.getHost(), port); - } else if (name.equals("usemd5")) { - useMD5 = true; - } else if (name.equals("errormd5")) { - errorMD5 = true; - } else if (name.equals("verbose")) { - verbose = true; - } else if (name.equals("noop")) { - noOp = true; - } else if (name.equals("obo")) { - message.setOnBehalfOf(value); - } else if (name.equals("slug")) { - if ((value != null) && (!value.trim().equals(""))) { - message.setSlug(value); - } - } else if (name.equals("cd")) { - contentDisposition = value; - } else if (name.equals("filetype")) { - filetype = value; - } else if (name.equals("formatnamespace")) { - if ((value != null) && (!value.trim().equals(""))) { - message.setFormatNamespace(value); - } - } else if (name.equals("u")) { - u = value; - login = true; - request.setAttribute("u", value); - } else if (name.equals("p")) { - p = value; - login = true; - } - request.setAttribute(name, value); - } else { - String fname = tempDirectory + File.separator + - "ServletClient-" + counter++; - if ((contentDisposition != null) && (!contentDisposition.equals(""))) { - fname = tempDirectory + File.separator + contentDisposition; - } - - File uploadedFile = new File(fname); - item.write(uploadedFile); - message.setFilepath(fname); - - if ((filetype == null) || (filetype.trim().equals(""))) { - message.setFiletype(item.getContentType()); - } else { - message.setFiletype(filetype); - } - } - } - - if (login) { - client.setCredentials(u, p); - } - - if (useProxy) { - client.setProxy(pHost, pPort); - } - - message.setUseMD5(useMD5); - message.setChecksumError(errorMD5); - message.setVerbose(verbose); - message.setNoOp(noOp); - - // Post the file - DepositResponse resp = client.postFile(message); - - // Set the status - Status status = client.getStatus(); - request.setAttribute("status", status.toString()); - if ((status.getCode() == 201) || (status.getCode() == 202)) { - // Set the debug response - String xml = resp.marshall(); - - String validateXml = xml; - validateXml = validateXml.replaceAll("&", "&"); - validateXml = validateXml.replaceAll("<", "<"); - validateXml = validateXml.replaceAll(">", ">"); - validateXml = validateXml.replaceAll("\"", """); - validateXml = validateXml.replaceAll("'", "'"); - request.setAttribute("xmlValidate", validateXml); // for passing to validation - - xml = xml.replaceAll("<", "<"); - xml = xml.replaceAll(">", ">"); - request.setAttribute("xml", xml); - SWORDEntry se = resp.getEntry(); - request.setAttribute("id", se.getId()); - request.setAttribute("authors", se.getAuthors()); - request.setAttribute("contributors", se.getContributors()); - request.setAttribute("title", se.getTitle().getContent()); - request.setAttribute("updated", se.getUpdated()); - request.setAttribute("categories", se.getCategories()); - request.setAttribute("treatment", se.getTreatment()); - request.setAttribute("summary", se.getSummary().getContent()); - request.setAttribute("generator", se.getGenerator().getContent()); - request.setAttribute("userAgent", se.getUserAgent()); - request.setAttribute("packaging", se.getPackaging()); - request.setAttribute("links", se.getLinks()); - request.setAttribute("location", resp.getLocation()); - - // Set the ServiceDocument and associated values - request.getRequestDispatcher("deposit.jsp").forward(request, response); - return; - } else { - String error = status.getCode() + " " + status.getMessage() + " - "; - try { - error += resp.getEntry().getSummary().getContent(); - } catch (Exception e) { - // Do nothing - we have default error message - e.printStackTrace(); - } - request.setAttribute("error", error); - - // Try and get an error document in xml - String xml = resp.marshall(); - xml = xml.replaceAll("<", "<"); - xml = xml.replaceAll(">", ">"); - request.setAttribute("xml", xml); - - request.getRequestDispatcher("depositform.jsp").forward(request, response); - return; - } - } catch (RuntimeException e) { - e.printStackTrace(); - request.setAttribute("error", "value: " + e.toString()); - request.setAttribute("urls", urls); - request.getRequestDispatcher("depositform.jsp").forward(request, response); - } catch (Exception e) { - e.printStackTrace(); - request.setAttribute("error", "value: " + e.toString()); - request.setAttribute("urls", urls); - request.getRequestDispatcher("depositform.jsp").forward(request, response); - } - } -} diff --git a/dspace-sword/src/main/java/org/purl/sword/server/AtomDocumentServlet.java b/dspace-sword/src/main/java/org/purl/sword/server/AtomDocumentServlet.java index 0b2a675efd4e..0c7cb3aab19a 100644 --- a/dspace-sword/src/main/java/org/purl/sword/server/AtomDocumentServlet.java +++ b/dspace-sword/src/main/java/org/purl/sword/server/AtomDocumentServlet.java @@ -9,10 +9,10 @@ import java.io.IOException; import java.io.PrintWriter; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.purl.sword.base.AtomDocumentRequest; import org.purl.sword.base.AtomDocumentResponse; import org.purl.sword.base.SWORDAuthenticationException; diff --git a/dspace-sword/src/main/java/org/purl/sword/server/DepositServlet.java b/dspace-sword/src/main/java/org/purl/sword/server/DepositServlet.java index d7c01a3f0489..ce63615edae8 100644 --- a/dspace-sword/src/main/java/org/purl/sword/server/DepositServlet.java +++ b/dspace-sword/src/main/java/org/purl/sword/server/DepositServlet.java @@ -19,11 +19,11 @@ import java.util.Date; import java.util.StringTokenizer; import java.util.concurrent.atomic.AtomicInteger; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Base64; import org.apache.logging.log4j.Logger; import org.purl.sword.atom.Summary; @@ -159,7 +159,7 @@ public void init() throws ServletException { * * @param request the request. * @param response the response. - * @throws javax.servlet.ServletException passed through. + * @throws jakarta.servlet.ServletException passed through. * @throws java.io.IOException passed through. */ @Override @@ -174,7 +174,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) * * @param request the request. * @param response the response. - * @throws javax.servlet.ServletException passed through. + * @throws jakarta.servlet.ServletException passed through. * @throws java.io.IOException passed through. */ @Override diff --git a/dspace-sword/src/main/java/org/purl/sword/server/DummyServer.java b/dspace-sword/src/main/java/org/purl/sword/server/DummyServer.java index 2dc9b3b7e214..96551af2d2ba 100644 --- a/dspace-sword/src/main/java/org/purl/sword/server/DummyServer.java +++ b/dspace-sword/src/main/java/org/purl/sword/server/DummyServer.java @@ -15,8 +15,8 @@ import java.util.TimeZone; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.Logger; import org.purl.sword.atom.Author; import org.purl.sword.atom.Content; diff --git a/dspace-sword/src/main/java/org/purl/sword/server/ServiceDocumentServlet.java b/dspace-sword/src/main/java/org/purl/sword/server/ServiceDocumentServlet.java index 494cbc9db41c..842726a9511a 100644 --- a/dspace-sword/src/main/java/org/purl/sword/server/ServiceDocumentServlet.java +++ b/dspace-sword/src/main/java/org/purl/sword/server/ServiceDocumentServlet.java @@ -10,11 +10,11 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.StringTokenizer; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Base64; import org.apache.logging.log4j.Logger; import org.purl.sword.base.HttpHeaders; @@ -107,7 +107,7 @@ public void init() throws ServletException { * * @param request the request. * @param response the response. - * @throws javax.servlet.ServletException passed through. + * @throws jakarta.servlet.ServletException passed through. * @throws java.io.IOException passed through. */ @Override @@ -174,7 +174,7 @@ protected void doGet(HttpServletRequest request, * * @param request the request. * @param response the response. - * @throws javax.servlet.ServletException passed through. + * @throws jakarta.servlet.ServletException passed through. * @throws java.io.IOException passed through. */ @Override diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 740351d5db69..1e799449898d 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -24,42 +24,26 @@ - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided - org.swordapp + io.gdcc sword2-server - 1.0 - jar - classes + 2.0.0 - - - org.apache.abdera - abdera-client - - - javax.servlet - servlet-api - - - - log4j - log4j - + - org.slf4j - slf4j-log4j12 + org.codehaus.woodstox + woodstox-core-asl - + - com.hp.hpl.jena - jena + org.glassfish.jersey.core + jersey-common @@ -96,29 +80,6 @@ org.apache.logging.log4j log4j-web - - - - org.apache.ws.commons.axiom - fom-impl - - 1.2.22 - - - - org.apache.geronimo.specs - * - - - - org.codehaus.woodstox - woodstox-core-asl - - - diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/GenericStatementDisseminator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/GenericStatementDisseminator.java index f06deb61fd85..98bd2095726b 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/GenericStatementDisseminator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/GenericStatementDisseminator.java @@ -17,7 +17,11 @@ import org.apache.commons.lang3.ArrayUtils; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; +import org.dspace.content.DCDate; import org.dspace.content.Item; +import org.dspace.content.MetadataValue; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.ItemService; import org.dspace.core.Context; import org.dspace.services.factory.DSpaceServicesFactory; import org.swordapp.server.OriginalDeposit; @@ -28,6 +32,9 @@ public abstract class GenericStatementDisseminator implements SwordStatementDisseminator { protected SwordUrlManager urlManager; + protected ItemService itemService = ContentServiceFactory.getInstance() + .getItemService(); + protected void populateStatement(Context context, Item item, Statement statement) throws DSpaceSwordException { @@ -78,6 +85,7 @@ protected List getOriginalDeposits(Context context, bitstream)); deposit.setMediaType(bitstream .getFormat(context).getMIMEType()); + deposit.setDepositedOn(this.getDateOfDeposit(item)); originalDeposits.add(deposit); } } @@ -173,4 +181,14 @@ private String getOriginalDepositsBundle() { } return swordBundle; } + + private Date getDateOfDeposit(Item item) { + List values = itemService.getMetadata(item, "dc", "date", "accessioned", Item.ANY); + Date date = new Date(); + if (values != null && values.size() > 0) { + String strDate = values.get(0).getValue(); + date = new DCDate(strDate).toDate(); + } + return date; + } } diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/ReceiptGenerator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/ReceiptGenerator.java index b4526985145a..725ae5e73492 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/ReceiptGenerator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/ReceiptGenerator.java @@ -8,8 +8,6 @@ package org.dspace.sword2; import java.sql.SQLException; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -28,6 +26,7 @@ import org.dspace.core.Context; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.util.MultiFormatDateParser; import org.swordapp.server.DepositReceipt; import org.swordapp.server.SwordError; import org.swordapp.server.SwordServerException; @@ -284,14 +283,8 @@ protected void addPublishDate(DepositResult result, DepositReceipt receipt) { List dcv = itemService.getMetadataByMetadataString( result.getItem(), "dc.date.issued"); if (dcv != null && !dcv.isEmpty()) { - try { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - Date published = sdf.parse(dcv.get(0).getValue()); - receipt.getWrappedEntry().setPublished(published); - } catch (ParseException e) { - // we tried, but never mind - log.warn("Couldn't add published date", e); - } + Date published = MultiFormatDateParser.parse(dcv.get(0).getValue()); + receipt.getWrappedEntry().setPublished(published); } } @@ -305,14 +298,8 @@ protected void addPublishDate(Item item, DepositReceipt receipt) { List dcv = itemService.getMetadataByMetadataString( item, "dc.date.issued"); if (dcv != null && dcv.size() == 1) { - try { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - Date published = sdf.parse(dcv.get(0).getValue()); - receipt.getWrappedEntry().setPublished(published); - } catch (ParseException e) { - // we tried, but never mind - log.warn("Couldn't add published date", e); - } + Date published = MultiFormatDateParser.parse(dcv.get(0).getValue()); + receipt.getWrappedEntry().setPublished(published); } } @@ -329,14 +316,8 @@ protected void addLastUpdatedDate(DepositResult result, List dcv = itemService.getMetadataByMetadataString( result.getItem(), config); if (dcv != null && dcv.size() == 1) { - try { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - Date updated = sdf.parse(dcv.get(0).getValue()); - receipt.getWrappedEntry().setUpdated(updated); - } catch (ParseException e) { - // we tried, but never mind - log.warn("Couldn't add last updated date", e); - } + Date updated = MultiFormatDateParser.parse(dcv.get(0).getValue()); + receipt.getWrappedEntry().setUpdated(updated); } } @@ -352,14 +333,8 @@ protected void addLastUpdatedDate(Item item, DepositReceipt receipt) { List dcv = itemService.getMetadataByMetadataString( item, config); if (dcv != null && dcv.size() == 1) { - try { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - Date updated = sdf.parse(dcv.get(0).getValue()); - receipt.getWrappedEntry().setUpdated(updated); - } catch (ParseException e) { - // we tried, but never mind - log.warn("Couldn't add last updated date", e); - } + Date updated = MultiFormatDateParser.parse(dcv.get(0).getValue()); + receipt.getWrappedEntry().setUpdated(updated); } } } diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index e860d59d1127..08b0f431fea1 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -788,7 +788,7 @@ event.dispatcher.noindex.consumers = eperson # consumer to maintain the discovery index event.consumer.discovery.class = org.dspace.discovery.IndexEventConsumer -event.consumer.discovery.filters = Community|Collection|Item|Bundle|Site+Add|Create|Modify|Modify_Metadata|Delete|Remove +event.consumer.discovery.filters = Community|Collection|Item|Bundle|Site|LDN_MESSAGE+Add|Create|Modify|Modify_Metadata|Delete|Remove # consumer related to EPerson changes event.consumer.eperson.class = org.dspace.eperson.EPersonConsumer @@ -1647,6 +1647,7 @@ include = ${module_dir}/clamav.cfg include = ${module_dir}/curate.cfg include = ${module_dir}/discovery.cfg include = ${module_dir}/doi-curation.cfg +include = ${module_dir}/duplicate-detection.cfg include = ${module_dir}/google-analytics.cfg include = ${module_dir}/healthcheck.cfg include = ${module_dir}/identifiers.cfg diff --git a/dspace/config/hibernate.cfg.xml b/dspace/config/hibernate.cfg.xml index 6cc1020c47bf..9d1ee9dac067 100644 --- a/dspace/config/hibernate.cfg.xml +++ b/dspace/config/hibernate.cfg.xml @@ -31,7 +31,7 @@ - ENABLE_SELECTIVE + ENABLE_SELECTIVE diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index a2c6c623d45e..05921ec4ca49 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -290,6 +290,13 @@ coarnotify + + + submit.progressbar.duplicates + org.dspace.app.rest.submit.step.DuplicateDetectionStep + duplicates + + @@ -383,6 +390,11 @@ + + + diff --git a/dspace/config/modules/duplicate-detection.cfg b/dspace/config/modules/duplicate-detection.cfg new file mode 100644 index 000000000000..665790384e07 --- /dev/null +++ b/dspace/config/modules/duplicate-detection.cfg @@ -0,0 +1,35 @@ +### +# Duplicate detection settings +## + +# Enable this feature. Default: false +#duplicate.enable = true + +## +# Normalisation rules. If these are changed, a full index-discovery re-index should be performed to force +# stored comparison values to be updated. +## +# Should the comparison query/index value be normalised for case? Default: true +duplicate.comparison.normalise.lowercase = true +# Should the comparison query/index value be normalised for whitespace? Default: true +# (highly recommended - if this is *not* used, some other placeholder needs to be used to force the value +# to be treated as a single term by Lucene) +duplicate.comparison.normalise.whitespace = true + +# Levenshtein edit distance. Default:0 (eg. Test will match Txst but not Txxt) +# Valid distances are 0, 1, 2 as per Solr documentation. Note that this distance is applied *after* normalisation +# rules above, so capitalisation and whitespace will not count as 'edits' if you have the above rules enabled. +duplicate.comparison.distance = 0 +# DSpace metadata field(s) to use. They will be concatenated before normalisation. +# Repeat the configuration property for multiple fields. +duplicate.comparison.metadata.field = dc.title +#duplicate.comparison.metadata.field = dc.contributor.author + +# Solr field used for storing the indexed comparison string +duplicate.comparison.solr.field = deduplication_keyword + +## Metadata to populate in the potential duplicate +duplicate.preview.metadata.field = dc.title +duplicate.preview.metadata.field = dc.date.issued +duplicate.preview.metadata.field = dc.type +duplicate.preview.metadata.field = dspace.entity.type \ No newline at end of file diff --git a/dspace/config/modules/rdf/fuseki-assembler.ttl b/dspace/config/modules/rdf/fuseki-assembler.ttl index 0b6340351cb5..7f577aebc108 100644 --- a/dspace/config/modules/rdf/fuseki-assembler.ttl +++ b/dspace/config/modules/rdf/fuseki-assembler.ttl @@ -29,7 +29,7 @@ ### Assembler initialization ### ################################ # Declaration additional assembler items. -[] ja:loadClass "com.hp.hpl.jena.tdb.TDB" . +[] ja:loadClass "org.apache.jena.tdb.TDB" . # TDB tdb:DatasetTDB rdfs:subClassOf ja:RDFDataset . diff --git a/dspace/config/modules/rest.cfg b/dspace/config/modules/rest.cfg index ef4f985f0d78..3bb620510e59 100644 --- a/dspace/config/modules/rest.cfg +++ b/dspace/config/modules/rest.cfg @@ -58,3 +58,4 @@ rest.properties.exposed = ldn.enabled rest.properties.exposed = ldn.notify.inbox rest.properties.exposed = handle.canonical.prefix rest.properties.exposed = contentreport.enable +rest.properties.exposed = duplicate.enable diff --git a/dspace/config/spring/api/core-hibernate.xml b/dspace/config/spring/api/core-hibernate.xml index 45f7d15dc51d..6c54fca46e9d 100644 --- a/dspace/config/spring/api/core-hibernate.xml +++ b/dspace/config/spring/api/core-hibernate.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true"> - + diff --git a/dspace/config/spring/api/core-services.xml b/dspace/config/spring/api/core-services.xml index 20b5bc74736d..29acb01e27e6 100644 --- a/dspace/config/spring/api/core-services.xml +++ b/dspace/config/spring/api/core-services.xml @@ -55,6 +55,7 @@ + @@ -144,6 +145,7 @@ + diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 711880fa51ac..92d72a521307 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -44,6 +44,9 @@ + + + @@ -126,6 +129,22 @@ + + + + + + + + + + + + + + + + @@ -1051,6 +1070,7 @@ + @@ -1060,6 +1080,9 @@ + + + @@ -1082,6 +1105,9 @@ + + + @@ -2586,6 +2612,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:LDNMessageEntity + + + + + + @@ -2597,6 +2678,150 @@ + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_INCOMING} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_INCOMING} + in_reply_to:* + activity_stream_type_keyword:Accept + queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_PROCESSED} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_INCOMING} + queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_PROCESSED} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_INCOMING} + queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_FAILED} OR queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_UNMAPPED_ACTION} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_INCOMING} + queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_UNTRUSTED} + + + + + + + + + + search.resourcetype:Item + {!join from=relateditem_authority to=search.resourceid fromIndex=${solr.multicorePrefix}search}notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_INCOMING} + -withdrawn:true AND -discoverable:false + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_OUTGOING} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_OUTGOING} + queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_PROCESSED} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_OUTGOING} + queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_QUEUED} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_OUTGOING} + queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_QUEUED_FOR_RETRY} + + + + + + + + + + search.resourcetype:LDNMessageEntity + notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_OUTGOING} + queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_FAILED} OR queue_status_authority:#{T(org.dspace.app.ldn.LDNMessageEntity).QUEUE_STATUS_UNMAPPED_ACTION} + + + + + + + + + + search.resourcetype:Item + {!join from=relateditem_authority to=search.resourceid fromIndex=${solr.multicorePrefix}search}notification_type_keyword:#{T(org.dspace.app.ldn.LDNMessageEntity).TYPE_OUTGOING} + -withdrawn:true AND -discoverable:false + + + @@ -3321,6 +3546,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + datacite.relation.isReferencedBy + datacite.relation.isSupplementedBy + + + + + + + + + + + + + + notify.relation.endorsedBy + + + + + + + + + + + + + + datacite.relation.isReviewedBy + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3401,6 +3797,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace/config/spring/api/orcid-services.xml b/dspace/config/spring/api/orcid-services.xml index e5fb002c314f..8286a16a88fb 100644 --- a/dspace/config/spring/api/orcid-services.xml +++ b/dspace/config/spring/api/orcid-services.xml @@ -38,17 +38,17 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/dspace/config/spring/api/subscriptions_email_configuration.xml b/dspace/config/spring/api/subscriptions_email_configuration.xml index 2d52dfc27089..0eaf2d97d90c 100644 --- a/dspace/config/spring/api/subscriptions_email_configuration.xml +++ b/dspace/config/spring/api/subscriptions_email_configuration.xml @@ -17,15 +17,6 @@ http://www.springframework.org/schema/util/spring-util.xsd"> - - - - - - @@ -33,6 +24,15 @@ + + + + + + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 68927fef414e..bcc35e517384 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -190,7 +190,9 @@ codirecteurs ou codirectrices. Ne pas saisir le nom des autres membres du jury. + Veuillez inscrire le nom de votre directeur ou de votre directrice de recherche. + @@ -455,7 +457,9 @@ S'il s'agit d'une version publiée, un identifiant unique tel l'ISBN du livre et la pagination du chapitre suffisent.
Pour toute autre version, entrez le titre du livre, l'édition (si applicable), la pagination du chapitre (si connue), et indiquez la date de cette version. + Vous devez inscrire la référence du chapitre de livre. + @@ -1414,7 +1418,9 @@ Entrez le nom et prénom complet du(des) auteur(s) tels qu'ils figurent sur la page de titre du travail.
Utilisez le bouton « Ajouter » pour saisir les coauteurs. + Vous devez inscrire nom et prénom des auteurs. + diff --git a/dspace/modules/additions/pom.xml b/dspace/modules/additions/pom.xml index 54d4dea25cde..8a98a72430fe 100644 --- a/dspace/modules/additions/pom.xml +++ b/dspace/modules/additions/pom.xml @@ -109,7 +109,7 @@ - ${agnostic.build.dir}/testing/dspace/ + ${agnostic.build.dir}/testing/dspace true ${agnostic.build.dir}/testing/dspace/solr/ @@ -177,7 +177,7 @@ - ${agnostic.build.dir}/testing/dspace/ + ${agnostic.build.dir}/testing/dspace true ${agnostic.build.dir}/testing/dspace/solr/ @@ -223,8 +223,8 @@ dspace-services - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided @@ -250,6 +250,13 @@ solr-core ${solr.client.version} test + + + + org.antlr + antlr4-runtime + + org.apache.lucene diff --git a/dspace/modules/server/pom.xml b/dspace/modules/server/pom.xml index 557b5f080972..76e53f309232 100644 --- a/dspace/modules/server/pom.xml +++ b/dspace/modules/server/pom.xml @@ -170,7 +170,7 @@ - ${agnostic.build.dir}/testing/dspace/ + ${agnostic.build.dir}/testing/dspace true ${agnostic.build.dir}/testing/dspace/solr/ @@ -239,7 +239,7 @@ - ${agnostic.build.dir}/testing/dspace/ + ${agnostic.build.dir}/testing/dspace true ${agnostic.build.dir}/testing/dspace/solr/ @@ -335,6 +335,13 @@ solr-core ${solr.client.version} test + + + + org.antlr + antlr4-runtime + + org.apache.lucene diff --git a/dspace/pom.xml b/dspace/pom.xml index 6beb4a63c0f3..3247fd30d41a 100644 --- a/dspace/pom.xml +++ b/dspace/pom.xml @@ -248,8 +248,8 @@ - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api diff --git a/dspace/src/main/docker/test/rest_web.xml b/dspace/src/main/docker/test/rest_web.xml deleted file mode 100644 index 05a626869265..000000000000 --- a/dspace/src/main/docker/test/rest_web.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - dspace.request - org.dspace.utils.servlet.DSpaceWebappServletFilter - - - - dspace.request - /* - - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - - springSecurityFilterChain - /* - - - - - DSpace REST API - - org.glassfish.jersey.servlet.ServletContainer - - - javax.ws.rs.Application - org.dspace.rest.DSpaceRestApplication - - 1 - - - - DSpace REST API - /* - - - - default - /static/* - - - - - - - - - The location of the DSpace home directory - - dspace.dir - ${dspace.dir} - - - - contextConfigLocation - - /WEB-INF/applicationContext.xml, - /WEB-INF/security-applicationContext.xml - - - - - org.dspace.app.util.DSpaceContextListener - - - - - org.dspace.servicemanager.servlet.DSpaceKernelServletContextListener - - - - - org.springframework.web.context.ContextLoaderListener - - - - - org.dspace.app.util.DSpaceWebappListener - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8c8fc8d98e46..8c398011d0d0 100644 --- a/pom.xml +++ b/pom.xml @@ -18,47 +18,47 @@ - 11 - 5.3.32 - 2.7.18 - 5.7.11 - 5.6.15.Final - 6.2.5.Final - 42.7.2 - 8.11.2 + 17 + 6.1.5 + 3.2.4 + 6.2.3 + 6.4.4.Final + 8.0.1.Final + 42.7.3 + 10.10.0 + 8.11.3 3.10.8 2.10.0 2.16.0 2.16.0 - 1.3.2 - 2.3.1 - 2.3.9 + 2.1.1 + 4.0.0 + 4.0.1 1.1.1 9.4.54.v20240208 - 2.22.1 - 2.0.30 + 2.23.1 + 2.0.31 1.19.0 - 1.7.36 - 2.5.0 - - 1.70 - + 2.0.11 + 2.9.1 + + 1.76 + 8.0.1 + + 3.1.5 2.9.0 - 7.9 + 9.37.3 - - 2.13.0 - - 2.39.1 + + 4.9.0 UTF-8 @@ -89,7 +89,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M3 + 3.4.1 enforce-java @@ -140,9 +140,9 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.13.0 - 11 + ${java.version} true @@ -159,6 +159,9 @@ -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -Xpkginfo:always + + -parameters @@ -173,7 +176,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + 3.3.0 @@ -187,7 +190,7 @@ org.apache.maven.plugins maven-war-plugin - 3.2.3 + 3.4.0 false @@ -204,7 +207,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.22.2 + 3.2.5 @@ -219,6 +222,9 @@ false ${skipUnitTests} + + false maven-failsafe-plugin - 2.22.2 + 3.2.5 @@ -242,6 +248,9 @@ false ${skipIntegrationTests} + + false @@ -319,7 +328,7 @@ maven-clean-plugin - 3.1.0 + 3.3.2 @@ -333,17 +342,17 @@ maven-assembly-plugin - 3.6.0 + 3.7.1 org.apache.maven.plugins maven-dependency-plugin - 3.1.2 + 3.6.1 org.apache.maven.plugins maven-resources-plugin - 3.1.0 + 3.3.1 @@ -355,13 +364,13 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.13 org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.6.3 false @@ -376,7 +385,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 @@ -389,13 +398,13 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.2.1 org.jacoco jacoco-maven-plugin - 0.8.5 + 0.8.11 @@ -407,7 +416,7 @@ org.apache.maven.plugins maven-release-plugin - 2.5.3 + 3.0.0 @@ -1073,19 +1082,26 @@ - org.hibernate + org.hibernate.orm hibernate-core ${hibernate.version} - org.hibernate + org.hibernate.orm hibernate-jpamodelgen ${hibernate.version} + + + + org.antlr + antlr4-runtime + + - org.hibernate + org.hibernate.orm hibernate-jcache ${hibernate.version} @@ -1097,7 +1113,7 @@ - org.hibernate + org.hibernate.validator hibernate-validator ${hibernate-validator.version} @@ -1257,13 +1273,13 @@ org.bouncycastle - bcpkix-jdk15on + bcpkix-jdk18on ${bouncycastle.version} org.bouncycastle - bcprov-jdk15on + bcprov-jdk18on ${bouncycastle.version} @@ -1276,7 +1292,37 @@ org.ow2.asm asm - 8.0.1 + ${asm.version} + + + org.ow2.asm + asm-analysis + ${asm.version} + + + org.ow2.asm + asm-commons + ${asm.version} + + + org.ow2.asm + asm-tree + ${asm.version} + + + + + org.checkerframework + checker-qual + 3.31.0 + + + + + com.google.code.gson + gson + 2.10.1 - - org.apache.commons - commons-csv - - net.handle handle 9.3.1 - - - - com.google.code.gson - gson - - - + net.cnri cnri-servlet-container - 3.0.0 + 3.1.0 + runtime - + org.eclipse.jetty jetty-server ${jetty.version} + runtime - - org.eclipse.jetty - jetty-alpn-java-server - ${jetty.version} - + org.eclipse.jetty jetty-deploy ${jetty.version} + runtime org.eclipse.jetty jetty-http ${jetty.version} + runtime org.eclipse.jetty jetty-io ${jetty.version} + runtime org.eclipse.jetty jetty-servlet ${jetty.version} - - - org.eclipse.jetty - jetty-servlets - ${jetty.version} + runtime org.eclipse.jetty jetty-util ${jetty.version} + runtime org.eclipse.jetty jetty-webapp ${jetty.version} - - - org.eclipse.jetty - jetty-xml - ${jetty.version} + runtime org.eclipse.jetty.http2 http2-common ${jetty.version} - - - org.eclipse.jetty.http2 - http2-server - ${jetty.version} + runtime @@ -1448,11 +1466,13 @@ org.apache.commons commons-dbcp2 2.11.0 - - - commons-fileupload - commons-fileupload - 1.5 + + + + jakarta.transaction + jakarta.transaction-api + + commons-io @@ -1464,13 +1484,23 @@ commons-lang3 3.14.0 - + commons-logging commons-logging 1.3.0 + + org.apache.commons + commons-compress + 1.26.0 + + + org.apache.commons + commons-csv + 1.10.0 + org.apache.commons commons-pool2 @@ -1493,13 +1523,18 @@ com.sun.mail - javax.mail - 1.6.2 + jakarta.mail + 2.0.1 - javax.servlet - javax.servlet-api - 3.1.0 + jakarta.servlet + jakarta.servlet-api + 6.0.0 + + + jakarta.el + jakarta.el-api + 5.0.1 @@ -1627,6 +1662,12 @@ ${errorprone.version} compile + + com.google.errorprone + error_prone_annotations + ${errorprone.version} + compile + org.hamcrest @@ -1731,6 +1772,11 @@ jackson-databind ${jackson-databind.version} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-databind.version} + com.google.guava guava @@ -1765,8 +1811,8 @@ - javax.xml.bind - jaxb-api + jakarta.xml.bind + jakarta.xml.bind-api ${jaxb-api.version} @@ -1776,9 +1822,9 @@ runtime - javax.annotation - javax.annotation-api - ${javax-annotation.version} + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation.version} @@ -1909,8 +1955,11 @@ - maven-central + central https://repo.maven.apache.org/maven2 + + false + @@ -1928,6 +1977,18 @@ handle.net https://handle.net/maven + + false + + + + + oicr.on.ca + https://artifacts.oicr.on.ca/artifactory/collab-release/ + + false +