diff --git a/.github/workflows/codescan.yml b/.github/workflows/codescan.yml
index 3a563c6fa39c..cbdb4b880cbb 100644
--- a/.github/workflows/codescan.yml
+++ b/.github/workflows/codescan.yml
@@ -47,7 +47,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
# https://github.com/github/codeql-action
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
# Codescan Javascript as well since a few JS files exist in REST API's interface
languages: java, javascript
@@ -56,8 +56,8 @@ jobs:
# NOTE: Based on testing, this autobuild process works well for DSpace. A custom
# DSpace build w/caching (like in build.yml) was about the same speed as autobuild.
- name: Autobuild
- uses: github/codeql-action/autobuild@v2
+ uses: github/codeql-action/autobuild@v3
# Perform GitHub Code Scanning.
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 9d32cb119d41..aea0bb6478ff 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -220,6 +220,19 @@ jobs:
result=$(wget -O- -q http://127.0.0.1:8080/server/api/core/collections)
echo "$result"
echo "$result" | grep -oE "\"Dog in Yard\","
+ # Verify basic backend logging is working.
+ # 1. Access the top communities list. Verify that the "Before request" INFO statement is logged
+ # 2. Access an invalid endpoint (and ignore 404 response). Verify that a "status:404" WARN statement is logged
+ - name: Verify backend is logging properly
+ run: |
+ wget -O/dev/null -q http://127.0.0.1:8080/server/api/core/communities/search/top
+ logs=$(docker compose -f docker-compose.yml logs -n 5 dspace)
+ echo "$logs"
+ echo "$logs" | grep -o "Before request \[GET /server/api/core/communities/search/top\]"
+ wget -O/dev/null -q http://127.0.0.1:8080/server/api/does/not/exist || true
+ logs=$(docker compose -f docker-compose.yml logs -n 5 dspace)
+ echo "$logs"
+ echo "$logs" | grep -o "status:404 exception: The repository type does.not was not found"
# Verify Handle Server can be stared and is working properly
# 1. First generate the "[dspace]/handle-server" folder with the sitebndl.zip
# 2. Start the Handle Server (and wait 20 seconds to let it start up)
diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml
index 0c3261da95da..5e011c4668ed 100644
--- a/.github/workflows/reusable-docker-build.yml
+++ b/.github/workflows/reusable-docker-build.yml
@@ -164,7 +164,7 @@ jobs:
# Use GitHub cache to load cached Docker images and cache the results of this build
# This decreases the number of images we need to fetch from DockerHub
cache-from: type=gha,scope=${{ inputs.build_id }}
- cache-to: type=gha,scope=${{ inputs.build_id }},mode=max
+ cache-to: type=gha,scope=${{ inputs.build_id }},mode=min
# Export the digest of Docker build locally
- name: Export Docker build digest
@@ -216,7 +216,7 @@ jobs:
# Use GitHub cache to load cached Docker images and cache the results of this build
# This decreases the number of images we need to fetch from DockerHub
cache-from: type=gha,scope=${{ inputs.build_id }}
- cache-to: type=gha,scope=${{ inputs.build_id }},mode=max
+ cache-to: type=gha,scope=${{ inputs.build_id }},mode=min
# Export image to a local TAR file
outputs: type=docker,dest=/tmp/${{ inputs.build_id }}.tar
@@ -298,9 +298,12 @@ jobs:
# 'regctl' is used to more easily copy the image to DockerHub and obtain the digest from DockerHub
# See https://github.com/regclient/regclient/blob/main/docs/regctl.md
- name: Install regctl for Docker registry tools
- uses: regclient/actions/regctl-installer@main
- with:
- release: 'v0.8.0'
+ run: |
+ export REGCTL_VERSION=v0.9.2
+ mkdir -p bin
+ curl -sSLo bin/regctl https://github.com/regclient/regclient/releases/download/${REGCTL_VERSION}/regctl-linux-amd64
+ chmod a+x bin/regctl
+ echo "$(pwd)/bin" >> $GITHUB_PATH
# This recreates Docker tags for DockerHub
- name: Add Docker metadata for image
diff --git a/LICENSES_THIRD_PARTY b/LICENSES_THIRD_PARTY
index 5d99bd7e426c..d6b30f3fd1f8 100644
--- a/LICENSES_THIRD_PARTY
+++ b/LICENSES_THIRD_PARTY
@@ -21,35 +21,34 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
Apache Software License, Version 2.0:
* Ant-Contrib Tasks (ant-contrib:ant-contrib:1.0b3 - http://ant-contrib.sourceforge.net)
- * AWS SDK for Java - Core (com.amazonaws:aws-java-sdk-core:1.12.785 - https://aws.amazon.com/sdkforjava)
- * AWS Java SDK for AWS KMS (com.amazonaws:aws-java-sdk-kms:1.12.785 - https://aws.amazon.com/sdkforjava)
- * AWS Java SDK for Amazon S3 (com.amazonaws:aws-java-sdk-s3:1.12.785 - https://aws.amazon.com/sdkforjava)
- * JMES Path Query library (com.amazonaws:jmespath-java:1.12.785 - https://aws.amazon.com/sdkforjava)
+ * S3Mock - Testsupport - Testcontainers (com.adobe.testing:s3mock-testcontainers:4.10.0 - https://www.github.com/adobe/S3Mock/s3mock-testsupport-reactor/s3mock-testcontainers)
* Titanium JSON-LD 1.1 (JRE11) (com.apicatalog:titanium-json-ld:1.3.2 - https://github.com/filip26/titanium-json-ld)
* HPPC Collections (com.carrotsearch:hppc:0.8.1 - http://labs.carrotsearch.com/hppc.html/hppc)
* com.drewnoakes:metadata-extractor (com.drewnoakes:metadata-extractor:2.19.0 - https://drewnoakes.com/code/exif/)
* parso (com.epam:parso:2.0.14 - https://github.com/epam/parso)
* Internet Time Utility (com.ethlo.time:itu:1.7.0 - https://github.com/ethlo/itu)
- * ClassMate (com.fasterxml:classmate:1.7.0 - https://github.com/FasterXML/java-classmate)
- * Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.19.1 - https://github.com/FasterXML/jackson)
- * Jackson-core (com.fasterxml.jackson.core:jackson-core:2.19.1 - https://github.com/FasterXML/jackson-core)
- * jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.19.1 - https://github.com/FasterXML/jackson)
- * Jackson dataformat: CBOR (com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.17.2 - https://github.com/FasterXML/jackson-dataformats-binary)
+ * ClassMate (com.fasterxml:classmate:1.7.1 - https://github.com/FasterXML/java-classmate)
+ * Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.20 - https://github.com/FasterXML/jackson)
+ * Jackson-core (com.fasterxml.jackson.core:jackson-core:2.20.1 - https://github.com/FasterXML/jackson-core)
+ * jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.20.1 - https://github.com/FasterXML/jackson)
* Jackson dataformat: Smile (com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.15.2 - https://github.com/FasterXML/jackson-dataformats-binary)
* Jackson-dataformat-TOML (com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2 - https://github.com/FasterXML/jackson-dataformats-text)
* Jackson-dataformat-YAML (com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.2 - https://github.com/FasterXML/jackson-dataformats-text)
- * Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.19.1 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8)
- * Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.19.1 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310)
+ * Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.19.4 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8)
+ * Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.1 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310)
* Jackson Jakarta-RS: base (com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-base:2.16.2 - https://github.com/FasterXML/jackson-jakarta-rs-providers/jackson-jakarta-rs-base)
* Jackson Jakarta-RS: JSON (com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-json-provider:2.16.2 - https://github.com/FasterXML/jackson-jakarta-rs-providers/jackson-jakarta-rs-json-provider)
* Jackson module: Jakarta XML Bind Annotations (jakarta.xml.bind) (com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.16.2 - https://github.com/FasterXML/jackson-modules-base)
- * Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.19.1 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names)
+ * Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.19.4 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names)
* Java UUID Generator (com.fasterxml.uuid:java-uuid-generator:4.1.0 - https://github.com/cowtowncoder/java-uuid-generator)
* Woodstox (com.fasterxml.woodstox:woodstox-core:6.5.1 - https://github.com/FasterXML/woodstox)
* zjsonpatch (com.flipkart.zjsonpatch:zjsonpatch:0.4.16 - https://github.com/flipkart-incubator/zjsonpatch/)
* Caffeine cache (com.github.ben-manes.caffeine:caffeine:2.9.3 - https://github.com/ben-manes/caffeine)
* Caffeine cache (com.github.ben-manes.caffeine:caffeine:3.1.8 - https://github.com/ben-manes/caffeine)
* JSON.simple (com.github.cliftonlabs:json-simple:3.0.2 - https://cliftonlabs.github.io/json-simple/)
+ * docker-java-api (com.github.docker-java:docker-java-api:3.4.2 - https://github.com/docker-java/docker-java)
+ * docker-java-transport (com.github.docker-java:docker-java-transport:3.4.2 - https://github.com/docker-java/docker-java)
+ * docker-java-transport-zerodep (com.github.docker-java:docker-java-transport-zerodep:3.4.2 - https://github.com/docker-java/docker-java)
* btf (com.github.java-json-tools:btf:1.3 - https://github.com/java-json-tools/btf)
* jackson-coreutils (com.github.java-json-tools:jackson-coreutils:2.0 - https://github.com/java-json-tools/jackson-coreutils)
* jackson-coreutils-equivalence (com.github.java-json-tools:jackson-coreutils-equivalence:1.0 - https://github.com/java-json-tools/jackson-coreutils)
@@ -60,25 +59,25 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* uri-template (com.github.java-json-tools:uri-template:0.10 - https://github.com/java-json-tools/uri-template)
* JCIP Annotations under Apache License (com.github.stephenc.jcip:jcip-annotations:1.0-1 - http://stephenc.github.com/jcip-annotations)
* FindBugs-jsr305 (com.google.code.findbugs:jsr305:3.0.2 - http://findbugs.sourceforge.net/)
- * Gson (com.google.code.gson:gson:2.13.1 - https://github.com/google/gson)
- * error-prone annotations (com.google.errorprone:error_prone_annotations:2.38.0 - https://errorprone.info/error_prone_annotations)
+ * Gson (com.google.code.gson:gson:2.13.2 - https://github.com/google/gson)
+ * error-prone annotations (com.google.errorprone:error_prone_annotations:2.42.0 - https://errorprone.info/error_prone_annotations)
* Guava InternalFutureFailureAccess and InternalFutures (com.google.guava:failureaccess:1.0.1 - https://github.com/google/guava/failureaccess)
* Guava: Google Core Libraries for Java (com.google.guava:guava:32.1.3-jre - https://github.com/google/guava)
* Guava ListenableFuture only (com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava - https://github.com/google/guava/listenablefuture)
* J2ObjC Annotations (com.google.j2objc:j2objc-annotations:1.3 - https://github.com/google/j2objc/)
* J2ObjC Annotations (com.google.j2objc:j2objc-annotations:2.8 - https://github.com/google/j2objc/)
* libphonenumber (com.googlecode.libphonenumber:libphonenumber:8.11.1 - https://github.com/google/libphonenumber/)
- * Jackcess (com.healthmarketscience.jackcess:jackcess:4.0.8 - https://jackcess.sourceforge.io)
+ * Jackcess (com.healthmarketscience.jackcess:jackcess:4.0.10 - https://jackcess.sourceforge.io)
* Jackcess Encrypt (com.healthmarketscience.jackcess:jackcess-encrypt:4.0.3 - http://jackcessencrypt.sf.net)
- * json-path (com.jayway.jsonpath:json-path:2.9.0 - https://github.com/jayway/JsonPath)
- * json-path-assert (com.jayway.jsonpath:json-path-assert:2.9.0 - https://github.com/jayway/JsonPath)
+ * json-path (com.jayway.jsonpath:json-path:2.10.0 - https://github.com/jayway/JsonPath)
+ * json-path-assert (com.jayway.jsonpath:json-path-assert:2.10.0 - https://github.com/jayway/JsonPath)
* Disruptor Framework (com.lmax:disruptor:3.4.2 - http://lmax-exchange.github.com/disruptor)
* MaxMind DB Reader (com.maxmind.db:maxmind-db:2.1.0 - http://dev.maxmind.com/)
* MaxMind GeoIP2 API (com.maxmind.geoip2:geoip2:2.17.0 - https://dev.maxmind.com/geoip?lang=en)
* JsonSchemaValidator (com.networknt:json-schema-validator:1.0.76 - https://github.com/networknt/json-schema-validator)
* Nimbus JOSE+JWT (com.nimbusds:nimbus-jose-jwt:9.28 - https://bitbucket.org/connect2id/nimbus-jose-jwt)
* Nimbus JOSE+JWT (com.nimbusds:nimbus-jose-jwt:9.48 - https://bitbucket.org/connect2id/nimbus-jose-jwt)
- * opencsv (com.opencsv:opencsv:5.11.1 - http://opencsv.sf.net)
+ * opencsv (com.opencsv:opencsv:5.12.0 - http://opencsv.sf.net)
* java-libpst (com.pff:java-libpst:0.9.3 - https://github.com/rjohnsondev/java-libpst)
* rome (com.rometools:rome:1.19.0 - http://rometools.com/rome)
* rome-modules (com.rometools:rome-modules:1.19.0 - http://rometools.com/rome-modules)
@@ -88,26 +87,17 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* okio (com.squareup.okio:okio:3.6.0 - https://github.com/square/okio/)
* okio (com.squareup.okio:okio-jvm:3.6.0 - https://github.com/square/okio/)
* T-Digest (com.tdunning:t-digest:3.1 - https://github.com/tdunning/t-digest)
- * config (com.typesafe:config:1.3.3 - https://github.com/lightbend/config)
- * ssl-config-core (com.typesafe:ssl-config-core_2.13:0.3.8 - https://github.com/lightbend/ssl-config)
- * akka-actor (com.typesafe.akka:akka-actor_2.13:2.5.31 - https://akka.io/)
- * akka-http-core (com.typesafe.akka:akka-http-core_2.13:10.1.12 - https://akka.io)
- * akka-http (com.typesafe.akka:akka-http_2.13:10.1.12 - https://akka.io)
- * akka-parsing (com.typesafe.akka:akka-parsing_2.13:10.1.12 - https://akka.io)
- * akka-protobuf (com.typesafe.akka:akka-protobuf_2.13:2.5.31 - https://akka.io/)
- * akka-stream (com.typesafe.akka:akka-stream_2.13:2.5.31 - https://akka.io/)
- * scala-logging (com.typesafe.scala-logging:scala-logging_2.13:3.9.2 - https://github.com/lightbend/scala-logging)
* JSON library from Android SDK (com.vaadin.external.google:android-json:0.0.20131108.vaadin1 - http://developer.android.com/sdk)
* SparseBitSet (com.zaxxer:SparseBitSet:1.3 - https://github.com/brettwooldridge/SparseBitSet)
* Apache Commons BeanUtils (commons-beanutils:commons-beanutils:1.11.0 - https://commons.apache.org/proper/commons-beanutils)
- * Apache Commons CLI (commons-cli:commons-cli:1.9.0 - https://commons.apache.org/proper/commons-cli/)
- * Apache Commons Codec (commons-codec:commons-codec:1.18.0 - https://commons.apache.org/proper/commons-codec/)
+ * Apache Commons CLI (commons-cli:commons-cli:1.11.0 - https://commons.apache.org/proper/commons-cli/)
+ * Apache Commons Codec (commons-codec:commons-codec:1.20.0 - https://commons.apache.org/proper/commons-codec/)
* Apache Commons Collections (commons-collections:commons-collections:3.2.2 - http://commons.apache.org/collections/)
* Commons Digester (commons-digester:commons-digester:2.1 - http://commons.apache.org/digester/)
- * Apache Commons IO (commons-io:commons-io:2.19.0 - https://commons.apache.org/proper/commons-io/)
+ * Apache Commons IO (commons-io:commons-io:2.21.0 - https://commons.apache.org/proper/commons-io/)
* Commons Lang (commons-lang:commons-lang:2.6 - http://commons.apache.org/lang/)
* Apache Commons Logging (commons-logging:commons-logging:1.3.5 - https://commons.apache.org/proper/commons-logging/)
- * Apache Commons Validator (commons-validator:commons-validator:1.9.0 - http://commons.apache.org/proper/commons-validator/)
+ * Apache Commons Validator (commons-validator:commons-validator:1.10.1 - https://commons.apache.org/proper/commons-validator/)
* GeoJson POJOs for Jackson (de.grundid.opendatalab:geojson-jackson:1.14 - https://github.com/opendatalab-de/geojson-jackson)
* broker-client (eu.openaire:broker-client:1.1.2 - http://api.openaire.eu/broker/broker-client)
* OpenAIRE Funders Model (eu.openaire:funders-model:2.0.0 - https://api.openaire.eu)
@@ -117,10 +107,10 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Metrics Integration with JMX (io.dropwizard.metrics:metrics-jmx:4.1.5 - https://metrics.dropwizard.io/metrics-jmx)
* JVM Integration for Metrics (io.dropwizard.metrics:metrics-jvm:4.1.5 - https://metrics.dropwizard.io/metrics-jvm)
* SWORD v2 Common Server Library (forked) (io.gdcc:sword2-server:2.0.0 - https://github.com/gdcc/sword2-server)
- * micrometer-commons (io.micrometer:micrometer-commons:1.14.8 - https://github.com/micrometer-metrics/micrometer)
- * micrometer-core (io.micrometer:micrometer-core:1.15.1 - https://github.com/micrometer-metrics/micrometer)
- * micrometer-jakarta9 (io.micrometer:micrometer-jakarta9:1.15.1 - https://github.com/micrometer-metrics/micrometer)
- * micrometer-observation (io.micrometer:micrometer-observation:1.14.8 - https://github.com/micrometer-metrics/micrometer)
+ * micrometer-commons (io.micrometer:micrometer-commons:1.14.13 - https://github.com/micrometer-metrics/micrometer)
+ * micrometer-core (io.micrometer:micrometer-core:1.15.6 - https://github.com/micrometer-metrics/micrometer)
+ * micrometer-jakarta9 (io.micrometer:micrometer-jakarta9:1.15.6 - https://github.com/micrometer-metrics/micrometer)
+ * micrometer-observation (io.micrometer:micrometer-observation:1.14.13 - https://github.com/micrometer-metrics/micrometer)
* Netty/Buffer (io.netty:netty-buffer:4.1.99.Final - https://netty.io/netty-buffer/)
* Netty/Codec (io.netty:netty-codec:4.1.99.Final - https://netty.io/netty-codec/)
* Netty/Codec/HTTP (io.netty:netty-codec-http:4.1.86.Final - https://netty.io/netty-codec-http/)
@@ -168,39 +158,38 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Jakarta Bean Validation API (jakarta.validation:jakarta.validation-api:3.0.2 - https://beanvalidation.org)
* JSR107 API and SPI (javax.cache:cache-api:1.1.1 - https://github.com/jsr107/jsr107spec)
* jdbm (jdbm:jdbm:1.0 - no url defined)
- * Joda-Time (joda-time:joda-time:2.12.7 - https://www.joda.org/joda-time/)
+ * Joda-Time (joda-time:joda-time:2.10.5 - https://www.joda.org/joda-time/)
* Byte Buddy (without dependencies) (net.bytebuddy:byte-buddy:1.11.13 - https://bytebuddy.net/byte-buddy)
* Byte Buddy (without dependencies) (net.bytebuddy:byte-buddy:1.14.11 - https://bytebuddy.net/byte-buddy)
* Byte Buddy agent (net.bytebuddy:byte-buddy-agent:1.11.13 - https://bytebuddy.net/byte-buddy-agent)
* eigenbase-properties (net.hydromatic:eigenbase-properties:1.1.5 - http://github.com/julianhyde/eigenbase-properties)
+ * Java Native Access (net.java.dev.jna:jna:5.13.0 - https://github.com/java-native-access/jna)
* json-unit-core (net.javacrumbs.json-unit:json-unit-core:2.36.0 - https://github.com/lukas-krecan/JsonUnit/json-unit-core)
* "Java Concurrency in Practice" book annotations (net.jcip:jcip-annotations:1.0 - http://jcip.net/)
- * ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.5.0 - https://urielch.github.io/)
- * ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.5.2 - https://urielch.github.io/)
- * JSON Small and Fast Parser (net.minidev:json-smart:2.5.0 - https://urielch.github.io/)
- * JSON Small and Fast Parser (net.minidev:json-smart:2.5.2 - https://urielch.github.io/)
+ * ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.6.0 - https://urielch.github.io/)
+ * JSON Small and Fast Parser (net.minidev:json-smart:2.6.0 - https://urielch.github.io/)
* Abdera Core (org.apache.abdera:abdera-core:1.1.3 - http://abdera.apache.org/abdera-core)
* I18N Libraries (org.apache.abdera:abdera-i18n:1.1.3 - http://abdera.apache.org)
* Abdera Parser (org.apache.abdera:abdera-parser:1.1.3 - http://abdera.apache.org/abdera-parser)
* Apache Ant Core (org.apache.ant:ant:1.10.15 - https://ant.apache.org/)
* Apache Ant Launcher (org.apache.ant:ant-launcher:1.10.15 - https://ant.apache.org/)
- * Apache Commons BCEL (org.apache.bcel:bcel:6.10.0 - https://commons.apache.org/proper/commons-bcel)
+ * Apache Commons BCEL (org.apache.bcel:bcel:6.11.0 - https://commons.apache.org/proper/commons-bcel)
* Calcite Core (org.apache.calcite:calcite-core:1.35.0 - https://calcite.apache.org)
* Calcite Linq4j (org.apache.calcite:calcite-linq4j:1.35.0 - https://calcite.apache.org)
* Apache Calcite Avatica (org.apache.calcite.avatica:avatica-core:1.23.0 - https://calcite.apache.org/avatica)
* Apache Calcite Avatica Metrics (org.apache.calcite.avatica:avatica-metrics:1.23.0 - https://calcite.apache.org/avatica)
* Apache Commons Collections (org.apache.commons:commons-collections4:4.5.0 - https://commons.apache.org/proper/commons-collections/)
- * Apache Commons Compress (org.apache.commons:commons-compress:1.27.1 - https://commons.apache.org/proper/commons-compress/)
- * Apache Commons Configuration (org.apache.commons:commons-configuration2:2.12.0 - https://commons.apache.org/proper/commons-configuration/)
- * Apache Commons CSV (org.apache.commons:commons-csv:1.14.0 - https://commons.apache.org/proper/commons-csv/)
+ * Apache Commons Compress (org.apache.commons:commons-compress:1.28.0 - https://commons.apache.org/proper/commons-compress/)
+ * Apache Commons Configuration (org.apache.commons:commons-configuration2:2.13.0 - https://commons.apache.org/proper/commons-configuration/)
+ * Apache Commons CSV (org.apache.commons:commons-csv:1.14.1 - https://commons.apache.org/proper/commons-csv/)
* Apache Commons DBCP (org.apache.commons:commons-dbcp2:2.13.0 - https://commons.apache.org/proper/commons-dbcp/)
* Apache Commons Digester (org.apache.commons:commons-digester3:3.2 - http://commons.apache.org/digester/)
* Apache Commons Exec (org.apache.commons:commons-exec:1.3 - http://commons.apache.org/proper/commons-exec/)
- * Apache Commons Exec (org.apache.commons:commons-exec:1.4.0 - https://commons.apache.org/proper/commons-exec/)
- * Apache Commons Lang (org.apache.commons:commons-lang3:3.17.0 - https://commons.apache.org/proper/commons-lang/)
+ * Apache Commons Exec (org.apache.commons:commons-exec:1.5.0 - https://commons.apache.org/proper/commons-exec/)
+ * Apache Commons Lang (org.apache.commons:commons-lang3:3.20.0 - https://commons.apache.org/proper/commons-lang/)
* Apache Commons Math (org.apache.commons:commons-math3:3.6.1 - http://commons.apache.org/proper/commons-math/)
* Apache Commons Pool (org.apache.commons:commons-pool2:2.12.1 - https://commons.apache.org/proper/commons-pool/)
- * Apache Commons Text (org.apache.commons:commons-text:1.13.1 - https://commons.apache.org/proper/commons-text)
+ * Apache Commons Text (org.apache.commons:commons-text:1.14.0 - https://commons.apache.org/proper/commons-text)
* Curator Client (org.apache.curator:curator-client:2.13.0 - http://curator.apache.org/curator-client)
* Curator Framework (org.apache.curator:curator-framework:2.13.0 - http://curator.apache.org/curator-framework)
* Curator Recipes (org.apache.curator:curator-recipes:2.13.0 - http://curator.apache.org/curator-recipes)
@@ -214,13 +203,13 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.16 - http://hc.apache.org/httpcomponents-core-ga)
* Apache HttpClient Mime (org.apache.httpcomponents:httpmime:4.5.14 - http://hc.apache.org/httpcomponents-client-ga)
* Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.1.3 - https://hc.apache.org/httpcomponents-client-5.0.x/5.1.3/httpclient5/)
- * Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.5 - https://hc.apache.org/httpcomponents-client-5.5.x/5.5/httpclient5/)
+ * Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.5.1 - https://hc.apache.org/httpcomponents-client-5.5.x/5.5.1/httpclient5/)
* Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.1.3 - https://hc.apache.org/httpcomponents-core-5.1.x/5.1.3/httpcore5/)
- * Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.3.4 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.4/httpcore5/)
+ * Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.3.6 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.6/httpcore5/)
* Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.1.3 - https://hc.apache.org/httpcomponents-core-5.1.x/5.1.3/httpcore5-h2/)
- * Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.3.4 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.4/httpcore5-h2/)
- * Apache James :: Mime4j :: Core (org.apache.james:apache-mime4j-core:0.8.12 - http://james.apache.org/mime4j/apache-mime4j-core)
- * Apache James :: Mime4j :: DOM (org.apache.james:apache-mime4j-dom:0.8.12 - http://james.apache.org/mime4j/apache-mime4j-dom)
+ * Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.3.6 - https://hc.apache.org/httpcomponents-core-5.3.x/5.3.6/httpcore5-h2/)
+ * Apache James :: Mime4j :: Core (org.apache.james:apache-mime4j-core:0.8.13 - http://james.apache.org/mime4j/apache-mime4j-core)
+ * Apache James :: Mime4j :: DOM (org.apache.james:apache-mime4j-dom:0.8.13 - http://james.apache.org/mime4j/apache-mime4j-dom)
* Apache Jena - Libraries POM (org.apache.jena:apache-jena-libs:4.10.0 - https://jena.apache.org/apache-jena-libs/)
* Apache Jena - ARQ (org.apache.jena:jena-arq:4.10.0 - https://jena.apache.org/jena-arq/)
* Apache Jena - Base (org.apache.jena:jena-base:4.10.0 - https://jena.apache.org/jena-base/)
@@ -242,12 +231,12 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Kerby ASN1 Project (org.apache.kerby:kerby-asn1:1.0.1 - http://directory.apache.org/kerby/kerby-common/kerby-asn1)
* Kerby PKIX Project (org.apache.kerby:kerby-pkix:1.0.1 - http://directory.apache.org/kerby/kerby-pkix)
* Apache Log4j 1.x Compatibility API (org.apache.logging.log4j:log4j-1.2-api:2.17.2 - https://logging.apache.org/log4j/2.x/log4j-1.2-api/)
- * Apache Log4j API (org.apache.logging.log4j:log4j-api:2.24.3 - https://logging.apache.org/log4j/2.x/log4j/log4j-api/)
- * Apache Log4j Core (org.apache.logging.log4j:log4j-core:2.24.3 - https://logging.apache.org/log4j/2.x/log4j/log4j-core/)
+ * Apache Log4j API (org.apache.logging.log4j:log4j-api:2.25.2 - https://logging.apache.org/log4j/2.x/)
+ * Apache Log4j Core (org.apache.logging.log4j:log4j-core:2.25.2 - https://logging.apache.org/log4j/2.x/)
* Apache Log4j JUL Adapter (org.apache.logging.log4j:log4j-jul:2.24.3 - https://logging.apache.org/log4j/2.x/log4j/log4j-jul/)
* Apache Log4j Layout for JSON template (org.apache.logging.log4j:log4j-layout-template-json:2.17.2 - https://logging.apache.org/log4j/2.x/log4j-layout-template-json/)
* Apache Log4j SLF4J Binding (org.apache.logging.log4j:log4j-slf4j-impl:2.17.2 - https://logging.apache.org/log4j/2.x/log4j-slf4j-impl/)
- * SLF4J 2 Provider for Log4j API (org.apache.logging.log4j:log4j-slf4j2-impl:2.24.3 - https://logging.apache.org/log4j/2.x/log4j/log4j-slf4j2-impl/)
+ * SLF4J 2 Provider for Log4j API (org.apache.logging.log4j:log4j-slf4j2-impl:2.25.2 - https://logging.apache.org/log4j/2.x/)
* Apache Log4j Web (org.apache.logging.log4j:log4j-web:2.17.2 - https://logging.apache.org/log4j/2.x/log4j-web/)
* Lucene Common Analyzers (org.apache.lucene:lucene-analyzers-common:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-common)
* Lucene ICU Analysis Components (org.apache.lucene:lucene-analyzers-icu:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-analyzers-icu)
@@ -272,12 +261,13 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Lucene Spatial Extras (org.apache.lucene:lucene-spatial-extras:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-spatial-extras)
* Lucene Spatial 3D (org.apache.lucene:lucene-spatial3d:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-spatial3d)
* Lucene Suggest (org.apache.lucene:lucene-suggest:8.11.4 - https://lucene.apache.org/lucene-parent/lucene-suggest)
- * Apache FontBox (org.apache.pdfbox:fontbox:2.0.34 - http://pdfbox.apache.org/)
+ * Apache FontBox (org.apache.pdfbox:fontbox:3.0.5 - http://pdfbox.apache.org/)
* PDFBox JBIG2 ImageIO plugin (org.apache.pdfbox:jbig2-imageio:3.0.4 - https://www.apache.org/jbig2-imageio/)
* Apache JempBox (org.apache.pdfbox:jempbox:1.8.17 - http://www.apache.org/pdfbox-parent/jempbox/)
- * Apache PDFBox (org.apache.pdfbox:pdfbox:2.0.34 - https://www.apache.org/pdfbox-parent/pdfbox/)
- * Apache PDFBox tools (org.apache.pdfbox:pdfbox-tools:2.0.34 - https://www.apache.org/pdfbox-parent/pdfbox-tools/)
- * Apache XmpBox (org.apache.pdfbox:xmpbox:2.0.34 - https://www.apache.org/pdfbox-parent/xmpbox/)
+ * Apache PDFBox (org.apache.pdfbox:pdfbox:3.0.5 - https://www.apache.org/pdfbox-parent/pdfbox/)
+ * Apache PDFBox io (org.apache.pdfbox:pdfbox-io:3.0.5 - https://www.apache.org/pdfbox-parent/pdfbox-io/)
+ * Apache PDFBox tools (org.apache.pdfbox:pdfbox-tools:3.0.5 - https://www.apache.org/pdfbox-parent/pdfbox-tools/)
+ * Apache XmpBox (org.apache.pdfbox:xmpbox:3.0.5 - https://www.apache.org/pdfbox-parent/xmpbox/)
* Apache POI - Common (org.apache.poi:poi:5.4.1 - https://poi.apache.org/)
* Apache POI - API based on OPC and OOXML schemas (org.apache.poi:poi-ooxml:5.4.1 - https://poi.apache.org/)
* Apache POI (org.apache.poi:poi-ooxml-lite:5.4.1 - https://poi.apache.org/)
@@ -287,33 +277,33 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Apache Standard Taglib Implementation (org.apache.taglibs:taglibs-standard-impl:1.2.5 - http://tomcat.apache.org/taglibs/standard-1.2.5/taglibs-standard-impl)
* Apache Standard Taglib Specification API (org.apache.taglibs:taglibs-standard-spec:1.2.5 - http://tomcat.apache.org/taglibs/standard-1.2.5/taglibs-standard-spec)
* Apache Thrift (org.apache.thrift:libthrift:0.19.0 - http://thrift.apache.org)
- * Apache Tika core (org.apache.tika:tika-core:2.9.4 - https://tika.apache.org/)
- * Apache Tika Apple parser module (org.apache.tika:tika-parser-apple-module:2.9.4 - https://tika.apache.org/tika-parser-apple-module/)
- * Apache Tika audiovideo parser module (org.apache.tika:tika-parser-audiovideo-module:2.9.4 - https://tika.apache.org/tika-parser-audiovideo-module/)
- * Apache Tika cad parser module (org.apache.tika:tika-parser-cad-module:2.9.4 - https://tika.apache.org/tika-parser-cad-module/)
- * Apache Tika code parser module (org.apache.tika:tika-parser-code-module:2.9.4 - https://tika.apache.org/tika-parser-code-module/)
- * Apache Tika crypto parser module (org.apache.tika:tika-parser-crypto-module:2.9.4 - https://tika.apache.org/tika-parser-crypto-module/)
- * Apache Tika digest commons (org.apache.tika:tika-parser-digest-commons:2.9.4 - https://tika.apache.org/tika-parser-digest-commons/)
- * Apache Tika font parser module (org.apache.tika:tika-parser-font-module:2.9.4 - https://tika.apache.org/tika-parser-font-module/)
- * Apache Tika html parser module (org.apache.tika:tika-parser-html-module:2.9.4 - https://tika.apache.org/tika-parser-html-module/)
- * Apache Tika image parser module (org.apache.tika:tika-parser-image-module:2.9.4 - https://tika.apache.org/tika-parser-image-module/)
- * Apache Tika mail commons (org.apache.tika:tika-parser-mail-commons:2.9.4 - https://tika.apache.org/tika-parser-mail-commons/)
- * Apache Tika mail parser module (org.apache.tika:tika-parser-mail-module:2.9.4 - https://tika.apache.org/tika-parser-mail-module/)
- * Apache Tika Microsoft parser module (org.apache.tika:tika-parser-microsoft-module:2.9.4 - https://tika.apache.org/tika-parser-microsoft-module/)
- * Apache Tika miscellaneous office format parser module (org.apache.tika:tika-parser-miscoffice-module:2.9.4 - https://tika.apache.org/tika-parser-miscoffice-module/)
- * Apache Tika news parser module (org.apache.tika:tika-parser-news-module:2.9.4 - https://tika.apache.org/tika-parser-news-module/)
- * Apache Tika OCR parser module (org.apache.tika:tika-parser-ocr-module:2.9.4 - https://tika.apache.org/tika-parser-ocr-module/)
- * Apache Tika PDF parser module (org.apache.tika:tika-parser-pdf-module:2.9.4 - https://tika.apache.org/tika-parser-pdf-module/)
- * Apache Tika package parser module (org.apache.tika:tika-parser-pkg-module:2.9.4 - https://tika.apache.org/tika-parser-pkg-module/)
- * Apache Tika text parser module (org.apache.tika:tika-parser-text-module:2.9.4 - https://tika.apache.org/tika-parser-text-module/)
- * Apache Tika WARC parser module (org.apache.tika:tika-parser-webarchive-module:2.9.4 - https://tika.apache.org/tika-parser-webarchive-module/)
- * Apache Tika XML parser module (org.apache.tika:tika-parser-xml-module:2.9.4 - https://tika.apache.org/tika-parser-xml-module/)
- * Apache Tika XMP commons (org.apache.tika:tika-parser-xmp-commons:2.9.4 - https://tika.apache.org/tika-parser-xmp-commons/)
- * Apache Tika ZIP commons (org.apache.tika:tika-parser-zip-commons:2.9.4 - https://tika.apache.org/tika-parser-zip-commons/)
- * Apache Tika standard parser package (org.apache.tika:tika-parsers-standard-package:2.9.4 - https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/)
- * tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:10.1.42 - https://tomcat.apache.org/)
- * tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:10.1.42 - https://tomcat.apache.org/)
- * tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:10.1.42 - https://tomcat.apache.org/)
+ * Apache Tika core (org.apache.tika:tika-core:3.2.3 - https://tika.apache.org/)
+ * Apache Tika Apple parser module (org.apache.tika:tika-parser-apple-module:3.2.3 - https://tika.apache.org/tika-parser-apple-module/)
+ * Apache Tika audiovideo parser module (org.apache.tika:tika-parser-audiovideo-module:3.2.3 - https://tika.apache.org/tika-parser-audiovideo-module/)
+ * Apache Tika cad parser module (org.apache.tika:tika-parser-cad-module:3.2.3 - https://tika.apache.org/tika-parser-cad-module/)
+ * Apache Tika code parser module (org.apache.tika:tika-parser-code-module:3.2.3 - https://tika.apache.org/tika-parser-code-module/)
+ * Apache Tika crypto parser module (org.apache.tika:tika-parser-crypto-module:3.2.3 - https://tika.apache.org/tika-parser-crypto-module/)
+ * Apache Tika digest commons (org.apache.tika:tika-parser-digest-commons:3.2.3 - https://tika.apache.org/tika-parser-digest-commons/)
+ * Apache Tika font parser module (org.apache.tika:tika-parser-font-module:3.2.3 - https://tika.apache.org/tika-parser-font-module/)
+ * Apache Tika html parser module (org.apache.tika:tika-parser-html-module:3.2.3 - https://tika.apache.org/tika-parser-html-module/)
+ * Apache Tika image parser module (org.apache.tika:tika-parser-image-module:3.2.3 - https://tika.apache.org/tika-parser-image-module/)
+ * Apache Tika mail commons (org.apache.tika:tika-parser-mail-commons:3.2.3 - https://tika.apache.org/tika-parser-mail-commons/)
+ * Apache Tika mail parser module (org.apache.tika:tika-parser-mail-module:3.2.3 - https://tika.apache.org/tika-parser-mail-module/)
+ * Apache Tika Microsoft parser module (org.apache.tika:tika-parser-microsoft-module:3.2.3 - https://tika.apache.org/tika-parser-microsoft-module/)
+ * Apache Tika miscellaneous office format parser module (org.apache.tika:tika-parser-miscoffice-module:3.2.3 - https://tika.apache.org/tika-parser-miscoffice-module/)
+ * Apache Tika news parser module (org.apache.tika:tika-parser-news-module:3.2.3 - https://tika.apache.org/tika-parser-news-module/)
+ * Apache Tika OCR parser module (org.apache.tika:tika-parser-ocr-module:3.2.3 - https://tika.apache.org/tika-parser-ocr-module/)
+ * Apache Tika PDF parser module (org.apache.tika:tika-parser-pdf-module:3.2.3 - https://tika.apache.org/tika-parser-pdf-module/)
+ * Apache Tika package parser module (org.apache.tika:tika-parser-pkg-module:3.2.3 - https://tika.apache.org/tika-parser-pkg-module/)
+ * Apache Tika text parser module (org.apache.tika:tika-parser-text-module:3.2.3 - https://tika.apache.org/tika-parser-text-module/)
+ * Apache Tika WARC parser module (org.apache.tika:tika-parser-webarchive-module:3.2.3 - https://tika.apache.org/tika-parser-webarchive-module/)
+ * Apache Tika XML parser module (org.apache.tika:tika-parser-xml-module:3.2.3 - https://tika.apache.org/tika-parser-xml-module/)
+ * Apache Tika XMP commons (org.apache.tika:tika-parser-xmp-commons:3.2.3 - https://tika.apache.org/tika-parser-xmp-commons/)
+ * Apache Tika ZIP commons (org.apache.tika:tika-parser-zip-commons:3.2.3 - https://tika.apache.org/tika-parser-zip-commons/)
+ * Apache Tika standard parser package (org.apache.tika:tika-parsers-standard-package:3.2.3 - https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/)
+ * tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:10.1.49 - https://tomcat.apache.org/)
+ * tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:10.1.49 - https://tomcat.apache.org/)
+ * tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:10.1.49 - https://tomcat.apache.org/)
* Apache Velocity - Engine (org.apache.velocity:velocity-engine-core:2.4.1 - http://velocity.apache.org/engine/devel/velocity-engine-core/)
* Apache Velocity - JSR 223 Scripting (org.apache.velocity:velocity-engine-scripting:2.3 - http://velocity.apache.org/engine/devel/velocity-engine-scripting/)
* Apache Velocity Tools - Generic tools (org.apache.velocity.tools:velocity-tools-generic:3.1 - https://velocity.apache.org/tools/devel/velocity-tools-generic/)
@@ -323,12 +313,11 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Apache ZooKeeper - Server (org.apache.zookeeper:zookeeper:3.6.2 - http://zookeeper.apache.org/zookeeper)
* Apache ZooKeeper - Jute (org.apache.zookeeper:zookeeper-jute:3.6.2 - http://zookeeper.apache.org/zookeeper-jute)
* org.apiguardian:apiguardian-api (org.apiguardian:apiguardian-api:1.1.2 - https://github.com/apiguardian-team/apiguardian)
- * AssertJ Core (org.assertj:assertj-core:3.27.3 - https://assertj.github.io/doc/#assertj-core)
+ * AssertJ Core (org.assertj:assertj-core:3.27.6 - https://assertj.github.io/doc/#assertj-core)
* Evo Inflector (org.atteo:evo-inflector:1.3 - http://atteo.org/static/evo-inflector)
* attoparser (org.attoparser:attoparser:2.0.7.RELEASE - https://www.attoparser.org)
* Awaitility (org.awaitility:awaitility:4.2.2 - http://awaitility.org)
* jose4j (org.bitbucket.b_c:jose4j:0.6.5 - https://bitbucket.org/b_c/jose4j/)
- * TagSoup (org.ccil.cowan.tagsoup:tagsoup:1.2.1 - http://home.ccil.org/~cowan/XML/tagsoup/)
* Woodstox (org.codehaus.woodstox:wstx-asl:3.2.6 - http://woodstox.codehaus.org)
* jems (org.dmfs:jems:1.18 - https://github.com/dmfs/jems)
* rfc3986-uri (org.dmfs:rfc3986-uri:0.8.1 - https://github.com/dmfs/uri-toolkit)
@@ -344,122 +333,145 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Jetty :: Asynchronous HTTP Client (org.eclipse.jetty:jetty-client:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-client)
* Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-continuation)
- * Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.57.v20241219 - https://jetty.org/jetty-deploy/)
- * Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.57.v20241219 - https://jetty.org/jetty-http/)
- * Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.57.v20241219 - https://jetty.org/jetty-io/)
+ * Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.58.v20250814 - https://jetty.org/jetty-deploy/)
+ * Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.58.v20250814 - https://jetty.org/jetty-http/)
+ * Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.58.v20250814 - https://jetty.org/jetty-io/)
* Jetty :: JMX Management (org.eclipse.jetty:jetty-jmx:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-jmx)
* Jetty :: JNDI Naming (org.eclipse.jetty:jetty-jndi:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Jetty :: Plus (org.eclipse.jetty:jetty-plus:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Jetty :: Rewrite Handler (org.eclipse.jetty:jetty-rewrite:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-rewrite)
* Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-security)
- * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.57.v20241219 - https://jetty.org/jetty-security/)
- * Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.57.v20241219 - https://jetty.org/jetty-server/)
- * Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.57.v20241219 - https://jetty.org/jetty-servlet/)
+ * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.58.v20250814 - https://jetty.org/jetty-security/)
+ * Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.58.v20250814 - https://jetty.org/jetty-server/)
+ * Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.58.v20250814 - https://jetty.org/jetty-servlet/)
* Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-servlets)
- * Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.57.v20241219 - https://jetty.org/jetty-util/)
- * Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.57.v20241219 - https://jetty.org/jetty-util-ajax/)
- * Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.57.v20241219 - https://jetty.org/jetty-webapp/)
+ * Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.58.v20250814 - https://jetty.org/jetty-util/)
+ * Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.58.v20250814 - https://jetty.org/jetty-util-ajax/)
+ * Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.58.v20250814 - https://jetty.org/jetty-webapp/)
* Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-xml)
- * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.57.v20241219 - https://jetty.org/jetty-xml/)
+ * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.58.v20250814 - https://jetty.org/jetty-xml/)
* Jetty :: ALPN :: API (org.eclipse.jetty.alpn:alpn-api:1.1.3.v20160715 - http://www.eclipse.org/jetty/alpn-api)
* Jetty :: HTTP2 :: Client (org.eclipse.jetty.http2:http2-client:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-client)
- * Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.57.v20241219 - https://jetty.org/http2-parent/http2-common/)
+ * Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.58.v20250814 - https://jetty.org/http2-parent/http2-common/)
* Jetty :: HTTP2 :: HPACK (org.eclipse.jetty.http2:http2-hpack:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-hpack)
* Jetty :: HTTP2 :: HTTP Client Transport (org.eclipse.jetty.http2:http2-http-client-transport:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-http-client-transport)
* Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.15.v20190215 - https://eclipse.org/jetty/http2-parent/http2-server)
* Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-server)
* Jetty :: Schemas (org.eclipse.jetty.toolchain:jetty-schemas:3.1.2 - https://eclipse.org/jetty/jetty-schemas)
- * Ehcache (org.ehcache:ehcache:3.10.8 - http://ehcache.org)
+ * Ehcache (org.ehcache:ehcache:3.11.1 - http://ehcache.org)
* flyway-core (org.flywaydb:flyway-core:10.22.0 - https://flywaydb.org/flyway-core)
* flyway-database-postgresql (org.flywaydb:flyway-database-postgresql:10.22.0 - https://flywaydb.org/flyway-database-postgresql)
* Ogg and Vorbis for Java, Core (org.gagravarr:vorbis-java-core:0.8 - https://github.com/Gagravarr/VorbisJava)
* Apache Tika plugin for Ogg, Vorbis and FLAC (org.gagravarr:vorbis-java-tika:0.8 - https://github.com/Gagravarr/VorbisJava)
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
- * Hibernate Validator Engine (org.hibernate.validator:hibernate-validator:8.0.2.Final - http://hibernate.org/validator/hibernate-validator)
- * Hibernate Validator Portable Extension (org.hibernate.validator:hibernate-validator-cdi:8.0.2.Final - http://hibernate.org/validator/hibernate-validator-cdi)
+ * Hibernate Validator Engine (org.hibernate.validator:hibernate-validator:8.0.3.Final - https://hibernate.org/validator)
+ * Hibernate Validator Portable Extension (org.hibernate.validator:hibernate-validator-cdi:8.0.3.Final - https://hibernate.org/validator)
* org.immutables.value-annotations (org.immutables:value-annotations:2.9.2 - http://immutables.org/value-annotations)
- * leveldb (org.iq80.leveldb:leveldb:0.12 - http://github.com/dain/leveldb/leveldb)
- * leveldb-api (org.iq80.leveldb:leveldb-api:0.12 - http://github.com/dain/leveldb/leveldb-api)
* Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/)
* JBoss Logging 3 (org.jboss.logging:jboss-logging:3.6.1.Final - http://www.jboss.org)
* JDOM (org.jdom:jdom2:2.0.6.1 - http://www.jdom.org)
- * IntelliJ IDEA Annotations (org.jetbrains:annotations:13.0 - http://www.jetbrains.org)
+ * JetBrains Java Annotations (org.jetbrains:annotations:17.0.0 - https://github.com/JetBrains/java-annotations)
* Kotlin Stdlib (org.jetbrains.kotlin:kotlin-stdlib:1.8.21 - https://kotlinlang.org/)
* Kotlin Stdlib Common (org.jetbrains.kotlin:kotlin-stdlib-common:1.8.21 - https://kotlinlang.org/)
* Kotlin Stdlib Jdk7 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21 - https://kotlinlang.org/)
* Kotlin Stdlib Jdk8 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21 - https://kotlinlang.org/)
+ * JSpecify annotations (org.jspecify:jspecify:1.0.0 - http://jspecify.org/)
* Proj4J (org.locationtech.proj4j:proj4j:1.1.5 - https://github.com/locationtech/proj4j)
* Spatial4J (org.locationtech.spatial4j:spatial4j:0.7 - https://projects.eclipse.org/projects/locationtech.spatial4j)
* MockServer Java Client (org.mock-server:mockserver-client-java:5.15.0 - https://www.mock-server.com)
* MockServer Core (org.mock-server:mockserver-core:5.15.0 - https://www.mock-server.com)
* MockServer JUnit 4 Integration (org.mock-server:mockserver-junit-rule:5.15.0 - https://www.mock-server.com)
* MockServer & Proxy Netty (org.mock-server:mockserver-netty:5.15.0 - https://www.mock-server.com)
- * jwarc (org.netpreserve:jwarc:0.31.1 - https://github.com/iipc/jwarc)
+ * jwarc (org.netpreserve:jwarc:0.32.0 - https://github.com/iipc/jwarc)
* Objenesis (org.objenesis:objenesis:3.2 - http://objenesis.org/objenesis)
- * org.opentest4j:opentest4j (org.opentest4j:opentest4j:1.3.0 - https://github.com/ota4j-team/opentest4j)
* org.roaringbitmap:RoaringBitmap (org.roaringbitmap:RoaringBitmap:1.0.0 - https://github.com/RoaringBitmap/RoaringBitmap)
* RRD4J (org.rrd4j:rrd4j:3.5 - https://github.com/rrd4j/rrd4j/)
- * Scala Library (org.scala-lang:scala-library:2.13.2 - https://www.scala-lang.org/)
- * Scala Compiler (org.scala-lang:scala-reflect:2.13.0 - https://www.scala-lang.org/)
- * scala-collection-compat (org.scala-lang.modules:scala-collection-compat_2.13:2.1.6 - http://www.scala-lang.org/)
- * scala-java8-compat (org.scala-lang.modules:scala-java8-compat_2.13:0.9.0 - http://www.scala-lang.org/)
- * scala-parser-combinators (org.scala-lang.modules:scala-parser-combinators_2.13:1.1.2 - http://www.scala-lang.org/)
- * scala-xml (org.scala-lang.modules:scala-xml_2.13:1.3.0 - http://www.scala-lang.org/)
* JSONassert (org.skyscreamer:jsonassert:1.5.3 - https://github.com/skyscreamer/JSONassert)
* JCL 1.2 implemented over SLF4J (org.slf4j:jcl-over-slf4j:2.0.17 - http://www.slf4j.org)
- * Spring AOP (org.springframework:spring-aop:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Beans (org.springframework:spring-beans:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Context (org.springframework:spring-context:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Context Support (org.springframework:spring-context-support:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Core (org.springframework:spring-core:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Expression Language (SpEL) (org.springframework:spring-expression:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Commons Logging Bridge (org.springframework:spring-jcl:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring JDBC (org.springframework:spring-jdbc:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Object/Relational Mapping (org.springframework:spring-orm:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring TestContext Framework (org.springframework:spring-test:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Transaction (org.springframework:spring-tx:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Web (org.springframework:spring-web:6.2.8 - https://github.com/spring-projects/spring-framework)
- * Spring Web MVC (org.springframework:spring-webmvc:6.2.8 - https://github.com/spring-projects/spring-framework)
- * spring-boot (org.springframework.boot:spring-boot:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-actuator (org.springframework.boot:spring-boot-actuator:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter (org.springframework.boot:spring-boot-starter:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-aop (org.springframework.boot:spring-boot-starter-aop:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-cache (org.springframework.boot:spring-boot-starter-cache:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-data-rest (org.springframework.boot:spring-boot-starter-data-rest:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-log4j2 (org.springframework.boot:spring-boot-starter-log4j2:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-security (org.springframework.boot:spring-boot-starter-security:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-test (org.springframework.boot:spring-boot-starter-test:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-thymeleaf (org.springframework.boot:spring-boot-starter-thymeleaf:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-test (org.springframework.boot:spring-boot-test:3.5.3 - https://spring.io/projects/spring-boot)
- * spring-boot-test-autoconfigure (org.springframework.boot:spring-boot-test-autoconfigure:3.5.3 - https://spring.io/projects/spring-boot)
- * Spring Data Core (org.springframework.data:spring-data-commons:3.5.1 - https://spring.io/projects/spring-data)
- * Spring Data REST - Core (org.springframework.data:spring-data-rest-core:4.5.1 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-core)
- * Spring Data REST - WebMVC (org.springframework.data:spring-data-rest-webmvc:4.5.1 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-webmvc)
+ * Spring AOP (org.springframework:spring-aop:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Beans (org.springframework:spring-beans:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Context (org.springframework:spring-context:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Context Support (org.springframework:spring-context-support:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Core (org.springframework:spring-core:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Expression Language (SpEL) (org.springframework:spring-expression:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Commons Logging Bridge (org.springframework:spring-jcl:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring JDBC (org.springframework:spring-jdbc:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Object/Relational Mapping (org.springframework:spring-orm:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring TestContext Framework (org.springframework:spring-test:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Transaction (org.springframework:spring-tx:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Web (org.springframework:spring-web:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * Spring Web MVC (org.springframework:spring-webmvc:6.2.14 - https://github.com/spring-projects/spring-framework)
+ * spring-boot (org.springframework.boot:spring-boot:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-actuator (org.springframework.boot:spring-boot-actuator:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter (org.springframework.boot:spring-boot-starter:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-aop (org.springframework.boot:spring-boot-starter-aop:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-cache (org.springframework.boot:spring-boot-starter-cache:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-data-rest (org.springframework.boot:spring-boot-starter-data-rest:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-log4j2 (org.springframework.boot:spring-boot-starter-log4j2:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-security (org.springframework.boot:spring-boot-starter-security:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-test (org.springframework.boot:spring-boot-starter-test:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-thymeleaf (org.springframework.boot:spring-boot-starter-thymeleaf:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-test (org.springframework.boot:spring-boot-test:3.5.8 - https://spring.io/projects/spring-boot)
+ * spring-boot-test-autoconfigure (org.springframework.boot:spring-boot-test-autoconfigure:3.5.8 - https://spring.io/projects/spring-boot)
+ * Spring Data Core (org.springframework.data:spring-data-commons:3.5.6 - https://spring.io/projects/spring-data)
+ * Spring Data REST - Core (org.springframework.data:spring-data-rest-core:4.5.6 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-core)
+ * Spring Data REST - WebMVC (org.springframework.data:spring-data-rest-webmvc:4.5.6 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-webmvc)
* Spring HATEOAS (org.springframework.hateoas:spring-hateoas:2.5.1 - https://github.com/spring-projects/spring-hateoas)
* Spring Plugin - Core (org.springframework.plugin:spring-plugin-core:3.0.0 - https://github.com/spring-projects/spring-plugin/spring-plugin-core)
- * spring-security-config (org.springframework.security:spring-security-config:6.5.1 - https://spring.io/projects/spring-security)
- * spring-security-core (org.springframework.security:spring-security-core:6.5.1 - https://spring.io/projects/spring-security)
- * spring-security-crypto (org.springframework.security:spring-security-crypto:6.5.1 - https://spring.io/projects/spring-security)
- * spring-security-test (org.springframework.security:spring-security-test:6.5.1 - https://spring.io/projects/spring-security)
- * spring-security-web (org.springframework.security:spring-security-web:6.5.1 - https://spring.io/projects/spring-security)
+ * spring-security-config (org.springframework.security:spring-security-config:6.5.7 - https://spring.io/projects/spring-security)
+ * spring-security-core (org.springframework.security:spring-security-core:6.5.7 - https://spring.io/projects/spring-security)
+ * spring-security-crypto (org.springframework.security:spring-security-crypto:6.5.7 - https://spring.io/projects/spring-security)
+ * spring-security-test (org.springframework.security:spring-security-test:6.5.7 - https://spring.io/projects/spring-security)
+ * spring-security-web (org.springframework.security:spring-security-web:6.5.7 - https://spring.io/projects/spring-security)
* thymeleaf (org.thymeleaf:thymeleaf:3.1.3.RELEASE - http://www.thymeleaf.org/thymeleaf-lib/thymeleaf)
* thymeleaf-spring6 (org.thymeleaf:thymeleaf-spring6:3.1.3.RELEASE - http://www.thymeleaf.org/thymeleaf-lib/thymeleaf-spring6)
* unbescape (org.unbescape:unbescape:1.1.6.RELEASE - http://www.unbescape.org)
* snappy-java (org.xerial.snappy:snappy-java:1.1.10.1 - https://github.com/xerial/snappy-java)
* xml-matchers (org.xmlmatchers:xml-matchers:0.10 - http://code.google.com/p/xml-matchers/)
- * org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.10.2 - https://www.xmlunit.org/)
+ * org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.10.4 - https://www.xmlunit.org/)
+ * org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.11.0 - https://www.xmlunit.org/)
* org.xmlunit:xmlunit-placeholders (org.xmlunit:xmlunit-placeholders:2.9.1 - https://www.xmlunit.org/xmlunit-placeholders/)
* SnakeYAML (org.yaml:snakeyaml:2.4 - https://bitbucket.org/snakeyaml/snakeyaml)
+ * AWS Java SDK :: Annotations (software.amazon.awssdk:annotations:2.38.8 - https://aws.amazon.com/sdkforjava/core/annotations)
+ * AWS Java SDK :: Arns (software.amazon.awssdk:arns:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Auth (software.amazon.awssdk:auth:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: AWS Core (software.amazon.awssdk:aws-core:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Core :: Protocols :: AWS Query Protocol (software.amazon.awssdk:aws-query-protocol:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Core :: Protocols :: AWS Xml Protocol (software.amazon.awssdk:aws-xml-protocol:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Checksums (software.amazon.awssdk:checksums:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Checksums SPI (software.amazon.awssdk:checksums-spi:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: AWS CRT Core (software.amazon.awssdk:crt-core:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Endpoints SPI (software.amazon.awssdk:endpoints-spi:2.38.8 - https://aws.amazon.com/sdkforjava/core/endpoints-spi)
+ * AWS Java SDK :: HTTP Auth (software.amazon.awssdk:http-auth:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: HTTP Auth AWS (software.amazon.awssdk:http-auth-aws:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: HTTP Auth Event Stream (software.amazon.awssdk:http-auth-aws-eventstream:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: HTTP Auth SPI (software.amazon.awssdk:http-auth-spi:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: HTTP Client Interface (software.amazon.awssdk:http-client-spi:2.38.8 - https://aws.amazon.com/sdkforjava/http-client-spi)
+ * AWS Java SDK :: Identity SPI (software.amazon.awssdk:identity-spi:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Core :: Protocols :: Json Utils (software.amazon.awssdk:json-utils:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Metrics SPI (software.amazon.awssdk:metrics-spi:2.38.8 - https://aws.amazon.com/sdkforjava/core/metrics-spi)
+ * AWS Java SDK :: Profiles (software.amazon.awssdk:profiles:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Core :: Protocols :: Protocol Core (software.amazon.awssdk:protocol-core:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Regions (software.amazon.awssdk:regions:2.38.8 - https://aws.amazon.com/sdkforjava/core/regions)
+ * AWS Java SDK :: Retries (software.amazon.awssdk:retries:2.38.8 - https://aws.amazon.com/sdkforjava/core/retries)
+ * AWS Java SDK :: Retries API (software.amazon.awssdk:retries-spi:2.38.8 - https://aws.amazon.com/sdkforjava/core/retries-spi)
+ * AWS Java SDK :: Services :: Amazon S3 (software.amazon.awssdk:s3:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: SDK Core (software.amazon.awssdk:sdk-core:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Third Party :: Jackson-core (software.amazon.awssdk:third-party-jackson-core:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * AWS Java SDK :: Utilities (software.amazon.awssdk:utils:2.38.8 - https://aws.amazon.com/sdkforjava/utils)
+ * AWS Java SDK :: Utils Lite (software.amazon.awssdk:utils-lite:2.38.8 - https://aws.amazon.com/sdkforjava)
+ * software.amazon.awssdk.crt:aws-crt (software.amazon.awssdk.crt:aws-crt:0.39.4 - https://github.com/awslabs/aws-crt-java)
+ * AWS Event Stream (software.amazon.eventstream:eventstream:1.0.1 - https://github.com/awslabs/aws-eventstream-java)
* Xerces2-j (xerces:xercesImpl:2.12.2 - https://xerces.apache.org/xerces2-j/)
BSD License:
@@ -480,8 +492,8 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* janino (org.codehaus.janino:janino:3.1.8 - http://janino-compiler.github.io/janino/)
* Stax2 API (org.codehaus.woodstox:stax2-api:4.2.1 - http://github.com/FasterXML/stax2-api)
* Hamcrest Date (org.exparity:hamcrest-date:2.0.8 - https://github.com/exparity/hamcrest-date)
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
* Hamcrest (org.hamcrest:hamcrest:2.2 - http://hamcrest.org/JavaHamcrest/)
* Hamcrest Core (org.hamcrest:hamcrest-core:2.2 - http://hamcrest.org/JavaHamcrest/)
@@ -491,23 +503,19 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* asm-analysis (org.ow2.asm:asm-analysis:8.0.1 - http://asm.ow2.io/)
* asm-commons (org.ow2.asm:asm-commons:8.0.1 - http://asm.ow2.io/)
* asm-tree (org.ow2.asm:asm-tree:8.0.1 - http://asm.ow2.io/)
- * PostgreSQL JDBC Driver (org.postgresql:postgresql:42.7.7 - https://jdbc.postgresql.org)
+ * PostgreSQL JDBC Driver (org.postgresql:postgresql:42.7.8 - https://jdbc.postgresql.org)
* Reflections (org.reflections:reflections:0.9.12 - http://github.com/ronmamo/reflections)
* JMatIO (org.tallison:jmatio:1.5 - https://github.com/tballison/jmatio)
* XZ for Java (org.tukaani:xz:1.10 - https://tukaani.org/xz/java.html)
* XMLUnit for Java (xmlunit:xmlunit:1.3 - http://xmlunit.sourceforge.net/)
- CC0:
-
- * reactive-streams (org.reactivestreams:reactive-streams:1.0.2 - http://www.reactive-streams.org/)
-
Common Development and Distribution License (CDDL):
* JavaMail API (no providers) (com.sun.mail:mailapi:1.6.2 - http://javaee.github.io/javamail/mailapi)
* Old JAXB Core (com.sun.xml.bind:jaxb-core:2.3.0.1 - http://jaxb.java.net/jaxb-bundles/jaxb-core)
* Old JAXB Runtime (com.sun.xml.bind:jaxb-impl:2.3.1 - http://jaxb.java.net/jaxb-bundles/jaxb-impl)
* Jakarta Annotations API (jakarta.annotation:jakarta.annotation-api:2.1.1 - https://projects.eclipse.org/projects/ee4j.ca)
- * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.3 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api)
+ * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.5 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api)
* Jakarta Servlet (jakarta.servlet:jakarta.servlet-api:6.1.0 - https://projects.eclipse.org/projects/ee4j.servlet)
* jakarta.transaction API (jakarta.transaction:jakarta.transaction-api:2.0.1 - https://projects.eclipse.org/projects/ee4j.jta)
* JavaBeans Activation Framework API jar (javax.activation:javax.activation-api:1.2.0 - http://java.net/all/javax.activation-api/)
@@ -516,14 +524,14 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* javax.transaction API (javax.transaction:javax.transaction-api:1.3 - http://jta-spec.java.net)
* jaxb-api (javax.xml.bind:jaxb-api:2.3.1 - https://github.com/javaee/jaxb-spec/jaxb-api)
* JHighlight (org.codelibs:jhighlight:1.1.0 - https://github.com/codelibs/jhighlight)
- * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.3 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail)
+ * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.5 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail)
* HK2 API module (org.glassfish.hk2:hk2-api:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-api)
* ServiceLocator Default Implementation (org.glassfish.hk2:hk2-locator:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-locator)
* HK2 Implementation Utilities (org.glassfish.hk2:hk2-utils:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-utils)
* OSGi resource locator (org.glassfish.hk2:osgi-resource-locator:1.0.3 - https://projects.eclipse.org/projects/ee4j/osgi-resource-locator)
* aopalliance version 1.0 repackaged as a module (org.glassfish.hk2.external:aopalliance-repackaged:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/external/aopalliance-repackaged)
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
Cordra (Version 2) License Agreement:
@@ -538,17 +546,17 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
Eclipse Distribution License, Version 1.0:
* istack common utility code runtime (com.sun.istack:istack-commons-runtime:4.1.2 - https://projects.eclipse.org/projects/ee4j/istack-commons/istack-commons-runtime)
- * Jakarta Activation API (jakarta.activation:jakarta.activation-api:2.1.3 - https://github.com/jakartaee/jaf-api)
- * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.3 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api)
+ * Jakarta Activation API (jakarta.activation:jakarta.activation-api:2.1.4 - https://github.com/jakartaee/jaf-api)
+ * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.5 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api)
* Jakarta Persistence API (jakarta.persistence:jakarta.persistence-api:3.1.0 - https://github.com/eclipse-ee4j/jpa-api)
- * Jakarta XML Binding API (jakarta.xml.bind:jakarta.xml.bind-api:4.0.2 - https://github.com/jakartaee/jaxb-api/jakarta.xml.bind-api)
- * Angus Activation Registries (org.eclipse.angus:angus-activation:2.0.2 - https://github.com/eclipse-ee4j/angus-activation/angus-activation)
- * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.3 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail)
- * JAXB Core (org.glassfish.jaxb:jaxb-core:4.0.5 - https://eclipse-ee4j.github.io/jaxb-ri/)
- * JAXB Runtime (org.glassfish.jaxb:jaxb-runtime:4.0.5 - https://eclipse-ee4j.github.io/jaxb-ri/)
- * TXW2 Runtime (org.glassfish.jaxb:txw2:4.0.5 - https://eclipse-ee4j.github.io/jaxb-ri/)
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * Jakarta XML Binding API (jakarta.xml.bind:jakarta.xml.bind-api:4.0.4 - https://github.com/jakartaee/jaxb-api/jakarta.xml.bind-api)
+ * Angus Activation Registries (org.eclipse.angus:angus-activation:2.0.3 - https://github.com/eclipse-ee4j/angus-activation/angus-activation)
+ * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.5 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail)
+ * JAXB Core (org.glassfish.jaxb:jaxb-core:4.0.6 - https://eclipse-ee4j.github.io/jaxb-ri/)
+ * JAXB Runtime (org.glassfish.jaxb:jaxb-runtime:4.0.6 - https://eclipse-ee4j.github.io/jaxb-ri/)
+ * TXW2 Runtime (org.glassfish.jaxb:txw2:4.0.6 - https://eclipse-ee4j.github.io/jaxb-ri/)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
* MIME streaming extension (org.jvnet.mimepull:mimepull:1.9.15 - https://github.com/eclipse-ee4j/metro-mimepull)
* org.locationtech.jts:jts-core (org.locationtech.jts:jts-core:1.19.0 - https://www.locationtech.org/projects/technology.jts/jts-modules/jts-core)
@@ -557,16 +565,16 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
Eclipse Public License:
* System Rules (com.github.stefanbirkner:system-rules:1.19.0 - http://stefanbirkner.github.io/system-rules/)
- * H2 Database Engine (com.h2database:h2:2.3.232 - https://h2database.com)
+ * H2 Database Engine (com.h2database:h2:2.4.240 - https://h2database.com)
* Jakarta Annotations API (jakarta.annotation:jakarta.annotation-api:2.1.1 - https://projects.eclipse.org/projects/ee4j.ca)
- * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.3 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api)
+ * Jakarta Mail API (jakarta.mail:jakarta.mail-api:2.1.5 - https://projects.eclipse.org/projects/ee4j/jakarta.mail-api)
* Jakarta Persistence API (jakarta.persistence:jakarta.persistence-api:3.1.0 - https://github.com/eclipse-ee4j/jpa-api)
* Jakarta Servlet (jakarta.servlet:jakarta.servlet-api:6.1.0 - https://projects.eclipse.org/projects/ee4j.servlet)
* jakarta.transaction API (jakarta.transaction:jakarta.transaction-api:2.0.1 - https://projects.eclipse.org/projects/ee4j.jta)
* Jakarta RESTful WS API (jakarta.ws.rs:jakarta.ws.rs-api:3.1.0 - https://github.com/eclipse-ee4j/jaxrs-api)
* JUnit (junit:junit:4.13.2 - http://junit.org)
- * AspectJ Weaver (org.aspectj:aspectjweaver:1.9.24 - https://www.eclipse.org/aspectj/)
- * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.3 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail)
+ * AspectJ Weaver (org.aspectj:aspectjweaver:1.9.25 - https://www.eclipse.org/aspectj/)
+ * Angus Mail default provider (org.eclipse.angus:jakarta.mail:2.0.5 - http://eclipse-ee4j.github.io/angus-mail/jakarta.mail)
* Jetty :: Apache JSP Implementation (org.eclipse.jetty:apache-jsp:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Apache :: JSTL module (org.eclipse.jetty:apache-jstl:9.4.15.v20190215 - http://tomcat.apache.org/taglibs/standard/)
* Jetty :: ALPN :: Client (org.eclipse.jetty:jetty-alpn-client:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-client)
@@ -579,27 +587,27 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Jetty :: Asynchronous HTTP Client (org.eclipse.jetty:jetty-client:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-client)
* Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-continuation)
- * Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.57.v20241219 - https://jetty.org/jetty-deploy/)
- * Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.57.v20241219 - https://jetty.org/jetty-http/)
- * Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.57.v20241219 - https://jetty.org/jetty-io/)
+ * Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.58.v20250814 - https://jetty.org/jetty-deploy/)
+ * Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.58.v20250814 - https://jetty.org/jetty-http/)
+ * Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.58.v20250814 - https://jetty.org/jetty-io/)
* Jetty :: JMX Management (org.eclipse.jetty:jetty-jmx:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-jmx)
* Jetty :: JNDI Naming (org.eclipse.jetty:jetty-jndi:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Jetty :: Plus (org.eclipse.jetty:jetty-plus:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Jetty :: Rewrite Handler (org.eclipse.jetty:jetty-rewrite:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-rewrite)
* Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-security)
- * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.57.v20241219 - https://jetty.org/jetty-security/)
- * Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.57.v20241219 - https://jetty.org/jetty-server/)
- * Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.57.v20241219 - https://jetty.org/jetty-servlet/)
+ * Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.58.v20250814 - https://jetty.org/jetty-security/)
+ * Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.58.v20250814 - https://jetty.org/jetty-server/)
+ * Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.58.v20250814 - https://jetty.org/jetty-servlet/)
* Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.15.v20190215 - http://www.eclipse.org/jetty)
* Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-servlets)
- * Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.57.v20241219 - https://jetty.org/jetty-util/)
- * Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.57.v20241219 - https://jetty.org/jetty-util-ajax/)
- * Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.57.v20241219 - https://jetty.org/jetty-webapp/)
+ * Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.58.v20250814 - https://jetty.org/jetty-util/)
+ * Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.58.v20250814 - https://jetty.org/jetty-util-ajax/)
+ * Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.58.v20250814 - https://jetty.org/jetty-webapp/)
* Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.53.v20231009 - https://eclipse.org/jetty/jetty-xml)
- * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.57.v20241219 - https://jetty.org/jetty-xml/)
+ * Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.58.v20250814 - https://jetty.org/jetty-xml/)
* Jetty :: ALPN :: API (org.eclipse.jetty.alpn:alpn-api:1.1.3.v20160715 - http://www.eclipse.org/jetty/alpn-api)
* Jetty :: HTTP2 :: Client (org.eclipse.jetty.http2:http2-client:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-client)
- * Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.57.v20241219 - https://jetty.org/http2-parent/http2-common/)
+ * Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.58.v20250814 - https://jetty.org/http2-parent/http2-common/)
* Jetty :: HTTP2 :: HPACK (org.eclipse.jetty.http2:http2-hpack:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-hpack)
* Jetty :: HTTP2 :: HTTP Client Transport (org.eclipse.jetty.http2:http2-http-client-transport:9.4.53.v20231009 - https://eclipse.org/jetty/http2-parent/http2-http-client-transport)
* Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.15.v20190215 - https://eclipse.org/jetty/http2-parent/http2-server)
@@ -611,13 +619,10 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* HK2 Implementation Utilities (org.glassfish.hk2:hk2-utils:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-utils)
* OSGi resource locator (org.glassfish.hk2:osgi-resource-locator:1.0.3 - https://projects.eclipse.org/projects/ee4j/osgi-resource-locator)
* aopalliance version 1.0 repackaged as a module (org.glassfish.hk2.external:aopalliance-repackaged:3.0.6 - https://github.com/eclipse-ee4j/glassfish-hk2/external/aopalliance-repackaged)
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
- * JUnit Platform Commons (org.junit.platform:junit-platform-commons:1.11.4 - https://junit.org/junit5/)
- * JUnit Platform Engine API (org.junit.platform:junit-platform-engine:1.11.4 - https://junit.org/junit5/)
- * JUnit Vintage Engine (org.junit.vintage:junit-vintage-engine:5.11.4 - https://junit.org/junit5/)
* org.locationtech.jts:jts-core (org.locationtech.jts:jts-core:1.19.0 - https://www.locationtech.org/projects/technology.jts/jts-modules/jts-core)
* org.locationtech.jts.io:jts-io-common (org.locationtech.jts.io:jts-io-common:1.19.0 - https://www.locationtech.org/projects/technology.jts/jts-modules/jts-io/jts-io-common)
@@ -642,9 +647,9 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* FindBugs-Annotations (com.google.code.findbugs:annotations:3.0.1u2 - http://findbugs.sourceforge.net/)
* JHighlight (org.codelibs:jhighlight:1.1.0 - https://github.com/codelibs/jhighlight)
* Hibernate Commons Annotations (org.hibernate.common:hibernate-commons-annotations:6.0.6.Final - http://hibernate.org)
- * Hibernate ORM - hibernate-core (org.hibernate.orm:hibernate-core:6.4.8.Final - https://hibernate.org/orm)
- * Hibernate ORM - hibernate-jcache (org.hibernate.orm:hibernate-jcache:6.4.8.Final - https://hibernate.org/orm)
- * Hibernate ORM - hibernate-jpamodelgen (org.hibernate.orm:hibernate-jpamodelgen:6.4.8.Final - https://hibernate.org/orm)
+ * Hibernate ORM - hibernate-core (org.hibernate.orm:hibernate-core:6.4.10.Final - https://hibernate.org/orm)
+ * Hibernate ORM - hibernate-jcache (org.hibernate.orm:hibernate-jcache:6.4.10.Final - https://hibernate.org/orm)
+ * Hibernate ORM - hibernate-jpamodelgen (org.hibernate.orm:hibernate-jpamodelgen:6.4.10.Final - https://hibernate.org/orm)
* im4java (org.im4java:im4java:1.4.0 - http://sourceforge.net/projects/im4java/)
* Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/)
* XOM (xom:xom:1.3.9 - https://xom.nu)
@@ -661,28 +666,33 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* Simple Magic (com.j256.simplemagic:simplemagic:1.17 - https://256stuff.com/sources/simplemagic/)
+ LGPL-2.1-or-later:
+
+ * Java Native Access (net.java.dev.jna:jna:5.13.0 - https://github.com/java-native-access/jna)
+
MIT License:
* dexx (com.github.andrewoma.dexx:collection:0.7 - https://github.com/andrewoma/dexx)
- * better-files (com.github.pathikrit:better-files_2.13:3.9.1 - https://github.com/pathikrit/better-files)
* Java SemVer (com.github.zafarkhaja:java-semver:0.9.0 - https://github.com/zafarkhaja/jsemver)
* dd-plist (com.googlecode.plist:dd-plist:1.28 - http://www.github.com/3breadt/dd-plist)
* DigitalCollections: IIIF API Library (de.digitalcollections.iiif:iiif-apis:0.3.11 - https://github.com/dbmdz/iiif-apis)
- * s3mock (io.findify:s3mock_2.13:0.2.6 - https://github.com/findify/s3mock)
* ClassGraph (io.github.classgraph:classgraph:4.8.165 - https://github.com/classgraph/classgraph)
* JOpt Simple (net.sf.jopt-simple:jopt-simple:5.0.4 - http://jopt-simple.github.io/jopt-simple)
- * Bouncy Castle JavaMail S/MIME APIs (org.bouncycastle:bcmail-jdk18on:1.80 - https://www.bouncycastle.org/download/bouncy-castle-java/)
- * Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk18on:1.81 - https://www.bouncycastle.org/download/bouncy-castle-java/)
- * Bouncy Castle Provider (org.bouncycastle:bcprov-jdk18on:1.81 - https://www.bouncycastle.org/download/bouncy-castle-java/)
- * Bouncy Castle ASN.1 Extension and Utility APIs (org.bouncycastle:bcutil-jdk18on:1.81 - https://www.bouncycastle.org/download/bouncy-castle-java/)
+ * Bouncy Castle JavaMail Jakarta S/MIME APIs (org.bouncycastle:bcjmail-jdk18on:1.81 - https://www.bouncycastle.org/download/bouncy-castle-java/)
+ * Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk18on:1.82 - https://www.bouncycastle.org/download/bouncy-castle-java/)
+ * Bouncy Castle Provider (org.bouncycastle:bcprov-jdk18on:1.82 - https://www.bouncycastle.org/download/bouncy-castle-java/)
+ * Bouncy Castle ASN.1 Extension and Utility APIs (org.bouncycastle:bcutil-jdk18on:1.82 - https://www.bouncycastle.org/download/bouncy-castle-java/)
* org.brotli:dec (org.brotli:dec:0.1.2 - http://brotli.org/dec)
- * Checker Qual (org.checkerframework:checker-qual:3.49.5 - https://checkerframework.org/)
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * Checker Qual (org.checkerframework:checker-qual:3.52.0 - https://checkerframework.org/)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
+ * jsoup Java HTML Parser (org.jsoup:jsoup:1.21.2 - https://jsoup.org/)
* mockito-core (org.mockito:mockito-core:3.12.4 - https://github.com/mockito/mockito)
* mockito-inline (org.mockito:mockito-inline:3.12.4 - https://github.com/mockito/mockito)
+ * Duct Tape (org.rnorth.duct-tape:duct-tape:1.0.8 - https://github.com/rnorth/duct-tape)
* SLF4J API Module (org.slf4j:slf4j-api:2.0.17 - http://www.slf4j.org)
+ * Testcontainers Core (org.testcontainers:testcontainers:1.21.3 - https://java.testcontainers.org)
* HAL Browser (org.webjars:hal-browser:ad9b865 - http://webjars.org)
* toastr (org.webjars.bowergithub.codeseven:toastr:2.1.4 - http://webjars.org)
* backbone (org.webjars.bowergithub.jashkenas:backbone:1.4.1 - https://www.webjars.org)
@@ -690,28 +700,36 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
* jquery (org.webjars.bowergithub.jquery:jquery-dist:3.7.1 - https://www.webjars.org)
* urijs (org.webjars.bowergithub.medialize:uri.js:1.19.11 - https://www.webjars.org)
* bootstrap (org.webjars.bowergithub.twbs:bootstrap:4.6.2 - https://www.webjars.org)
- * core-js (org.webjars.npm:core-js:3.42.0 - https://www.webjars.org)
+ * core-js (org.webjars.npm:core-js:3.46.0 - https://www.webjars.org)
* @json-editor/json-editor (org.webjars.npm:json-editor__json-editor:2.15.2 - https://www.webjars.org)
+ MIT-0:
+
+ * reactive-streams (org.reactivestreams:reactive-streams:1.0.4 - http://www.reactive-streams.org/)
+
Mozilla Public License:
* juniversalchardet (com.github.albfernandez:juniversalchardet:2.5.0 - https://github.com/albfernandez/juniversalchardet)
- * H2 Database Engine (com.h2database:h2:2.3.232 - https://h2database.com)
+ * H2 Database Engine (com.h2database:h2:2.4.240 - https://h2database.com)
* Saxon-HE (net.sf.saxon:Saxon-HE:9.9.1-8 - http://www.saxonica.com/)
* Javassist (org.javassist:javassist:3.30.2-GA - https://www.javassist.org/)
* Mozilla Rhino (org.mozilla:rhino:1.7.7.2 - https://developer.mozilla.org/en/Rhino)
Public Domain:
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-core-common (org.glassfish.jersey.core:jersey-common:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
* HdrHistogram (org.hdrhistogram:HdrHistogram:2.2.2 - http://hdrhistogram.github.io/HdrHistogram/)
* JSON in Java (org.json:json:20231013 - https://github.com/douglascrockford/JSON-java)
* LatencyUtils (org.latencyutils:LatencyUtils:2.0.3 - http://latencyutils.github.io/LatencyUtils/)
* Reflections (org.reflections:reflections:0.9.12 - http://github.com/ronmamo/reflections)
+ The Apache Software License, version 2.0:
+
+ * picocli (info.picocli:picocli:4.7.6 - https://picocli.info)
+
UnRar License:
* Java Unrar (com.github.junrar:junrar:7.5.5 - https://github.com/junrar/junrar)
@@ -722,12 +740,12 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
W3C license:
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
jQuery license:
- * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
- * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.10 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
+ * jersey-core-client (org.glassfish.jersey.core:jersey-client:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
+ * jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:3.1.11 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
* jersey-media-multipart (org.glassfish.jersey.media:jersey-media-multipart:3.1.3 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-media-multipart)
diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml
index 882f0b037c73..6e061919362b 100644
--- a/dspace-api/pom.xml
+++ b/dspace-api/pom.xml
@@ -12,7 +12,7 @@
org.dspacedspace-parent
- 8.2
+ 8.3..
@@ -99,20 +99,6 @@
-
- org.codehaus.mojo
- build-helper-maven-plugin
- 3.6.1
-
-
- validate
-
- maven-version
-
-
-
-
-
org.codehaus.mojobuildnumber-maven-plugin
@@ -653,6 +639,7 @@
1.1.1
+
com.google.guavaguava
@@ -729,9 +716,25 @@
- com.amazonaws
- aws-java-sdk-s3
- 1.12.785
+ software.amazon.awssdk
+ s3
+ 2.38.8
+
+
+ software.amazon.awssdk
+ netty-nio-client
+
+
+ software.amazon.awssdk
+ apache-client
+
+
+
+
+
+ software.amazon.awssdk.crt
+ aws-crt
+ 0.39.4
@@ -785,14 +788,14 @@
org.xmlunitxmlunit-core
- 2.10.2
+ 2.11.0testorg.apache.bcelbcel
- 6.10.0
+ 6.11.0test
@@ -843,22 +846,12 @@
-
+
- io.findify
- s3mock_2.13
- 0.2.6
- test
-
-
- com.amazonawsl
- aws-java-sdk-s3
-
-
- com.amazonaws
- aws-java-sdk-s3
-
-
+ com.adobe.testing
+ s3mock-testcontainers
+ 4.10.0
+ test
diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java
index 30f68efaf3cb..59e75059c94f 100644
--- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java
+++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java
@@ -18,6 +18,7 @@
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
@@ -154,7 +155,7 @@ public void internalRun() throws Exception {
}
ObjectMapper mapper = new ObjectMapper();
- mapper.setTimeZone(TimeZone.getTimeZone("UTC"));
+ mapper.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
BulkAccessControlInput accessControl;
context = new Context(Context.Mode.BATCH_EDIT);
setEPerson(context);
diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java
index e4bbe335d63e..689df4701a96 100644
--- a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java
+++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExportSearch.java
@@ -14,6 +14,8 @@
import java.util.List;
import java.util.UUID;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.DefaultParser.Builder;
import org.apache.commons.cli.ParseException;
import org.dspace.content.Item;
import org.dspace.content.MetadataDSpaceCsvExportServiceImpl;
@@ -167,4 +169,14 @@ public IndexableObject resolveScope(Context context, String id) throws SQLExcept
}
return scopeObj;
}
+
+ @Override
+ protected StepResult parse(String[] args) throws ParseException {
+ commandLine = new DefaultParser().parse(getScriptConfiguration().getOptions(), args);
+ Builder builder = new DefaultParser().builder();
+ builder.setStripLeadingAndTrailingQuotes(false);
+ commandLine = builder.build().parse(getScriptConfiguration().getOptions(), args);
+ setup();
+ return StepResult.Continue;
+ }
}
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 e8cf42b47c1b..b12abbc46eb9 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
@@ -494,7 +494,7 @@ public List runImport(Context c, boolean change,
// Check it has an owning collection
List collections = line.get("collection");
- if (collections == null) {
+ if (collections == null || collections.isEmpty()) {
throw new MetadataImportException(
"New items must have a 'collection' assigned in the form of a handle");
}
diff --git a/dspace-api/src/main/java/org/dspace/app/checker/ChecksumChecker.java b/dspace-api/src/main/java/org/dspace/app/checker/ChecksumChecker.java
index ec024c345263..160d23e32204 100644
--- a/dspace-api/src/main/java/org/dspace/app/checker/ChecksumChecker.java
+++ b/dspace-api/src/main/java/org/dspace/app/checker/ChecksumChecker.java
@@ -98,7 +98,7 @@ public static void main(String[] args) throws SQLException {
options.addOption("h", "help", false, "Help");
options.addOption("d", "duration", true, "Checking duration");
options.addOption("c", "count", true, "Check count");
- options.addOption("a", "handle", true, "Specify a handle to check");
+ options.addOption("i", "handle", true, "Specify a handle to check");
options.addOption("v", "verbose", false, "Report all processing");
Option option;
@@ -106,7 +106,7 @@ public static void main(String[] args) throws SQLException {
option = Option.builder("b")
.longOpt("bitstream-ids")
.hasArgs()
- .desc("Space separated list of bitstream ids")
+ .desc("Space separated list of bitstream UUIDs")
.build();
options.addOption(option);
@@ -132,6 +132,17 @@ public static void main(String[] args) throws SQLException {
try {
context = new Context();
+ int mutuallyExclusiveOpts = 0;
+ for (char c : new char[]{'l', 'L', 'd', 'b', 'i','c'}) {
+ if (line.hasOption(c)) {
+ mutuallyExclusiveOpts++;
+ }
+ }
+ if (mutuallyExclusiveOpts > 1) {
+ System.err.println("Please use only one option of -l, -L, -d, -b, -i, or -c");
+ LOG.error("Please use only one option of -l, -L, -d, -b, -i, or -c");
+ System.exit(1);
+ }
// Prune stage
if (line.hasOption('p')) {
@@ -169,13 +180,13 @@ public static void main(String[] args) throws SQLException {
bitstreams.add(bitstreamService.find(context, UUID.fromString(ids[i])));
} catch (NumberFormatException nfe) {
System.err.println("The following argument: " + ids[i]
- + " is not an integer");
+ + " is not an UUID");
System.exit(0);
}
}
dispatcher = new IteratorDispatcher(bitstreams.iterator());
- } else if (line.hasOption('a')) {
- dispatcher = new HandleDispatcher(context, line.getOptionValue('a'));
+ } else if (line.hasOption('i')) {
+ dispatcher = new HandleDispatcher(context, line.getOptionValue('i'));
} else if (line.hasOption('d')) {
// run checker process for specified duration
try {
@@ -185,6 +196,8 @@ public static void main(String[] args) throws SQLException {
+ Utils.parseDuration(line
.getOptionValue('d'))));
} catch (Exception e) {
+ System.err.println("Couldn't parse " + line.getOptionValue('d')
+ + " as a duration");
LOG.fatal("Couldn't parse " + line.getOptionValue('d')
+ " as a duration: ", e);
System.exit(0);
@@ -228,18 +241,24 @@ public static void main(String[] args) throws SQLException {
private static void printHelp(Options options) {
HelpFormatter myhelp = new HelpFormatter();
- myhelp.printHelp("Checksum Checker\n", options);
- System.out.println("\nSpecify a duration for checker process, using s(seconds),"
- + "m(minutes), or h(hours): ChecksumChecker -d 30s"
- + " OR ChecksumChecker -d 30m"
- + " OR ChecksumChecker -d 2h");
- System.out.println("\nSpecify bitstream IDs: ChecksumChecker -b 13 15 17 20");
- System.out.println("\nLoop once through all bitstreams: "
- + "ChecksumChecker -l");
- System.out.println("\nLoop continuously through all bitstreams: ChecksumChecker -L");
- System.out.println("\nCheck a defined number of bitstreams: ChecksumChecker -c 10");
- System.out.println("\nReport all processing (verbose)(default reports only errors): ChecksumChecker -v");
- System.out.println("\nDefault (no arguments) is equivalent to '-c 1'");
+ myhelp.printHelp("checker\n", options);
+ System.out.println("\nChecksum Checker usage examples:");
+ System.out.println("\nThe following options are mutually exclusive:");
+ System.out.println(" - Specify a duration for checker process, using s(seconds),"
+ + "m(minutes), or h(hours): checker -d 30s"
+ + " OR checker -d 30m"
+ + " OR checker -d 2h");
+ System.out.println(" - Specify bitstream UUIDs: checker -b 550e8400-e29b-41d4-a716-446655440000"
+ + " f3f2e850-b5d4-11ef-ac7e-96584d5248b2");
+ System.out.println(" - Specify handle: checker -i 12345/100");
+ System.out.println(" - Loop once through all bitstreams: "
+ + "checker -l");
+ System.out.println(" - Loop continuously through all bitstreams: checker -L");
+ System.out.println(" - Check a defined number of bitstreams: checker -c 10");
+ System.out.println("\nThe following options can be used in combination with others above:");
+ System.out.println(" - Report all processing to checker.log (by default logs only errors): checker -v");
+ System.out.println(" - Prune old results from the database: checker -p");
+ System.out.println("\nDefault (no arguments) is equivalent to 'checker -c 1'\n");
System.exit(0);
}
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 9eaabc20e862..d50b44fd8d4c 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
@@ -352,7 +352,7 @@ protected void writeHandle(Context c, Item i, File destDir)
/**
* Create the 'collections' file. List handles of all Collections which
- * contain this Item. The "owning" Collection is listed first.
+ * contain this Item. The "owning" Collection is listed first.
*
* @param item list collections holding this Item.
* @param destDir write the file here.
@@ -363,12 +363,14 @@ protected void writeCollections(Item item, File destDir)
File outFile = new File(destDir, "collections");
if (outFile.createNewFile()) {
try (PrintWriter out = new PrintWriter(new FileWriter(outFile))) {
- String ownerHandle = item.getOwningCollection().getHandle();
- out.println(ownerHandle);
+ Collection owningCollection = item.getOwningCollection();
+ // The owning collection is null for workspace and workflow items
+ if (owningCollection != null) {
+ out.println(owningCollection.getHandle());
+ }
for (Collection collection : item.getCollections()) {
- String collectionHandle = collection.getHandle();
- if (!collectionHandle.equals(ownerHandle)) {
- out.println(collectionHandle);
+ if (!collection.equals(owningCollection)) {
+ out.println(collection.getHandle());
}
}
}
diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImport.java b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImport.java
index b32de11f7a7f..33487bc8e35a 100644
--- a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImport.java
+++ b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImport.java
@@ -22,6 +22,7 @@
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tika.Tika;
import org.dspace.app.itemimport.factory.ItemImportServiceFactory;
@@ -333,33 +334,38 @@ protected void process(Context context, ItemImportService itemImportService,
protected void readZip(Context context, ItemImportService itemImportService) throws Exception {
Optional optionalFileStream = Optional.empty();
Optional validationFileStream = Optional.empty();
- if (!remoteUrl) {
- // manage zip via upload
- optionalFileStream = handler.getFileStream(context, zipfilename);
- validationFileStream = handler.getFileStream(context, zipfilename);
- } else {
- // manage zip via remote url
- optionalFileStream = Optional.ofNullable(new URL(zipfilename).openStream());
- validationFileStream = Optional.ofNullable(new URL(zipfilename).openStream());
- }
+ try {
+ if (!remoteUrl) {
+ // manage zip via upload
+ optionalFileStream = handler.getFileStream(context, zipfilename);
+ validationFileStream = handler.getFileStream(context, zipfilename);
+ } else {
+ // manage zip via remote url
+ optionalFileStream = Optional.ofNullable(new URL(zipfilename).openStream());
+ validationFileStream = Optional.ofNullable(new URL(zipfilename).openStream());
+ }
- if (validationFileStream.isPresent()) {
- // validate zip file
if (validationFileStream.isPresent()) {
- validateZip(validationFileStream.get());
+ // validate zip file
+ if (validationFileStream.isPresent()) {
+ validateZip(validationFileStream.get());
+ }
+
+ workFile = new File(itemImportService.getTempWorkDir() + File.separator
+ + zipfilename + "-" + context.getCurrentUser().getID());
+ FileUtils.copyInputStreamToFile(optionalFileStream.get(), workFile);
+ } else {
+ throw new IllegalArgumentException(
+ "Error reading file, the file couldn't be found for filename: " + zipfilename);
}
- workFile = new File(itemImportService.getTempWorkDir() + File.separator
- + zipfilename + "-" + context.getCurrentUser().getID());
- FileUtils.copyInputStreamToFile(optionalFileStream.get(), workFile);
- } else {
- throw new IllegalArgumentException(
- "Error reading file, the file couldn't be found for filename: " + zipfilename);
+ workDir = new File(itemImportService.getTempWorkDir() + File.separator + TEMP_DIR
+ + File.separator + context.getCurrentUser().getID());
+ sourcedir = itemImportService.unzip(workFile, workDir.getAbsolutePath());
+ } finally {
+ optionalFileStream.ifPresent(IOUtils::closeQuietly);
+ validationFileStream.ifPresent(IOUtils::closeQuietly);
}
-
- workDir = new File(itemImportService.getTempWorkDir() + File.separator + TEMP_DIR
- + File.separator + context.getCurrentUser().getID());
- sourcedir = itemImportService.unzip(workFile, workDir.getAbsolutePath());
}
/**
diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportCLI.java b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportCLI.java
index 98d2469b7155..bd29aa97fe48 100644
--- a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportCLI.java
+++ b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportCLI.java
@@ -17,6 +17,7 @@
import java.util.UUID;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.itemimport.service.ItemImportService;
import org.dspace.content.Collection;
@@ -111,7 +112,11 @@ protected void readZip(Context context, ItemImportService itemImportService) thr
// validate zip file
InputStream validationFileStream = new FileInputStream(myZipFile);
- validateZip(validationFileStream);
+ try {
+ validateZip(validationFileStream);
+ } finally {
+ IOUtils.closeQuietly(validationFileStream);
+ }
workDir = new File(itemImportService.getTempWorkDir() + File.separator + TEMP_DIR
+ File.separator + context.getCurrentUser().getID());
@@ -120,22 +125,28 @@ protected void readZip(Context context, ItemImportService itemImportService) thr
} else {
// manage zip via remote url
Optional optionalFileStream = Optional.ofNullable(new URL(zipfilename).openStream());
- if (optionalFileStream.isPresent()) {
- // validate zip file via url
- Optional validationFileStream = Optional.ofNullable(new URL(zipfilename).openStream());
- if (validationFileStream.isPresent()) {
- validateZip(validationFileStream.get());
+ Optional validationFileStream = Optional.ofNullable(new URL(zipfilename).openStream());
+ try {
+ if (optionalFileStream.isPresent()) {
+ // validate zip file via url
+
+ if (validationFileStream.isPresent()) {
+ validateZip(validationFileStream.get());
+ }
+
+ workFile = new File(itemImportService.getTempWorkDir() + File.separator
+ + zipfilename + "-" + context.getCurrentUser().getID());
+ FileUtils.copyInputStreamToFile(optionalFileStream.get(), workFile);
+ workDir = new File(itemImportService.getTempWorkDir() + File.separator + TEMP_DIR
+ + File.separator + context.getCurrentUser().getID());
+ sourcedir = itemImportService.unzip(workFile, workDir.getAbsolutePath());
+ } else {
+ throw new IllegalArgumentException(
+ "Error reading file, the file couldn't be found for filename: " + zipfilename);
}
-
- workFile = new File(itemImportService.getTempWorkDir() + File.separator
- + zipfilename + "-" + context.getCurrentUser().getID());
- FileUtils.copyInputStreamToFile(optionalFileStream.get(), workFile);
- workDir = new File(itemImportService.getTempWorkDir() + File.separator + TEMP_DIR
- + File.separator + context.getCurrentUser().getID());
- sourcedir = itemImportService.unzip(workFile, workDir.getAbsolutePath());
- } else {
- throw new IllegalArgumentException(
- "Error reading file, the file couldn't be found for filename: " + zipfilename);
+ } finally {
+ optionalFileStream.ifPresent(IOUtils::closeQuietly);
+ validationFileStream.ifPresent(IOUtils::closeQuietly);
}
}
}
diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/BrandedPreviewJPEGFilter.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/BrandedPreviewJPEGFilter.java
index 7b082c6c21a4..483e4f5f6ea2 100644
--- a/dspace-api/src/main/java/org/dspace/app/mediafilter/BrandedPreviewJPEGFilter.java
+++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/BrandedPreviewJPEGFilter.java
@@ -7,9 +7,7 @@
*/
package org.dspace.app.mediafilter;
-import java.awt.image.BufferedImage;
import java.io.InputStream;
-import javax.imageio.ImageIO;
import org.dspace.content.Item;
import org.dspace.services.ConfigurationService;
@@ -63,27 +61,20 @@ public String getDescription() {
@Override
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
throws Exception {
- // read in bitstream's image
- BufferedImage buf = ImageIO.read(source);
-
// get config params
ConfigurationService configurationService
= DSpaceServicesFactory.getInstance().getConfigurationService();
- float xmax = (float) configurationService
- .getIntProperty("webui.preview.maxwidth");
- float ymax = (float) configurationService
- .getIntProperty("webui.preview.maxheight");
- boolean blurring = (boolean) configurationService
- .getBooleanProperty("webui.preview.blurring");
- boolean hqscaling = (boolean) configurationService
- .getBooleanProperty("webui.preview.hqscaling");
+ int xmax = configurationService.getIntProperty("webui.preview.maxwidth");
+ int ymax = configurationService.getIntProperty("webui.preview.maxheight");
+ boolean blurring = configurationService.getBooleanProperty("webui.preview.blurring");
+ boolean hqscaling = configurationService.getBooleanProperty("webui.preview.hqscaling");
int brandHeight = configurationService.getIntProperty("webui.preview.brand.height");
String brandFont = configurationService.getProperty("webui.preview.brand.font");
int brandFontPoint = configurationService.getIntProperty("webui.preview.brand.fontpoint");
JPEGFilter jpegFilter = new JPEGFilter();
- return jpegFilter
- .getThumbDim(currentItem, buf, verbose, xmax, ymax, blurring, hqscaling, brandHeight, brandFontPoint,
- brandFont);
+ return jpegFilter.getThumb(
+ currentItem, source, verbose, xmax, ymax, blurring, hqscaling, brandHeight, brandFontPoint, brandFont
+ );
}
}
diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/ImageMagickThumbnailFilter.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/ImageMagickThumbnailFilter.java
index 408982d157e5..7543410a7968 100644
--- a/dspace-api/src/main/java/org/dspace/app/mediafilter/ImageMagickThumbnailFilter.java
+++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/ImageMagickThumbnailFilter.java
@@ -14,7 +14,7 @@
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
-import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.dspace.content.Bitstream;
@@ -153,8 +153,8 @@ public File getImageFile(File f, boolean verbose)
// the CropBox is missing or empty because pdfbox will set it to the
// same size as the MediaBox if it doesn't exist. Also note that we
// only need to check the first page, since that's what we use for
- // generating the thumbnail (PDDocument uses a zero-based index).
- PDPage pdfPage = PDDocument.load(f).getPage(0);
+ // generating the thumbnail (PDPage uses a zero-based index).
+ PDPage pdfPage = Loader.loadPDF(f).getPage(0);
PDRectangle pdfPageMediaBox = pdfPage.getMediaBox();
PDRectangle pdfPageCropBox = pdfPage.getCropBox();
diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java
index 502f71eb5ca8..2ccc2afbb2d2 100644
--- a/dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java
+++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java
@@ -8,19 +8,32 @@
package org.dspace.app.mediafilter;
import java.awt.Color;
+import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
+import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
+import com.drew.imaging.ImageMetadataReader;
+import com.drew.imaging.ImageProcessingException;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.MetadataException;
+import com.drew.metadata.exif.ExifIFD0Directory;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.dspace.content.Item;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
@@ -33,6 +46,8 @@
* @author Jason Sherman jsherman@usao.edu
*/
public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats {
+ private static final Logger log = LogManager.getLogger(JPEGFilter.class);
+
@Override
public String getFilteredName(String oldFilename) {
return oldFilename + ".jpg";
@@ -62,6 +77,115 @@ public String getDescription() {
return "Generated Thumbnail";
}
+ /**
+ * Gets the rotation angle from image's metadata using ImageReader.
+ * This method consumes the InputStream, so you need to be careful to don't reuse the same InputStream after
+ * computing the rotation angle.
+ *
+ * @param buf InputStream of the image file
+ * @return Rotation angle in degrees (0, 90, 180, or 270)
+ */
+ public static int getImageRotationUsingImageReader(InputStream buf) {
+ try {
+ Metadata metadata = ImageMetadataReader.readMetadata(buf);
+ ExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
+ if (directory != null && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
+ return convertRotationToDegrees(directory.getInt(ExifIFD0Directory.TAG_ORIENTATION));
+ }
+ } catch (MetadataException | ImageProcessingException | IOException e) {
+ log.error("Error reading image metadata", e);
+ }
+ return 0;
+ }
+
+ public static int convertRotationToDegrees(int valueNode) {
+ // Common orientation values:
+ // 1 = Normal (0°)
+ // 6 = Rotated 90° CW
+ // 3 = Rotated 180°
+ // 8 = Rotated 270° CW
+ switch (valueNode) {
+ case 6:
+ return 90;
+ case 3:
+ return 180;
+ case 8:
+ return 270;
+ default:
+ return 0;
+ }
+ }
+
+ /**
+ * Rotates an image by the specified angle
+ *
+ * @param image The original image
+ * @param angle The rotation angle in degrees
+ * @return Rotated image
+ */
+ public static BufferedImage rotateImage(BufferedImage image, int angle) {
+ if (angle == 0) {
+ return image;
+ }
+
+ double radians = Math.toRadians(angle);
+ double sin = Math.abs(Math.sin(radians));
+ double cos = Math.abs(Math.cos(radians));
+
+ int newWidth = (int) Math.round(image.getWidth() * cos + image.getHeight() * sin);
+ int newHeight = (int) Math.round(image.getWidth() * sin + image.getHeight() * cos);
+
+ BufferedImage rotated = new BufferedImage(newWidth, newHeight, image.getType());
+ Graphics2D g2d = rotated.createGraphics();
+ AffineTransform at = new AffineTransform();
+
+ at.translate(newWidth / 2, newHeight / 2);
+ at.rotate(radians);
+ at.translate(-image.getWidth() / 2, -image.getHeight() / 2);
+
+ g2d.setTransform(at);
+ g2d.drawImage(image, 0, 0, null);
+ g2d.dispose();
+
+ return rotated;
+ }
+
+ /**
+ * Calculates scaled dimension while maintaining aspect ratio
+ *
+ * @param imgSize Original image dimensions
+ * @param boundary Maximum allowed dimensions
+ * @return New dimensions that fit within boundary while preserving aspect ratio
+ */
+ private Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
+
+ int originalWidth = imgSize.width;
+ int originalHeight = imgSize.height;
+ int boundWidth = boundary.width;
+ int boundHeight = boundary.height;
+ int newWidth = originalWidth;
+ int newHeight = originalHeight;
+
+
+ // First check if we need to scale width
+ if (originalWidth > boundWidth) {
+ // Scale width to fit
+ newWidth = boundWidth;
+ // Scale height to maintain aspect ratio
+ newHeight = (newWidth * originalHeight) / originalWidth;
+ }
+
+ // Then check if we need to scale even with the new height
+ if (newHeight > boundHeight) {
+ // Scale height to fit instead
+ newHeight = boundHeight;
+ newWidth = (newHeight * originalWidth) / originalHeight;
+ }
+
+ return new Dimension(newWidth, newHeight);
+ }
+
+
/**
* @param currentItem item
* @param source source input stream
@@ -72,10 +196,65 @@ public String getDescription() {
@Override
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
throws Exception {
- // read in bitstream's image
- BufferedImage buf = ImageIO.read(source);
+ return getThumb(currentItem, source, verbose);
+ }
- return getThumb(currentItem, buf, verbose);
+ public InputStream getThumb(Item currentItem, InputStream source, boolean verbose)
+ throws Exception {
+ // get config params
+ final ConfigurationService configurationService
+ = DSpaceServicesFactory.getInstance().getConfigurationService();
+ int xmax = configurationService
+ .getIntProperty("thumbnail.maxwidth");
+ int ymax = configurationService
+ .getIntProperty("thumbnail.maxheight");
+ boolean blurring = (boolean) configurationService
+ .getBooleanProperty("thumbnail.blurring");
+ boolean hqscaling = (boolean) configurationService
+ .getBooleanProperty("thumbnail.hqscaling");
+
+ return getThumb(currentItem, source, verbose, xmax, ymax, blurring, hqscaling, 0, 0, null);
+ }
+
+ protected InputStream getThumb(
+ Item currentItem,
+ InputStream source,
+ boolean verbose,
+ int xmax,
+ int ymax,
+ boolean blurring,
+ boolean hqscaling,
+ int brandHeight,
+ int brandFontPoint,
+ String brandFont
+ ) throws Exception {
+
+ File tempFile = File.createTempFile("temp", ".tmp");
+ tempFile.deleteOnExit();
+
+ // Write to temp file
+ try (FileOutputStream fos = new FileOutputStream(tempFile)) {
+ byte[] buffer = new byte[4096];
+ int len;
+ while ((len = source.read(buffer)) != -1) {
+ fos.write(buffer, 0, len);
+ }
+ }
+
+ int rotation = 0;
+ try (FileInputStream fis = new FileInputStream(tempFile)) {
+ rotation = getImageRotationUsingImageReader(fis);
+ }
+
+ try (FileInputStream fis = new FileInputStream(tempFile)) {
+ // read in bitstream's image
+ BufferedImage buf = ImageIO.read(fis);
+
+ return getThumbDim(
+ currentItem, buf, verbose, xmax, ymax, blurring, hqscaling, brandHeight, brandFontPoint, rotation,
+ brandFont
+ );
+ }
}
public InputStream getThumb(Item currentItem, BufferedImage buf, boolean verbose)
@@ -83,25 +262,28 @@ public InputStream getThumb(Item currentItem, BufferedImage buf, boolean verbose
// get config params
final ConfigurationService configurationService
= DSpaceServicesFactory.getInstance().getConfigurationService();
- float xmax = (float) configurationService
+ int xmax = configurationService
.getIntProperty("thumbnail.maxwidth");
- float ymax = (float) configurationService
+ int ymax = configurationService
.getIntProperty("thumbnail.maxheight");
boolean blurring = (boolean) configurationService
.getBooleanProperty("thumbnail.blurring");
boolean hqscaling = (boolean) configurationService
.getBooleanProperty("thumbnail.hqscaling");
- return getThumbDim(currentItem, buf, verbose, xmax, ymax, blurring, hqscaling, 0, 0, null);
+ return getThumbDim(currentItem, buf, verbose, xmax, ymax, blurring, hqscaling, 0, 0, 0, null);
}
- public InputStream getThumbDim(Item currentItem, BufferedImage buf, boolean verbose, float xmax, float ymax,
+ public InputStream getThumbDim(Item currentItem, BufferedImage buf, boolean verbose, int xmax, int ymax,
boolean blurring, boolean hqscaling, int brandHeight, int brandFontPoint,
- String brandFont)
+ int rotation, String brandFont)
throws Exception {
- // now get the image dimensions
- float xsize = (float) buf.getWidth(null);
- float ysize = (float) buf.getHeight(null);
+
+ // Rotate the image if needed
+ BufferedImage correctedImage = rotateImage(buf, rotation);
+
+ int xsize = correctedImage.getWidth();
+ int ysize = correctedImage.getHeight();
// if verbose flag is set, print out dimensions
// to STDOUT
@@ -109,86 +291,63 @@ public InputStream getThumbDim(Item currentItem, BufferedImage buf, boolean verb
System.out.println("original size: " + xsize + "," + ysize);
}
- // scale by x first if needed
- if (xsize > xmax) {
- // calculate scaling factor so that xsize * scale = new size (max)
- float scale_factor = xmax / xsize;
+ // Calculate new dimensions while maintaining aspect ratio
+ Dimension newDimension = getScaledDimension(
+ new Dimension(xsize, ysize),
+ new Dimension(xmax, ymax)
+ );
- // if verbose flag is set, print out extracted text
- // to STDOUT
- if (verbose) {
- System.out.println("x scale factor: " + scale_factor);
- }
-
- // now reduce x size
- // and y size
- xsize = xsize * scale_factor;
- ysize = ysize * scale_factor;
-
- // if verbose flag is set, print out extracted text
- // to STDOUT
- if (verbose) {
- System.out.println("size after fitting to maximum width: " + xsize + "," + ysize);
- }
- }
-
- // scale by y if needed
- if (ysize > ymax) {
- float scale_factor = ymax / ysize;
-
- // now reduce x size
- // and y size
- xsize = xsize * scale_factor;
- ysize = ysize * scale_factor;
- }
// if verbose flag is set, print details to STDOUT
if (verbose) {
- System.out.println("size after fitting to maximum height: " + xsize + ", "
- + ysize);
+ System.out.println("size after fitting to maximum height: " + newDimension.width + ", "
+ + newDimension.height);
}
+ xsize = newDimension.width;
+ ysize = newDimension.height;
+
// create an image buffer for the thumbnail with the new xsize, ysize
- BufferedImage thumbnail = new BufferedImage((int) xsize, (int) ysize,
- BufferedImage.TYPE_INT_RGB);
+ BufferedImage thumbnail = new BufferedImage(xsize, ysize, BufferedImage.TYPE_INT_RGB);
// Use blurring if selected in config.
// a little blur before scaling does wonders for keeping moire in check.
if (blurring) {
// send the buffered image off to get blurred.
- buf = getBlurredInstance((BufferedImage) buf);
+ correctedImage = getBlurredInstance(correctedImage);
}
// Use high quality scaling method if selected in config.
// this has a definite performance penalty.
if (hqscaling) {
// send the buffered image off to get an HQ downscale.
- buf = getScaledInstance((BufferedImage) buf, (int) xsize, (int) ysize,
- (Object) RenderingHints.VALUE_INTERPOLATION_BICUBIC, (boolean) true);
+ correctedImage = getScaledInstance(correctedImage, xsize, ysize,
+ RenderingHints.VALUE_INTERPOLATION_BICUBIC, true);
}
// now render the image into the thumbnail buffer
Graphics2D g2d = thumbnail.createGraphics();
- g2d.drawImage(buf, 0, 0, (int) xsize, (int) ysize, null);
+ g2d.drawImage(correctedImage, 0, 0, xsize, ysize, null);
if (brandHeight != 0) {
ConfigurationService configurationService
= DSpaceServicesFactory.getInstance().getConfigurationService();
- Brand brand = new Brand((int) xsize, brandHeight, new Font(brandFont, Font.PLAIN, brandFontPoint), 5);
+ Brand brand = new Brand(xsize, brandHeight, new Font(brandFont, Font.PLAIN, brandFontPoint), 5);
BufferedImage brandImage = brand.create(configurationService.getProperty("webui.preview.brand"),
configurationService.getProperty("webui.preview.brand.abbrev"),
currentItem == null ? "" : "hdl:" + currentItem.getHandle());
- g2d.drawImage(brandImage, (int) 0, (int) ysize, (int) xsize, (int) 20, null);
+ g2d.drawImage(brandImage, 0, ysize, xsize, 20, null);
}
- // now create an input stream for the thumbnail buffer and return it
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- ImageIO.write(thumbnail, "jpeg", baos);
- // now get the array
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ByteArrayInputStream bais;
+ // now create an input stream for the thumbnail buffer and return it
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ ImageIO.write(thumbnail, "jpeg", baos);
+ // now get the array
+ bais = new ByteArrayInputStream(baos.toByteArray());
+ }
return bais; // hope this gets written out before its garbage collected!
}
diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/PDFBoxThumbnail.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/PDFBoxThumbnail.java
index 3acb6900dbda..eb23e9daa085 100644
--- a/dspace-api/src/main/java/org/dspace/app/mediafilter/PDFBoxThumbnail.java
+++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/PDFBoxThumbnail.java
@@ -11,6 +11,8 @@
import java.io.InputStream;
import org.apache.logging.log4j.Logger;
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.io.RandomAccessReadBuffer;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
import org.apache.pdfbox.rendering.PDFRenderer;
@@ -71,7 +73,7 @@ public InputStream getDestinationStream(Item currentItem, InputStream source, bo
BufferedImage buf;
// Render the page image.
- try ( PDDocument doc = PDDocument.load(source); ) {
+ try ( PDDocument doc = Loader.loadPDF(new RandomAccessReadBuffer(source)); ) {
PDFRenderer renderer = new PDFRenderer(doc);
buf = renderer.renderImage(0);
} catch (InvalidPasswordException ex) {
@@ -81,6 +83,7 @@ public InputStream getDestinationStream(Item currentItem, InputStream source, bo
// Generate thumbnail derivative and return as IO stream.
JPEGFilter jpegFilter = new JPEGFilter();
+
return jpegFilter.getThumb(currentItem, buf, verbose);
}
}
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 d316cb636f87..a7140f244dfa 100644
--- a/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationMethod.java
+++ b/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationMethod.java
@@ -54,7 +54,7 @@ public interface AuthenticationMethod {
public static final int BAD_CREDENTIALS = 2;
/**
- * Not allowed to login this way without X.509 certificate.
+ * Not allowed to login this way without a certificate.
*/
public static final int CERT_REQUIRED = 3;
@@ -124,8 +124,8 @@ public boolean allowSetPassword(Context context,
* Predicate, is this an implicit authentication method.
* An implicit method gets credentials from the environment (such as
* an HTTP request or even Java system properties) rather than the
- * explicit username and password. For example, a method that reads
- * the X.509 certificates in an HTTPS request is implicit.
+ * explicit username and password. For example, a method that provides
+ * IP-based authentication is implicit.
*
* @return true if this method uses implicit authentication.
*/
@@ -166,7 +166,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request)
* otherwise
*/
public default boolean areSpecialGroupsApplicable(Context context, HttpServletRequest request) {
- return getName().equals(context.getAuthenticationMethod());
+ return getName().equals(context.getAuthenticationMethod()) || isUsed(context, request);
}
/**
@@ -188,7 +188,7 @@ public default boolean areSpecialGroupsApplicable(Context context, HttpServletRe
*
Meaning:
* SUCCESS - authenticated OK.
* BAD_CREDENTIALS - user exists, but credentials (e.g. passwd) don't match
- * CERT_REQUIRED - not allowed to login this way without X.509 cert.
+ * CERT_REQUIRED - not allowed to login this way without a cert.
* NO_SUCH_USER - user not found using this method.
* BAD_ARGS - user/pw not appropriate for this method
* @throws SQLException if database error
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 2b07f73c489c..c0dde49b13a3 100644
--- a/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationServiceImpl.java
@@ -38,11 +38,11 @@
* Configuration
* The stack of authentication methods is defined by one property in the DSpace configuration:
*
- * plugin.sequence.org.dspace.eperson.AuthenticationMethod = a list of method class names
+ * plugin.sequence.org.dspace.authenticate.AuthenticationMethod = a list of method class names
* e.g.
- * plugin.sequence.org.dspace.eperson.AuthenticationMethod = \
- * org.dspace.eperson.X509Authentication, \
- * org.dspace.eperson.PasswordAuthentication
+ * plugin.sequence.org.dspace.authenticate.AuthenticationMethod = \
+ * org.dspace.authenticate.IPAuthentication, \
+ * org.dspace.authenticate.PasswordAuthentication
*
*
* The "stack" is always traversed in order, with the methods
@@ -110,6 +110,7 @@ protected int authenticateInternal(Context context,
}
if (ret == AuthenticationMethod.SUCCESS) {
updateLastActiveDate(context);
+ context.setAuthenticationMethod(aMethodStack.getName());
return ret;
}
if (ret < bestRet) {
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 40b8f48078c9..9d7c09f1c314 100644
--- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java
+++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java
@@ -203,7 +203,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request)
*
Meaning:
* SUCCESS - authenticated OK.
* BAD_CREDENTIALS - user exists, but credentials (e.g. passwd) don't match
- * CERT_REQUIRED - not allowed to login this way without X.509 cert.
+ * CERT_REQUIRED - not allowed to login this way without a cert.
* NO_SUCH_USER - user not found using this method.
* BAD_ARGS - user/pw not appropriate for this method
*/
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 8e030305c957..035a235422a6 100644
--- a/dspace-api/src/main/java/org/dspace/authenticate/PasswordAuthentication.java
+++ b/dspace-api/src/main/java/org/dspace/authenticate/PasswordAuthentication.java
@@ -188,7 +188,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request)
*
Meaning:
* SUCCESS - authenticated OK.
* BAD_CREDENTIALS - user exists, but password doesn't match
- * CERT_REQUIRED - not allowed to login this way without X.509 cert.
+ * CERT_REQUIRED - not allowed to login this way without a cert.
* NO_SUCH_USER - no EPerson with matching email address.
* BAD_ARGS - missing username, or user matched but cannot login.
* @throws SQLException if database error
@@ -213,7 +213,7 @@ public int authenticate(Context context,
// cannot login this way
return BAD_ARGS;
} else if (eperson.getRequireCertificate()) {
- // this user can only login with x.509 certificate
+ // this user can only login with a certificate
log.warn(LogHelper.getHeader(context, "authenticate",
"rejecting PasswordAuthentication because " + username + " requires " +
"certificate."));
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 24d8266012d4..13a5ae6d0dfd 100644
--- a/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java
+++ b/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java
@@ -160,7 +160,7 @@ public class ShibAuthentication implements AuthenticationMethod {
* SUCCESS - authenticated OK.
* BAD_CREDENTIALS - user exists, but credentials (e.g. passwd)
* don't match
- * CERT_REQUIRED - not allowed to login this way without X.509 cert.
+ * CERT_REQUIRED - not allowed to login this way without a cert.
*
* NO_SUCH_USER - user not found using this method.
* BAD_ARGS - user/pw not appropriate for this method
@@ -417,8 +417,7 @@ public boolean allowSetPassword(Context context,
* Predicate, is this an implicit authentication method. An implicit method
* gets credentials from the environment (such as an HTTP request or even
* Java system properties) rather than the explicit username and password.
- * For example, a method that reads the X.509 certificates in an HTTPS
- * request is implicit.
+ * For example, a method that provides IP-based authentication is implicit.
*
* @return true if this method uses implicit authentication.
*/
@@ -871,7 +870,7 @@ protected void updateEPerson(Context context, HttpServletRequest request, EPerso
String[] nameParts = MetadataFieldName.parse(field);
ePersonService.setMetadataSingleValue(context, eperson,
- nameParts[0], nameParts[1], nameParts[2], value, null);
+ nameParts[0], nameParts[1], nameParts[2], null, value);
log.debug("Updated the eperson's '{}' metadata using header: '{}' = '{}'.",
field, header, value);
}
@@ -917,7 +916,7 @@ protected int swordCompatibility(Context context, String username, String passwo
" is not allowed to login.");
return BAD_ARGS;
} else if (eperson.getRequireCertificate()) {
- // this user can only login with x.509 certificate
+ // this user can only login with a certificate
log.error(
"Shibboleth-based password authentication failed for user " + username + " because the eperson object" +
" requires a certificate to authenticate..");
diff --git a/dspace-api/src/main/java/org/dspace/authenticate/X509Authentication.java b/dspace-api/src/main/java/org/dspace/authenticate/X509Authentication.java
deleted file mode 100644
index 55843c710760..000000000000
--- a/dspace-api/src/main/java/org/dspace/authenticate/X509Authentication.java
+++ /dev/null
@@ -1,616 +0,0 @@
-/**
- * The contents of this file are subject to the license and copyright
- * detailed in the LICENSE and NOTICE files at the root of the source
- * tree and available online at
- *
- * http://www.dspace.org/license/
- */
-package org.dspace.authenticate;
-
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.Principal;
-import java.security.PublicKey;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.StringTokenizer;
-
-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;
-import org.dspace.authenticate.service.AuthenticationService;
-import org.dspace.authorize.AuthorizeException;
-import org.dspace.core.Context;
-import org.dspace.core.LogHelper;
-import org.dspace.eperson.EPerson;
-import org.dspace.eperson.Group;
-import org.dspace.eperson.factory.EPersonServiceFactory;
-import org.dspace.eperson.service.EPersonService;
-import org.dspace.eperson.service.GroupService;
-import org.dspace.services.ConfigurationService;
-import org.dspace.services.factory.DSpaceServicesFactory;
-
-/**
- * Implicit authentication method that gets credentials from the X.509 client
- * certificate supplied by the HTTPS client when connecting to this server. The
- * email address in that certificate is taken as the authenticated user name
- * with no further checking, so be sure your HTTP server (e.g. Tomcat) is
- * configured correctly to accept only client certificates it can validate.
- *
- * See the AuthenticationMethod interface for more details.
- *
- * Configuration:
- *
- *
- * x509.keystore.path =
- *
- * path to Java keystore file
- *
- * keystore.password =
- *
- * password to access the keystore
- *
- * ca.cert =
- *
- * path to certificate file for CA whose client certs to accept.
- *
- * autoregister =
- *
- * "true" if E-Person is created automatically for unknown new users.
- *
- * groups =
- *
- * comma-delimited list of special groups to add user to if authenticated.
- *
- * emaildomain =
- *
- * email address domain (after the 'at' symbol) to match before allowing
- * membership in special groups.
- *
- *
- *
- * Only one of the "keystore.path" or "ca.cert"
- * options is required. If you supply a keystore, then all of the "trusted"
- * certificates in the keystore represent CAs whose client certificates will be
- * accepted. The ca.cert option only allows a single CA to be
- * named.
- *
- * You can configure both a keystore and a CA cert, and both will be
- * used.
- *
- * The autoregister configuration parameter determines what the
- * canSelfRegister() method returns. It also allows an EPerson
- * record to be created automatically when the presented certificate is
- * acceptable but there is no corresponding EPerson.
- *
- * @author Larry Stone
- * @version $Revision$
- */
-public class X509Authentication implements AuthenticationMethod {
-
- /**
- * log4j category
- */
- private static Logger log = org.apache.logging.log4j.LogManager.getLogger(X509Authentication.class);
-
- /**
- * public key of CA to check client certs against.
- */
- private static PublicKey caPublicKey = null;
-
- /**
- * key store for CA certs if we use that
- */
- private static KeyStore caCertKeyStore = null;
-
- private static String loginPageTitle = null;
-
- private static String loginPageURL = null;
-
- protected AuthenticationService authenticationService = AuthenticateServiceFactory.getInstance()
- .getAuthenticationService();
- protected EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
- protected GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
- protected ConfigurationService configurationService =
- DSpaceServicesFactory.getInstance().getConfigurationService();
-
- private static final String X509_AUTHENTICATED = "x509.authenticated";
-
-
- /**
- * Initialization: Set caPublicKey and/or keystore. This loads the
- * information needed to check if a client cert presented is valid and
- * acceptable.
- */
- static {
- ConfigurationService configurationService =
- DSpaceServicesFactory.getInstance().getConfigurationService();
- /*
- * allow identification of alternative entry points for certificate
- * authentication when selected by the user rather than implicitly.
- */
- loginPageTitle = configurationService
- .getProperty("authentication-x509.chooser.title.key");
- loginPageURL = configurationService
- .getProperty("authentication-x509.chooser.uri");
-
- String keystorePath = configurationService
- .getProperty("authentication-x509.keystore.path");
- String keystorePassword = configurationService
- .getProperty("authentication-x509.keystore.password");
- String caCertPath = configurationService
- .getProperty("authentication-x509.ca.cert");
-
- // First look for keystore full of trusted certs.
- if (keystorePath != null) {
- FileInputStream fis = null;
- if (keystorePassword == null) {
- keystorePassword = "";
- }
- try {
- KeyStore ks = KeyStore.getInstance("JKS");
- fis = new FileInputStream(keystorePath);
- ks.load(fis, keystorePassword.toCharArray());
- caCertKeyStore = ks;
- } catch (IOException e) {
- log
- .error("X509Authentication: Failed to load CA keystore, file="
- + keystorePath + ", error=" + e.toString());
- } catch (GeneralSecurityException e) {
- log
- .error("X509Authentication: Failed to extract CA keystore, file="
- + keystorePath + ", error=" + e.toString());
- } finally {
- if (fis != null) {
- try {
- fis.close();
- } catch (IOException ioe) {
- // ignore
- }
- }
- }
- }
-
- // Second, try getting public key out of CA cert, if that's configured.
- if (caCertPath != null) {
- InputStream is = null;
- FileInputStream fis = null;
- try {
- fis = new FileInputStream(caCertPath);
- is = new BufferedInputStream(fis);
- X509Certificate cert = (X509Certificate) CertificateFactory
- .getInstance("X.509").generateCertificate(is);
- if (cert != null) {
- caPublicKey = cert.getPublicKey();
- }
- } catch (IOException e) {
- log.error("X509Authentication: Failed to load CA cert, file="
- + caCertPath + ", error=" + e.toString());
- } catch (CertificateException e) {
- log
- .error("X509Authentication: Failed to extract CA cert, file="
- + caCertPath + ", error=" + e.toString());
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException ioe) {
- // ignore
- }
- }
-
- if (fis != null) {
- try {
- fis.close();
- } catch (IOException ioe) {
- // ignore
- }
- }
- }
- }
- }
-
- /**
- * Return the email address from certificate, or null if an
- * email address cannot be found in the certificate.
- *
- * Note that the certificate parsing has only been tested with certificates
- * granted by the MIT Certification Authority, and may not work elsewhere.
- *
- * @param certificate -
- * An X509 certificate object
- * @return - The email address found in certificate, or null if an email
- * address cannot be found in the certificate.
- */
- private static String getEmail(X509Certificate certificate)
- throws SQLException {
- Principal principal = certificate.getSubjectDN();
-
- if (principal == null) {
- return null;
- }
-
- String dn = principal.getName();
- if (dn == null) {
- return null;
- }
-
- StringTokenizer tokenizer = new StringTokenizer(dn, ",");
- String token = null;
- while (tokenizer.hasMoreTokens()) {
- int len = "emailaddress=".length();
-
- token = (String) tokenizer.nextToken();
-
- if (token.toLowerCase().startsWith("emailaddress=")) {
- // Make sure the token actually contains something
- if (token.length() <= len) {
- return null;
- }
-
- return token.substring(len).toLowerCase();
- }
- }
-
- return null;
- }
-
- /**
- * Verify CERTIFICATE against KEY. Return true if and only if CERTIFICATE is
- * valid and can be verified against KEY.
- *
- * @param context The current DSpace context
- * @param certificate -
- * An X509 certificate object
- * @return - True if CERTIFICATE is valid and can be verified against KEY,
- * false otherwise.
- */
- private static boolean isValid(Context context, X509Certificate certificate) {
- if (certificate == null) {
- return false;
- }
-
- // This checks that current time is within cert's validity window:
- try {
- certificate.checkValidity();
- } catch (CertificateException e) {
- log.info(LogHelper.getHeader(context, "authentication",
- "X.509 Certificate is EXPIRED or PREMATURE: "
- + e.toString()));
- return false;
- }
-
- // Try CA public key, if available.
- if (caPublicKey != null) {
- try {
- certificate.verify(caPublicKey);
- return true;
- } catch (GeneralSecurityException e) {
- log.info(LogHelper.getHeader(context, "authentication",
- "X.509 Certificate FAILED SIGNATURE check: "
- + e.toString()));
- }
- }
-
- // Try it with keystore, if available.
- if (caCertKeyStore != null) {
- try {
- Enumeration ke = caCertKeyStore.aliases();
-
- while (ke.hasMoreElements()) {
- String alias = (String) ke.nextElement();
- if (caCertKeyStore.isCertificateEntry(alias)) {
- Certificate ca = caCertKeyStore.getCertificate(alias);
- try {
- certificate.verify(ca.getPublicKey());
- return true;
- } catch (CertificateException ce) {
- // ignore
- }
- }
- }
- log
- .info(LogHelper
- .getHeader(context, "authentication",
- "Keystore method FAILED SIGNATURE check on client cert."));
- } catch (GeneralSecurityException e) {
- log.info(LogHelper.getHeader(context, "authentication",
- "X.509 Certificate FAILED SIGNATURE check: "
- + e.toString()));
- }
-
- }
- return false;
- }
-
- /**
- * Predicate, can new user automatically create EPerson. Checks
- * configuration value. You'll probably want this to be true to take
- * advantage of a Web certificate infrastructure with many more users than
- * are already known by DSpace.
- *
- * @throws SQLException if database error
- */
- @Override
- public boolean canSelfRegister(Context context, HttpServletRequest request,
- String username) throws SQLException {
- return configurationService
- .getBooleanProperty("authentication-x509.autoregister");
- }
-
- /**
- * Nothing extra to initialize.
- *
- * @throws SQLException if database error
- */
- @Override
- public void initEPerson(Context context, HttpServletRequest request,
- EPerson eperson) throws SQLException {
- }
-
- /**
- * We don't use EPerson password so there is no reason to change it.
- *
- * @throws SQLException if database error
- */
- @Override
- public boolean allowSetPassword(Context context,
- HttpServletRequest request, String username) throws SQLException {
- return false;
- }
-
- /**
- * Returns true, this is an implicit method.
- */
- @Override
- public boolean isImplicit() {
- return true;
- }
-
- /**
- * Returns a list of group names that the user should be added to upon
- * successful authentication, configured in dspace.cfg.
- *
- * @return List of special groups configured for this authenticator
- */
- private List getX509Groups() {
- List groupNames = new ArrayList();
-
- String[] groups = configurationService
- .getArrayProperty("authentication-x509.groups");
-
- if (ArrayUtils.isNotEmpty(groups)) {
- for (String group : groups) {
- groupNames.add(group.trim());
- }
- }
-
- return groupNames;
- }
-
- /**
- * Checks for configured email domain required to grant special groups
- * membership. If no email domain is configured to verify, special group
- * membership is simply granted.
- *
- * @param request -
- * The current request object
- * @param email -
- * The email address from the x509 certificate
- */
- private void setSpecialGroupsFlag(HttpServletRequest request, String email) {
- String emailDomain = null;
- emailDomain = (String) request
- .getAttribute("authentication.x509.emaildomain");
-
- HttpSession session = request.getSession(true);
-
- if (null != emailDomain && !"".equals(emailDomain)) {
- if (email.substring(email.length() - emailDomain.length()).equals(
- emailDomain)) {
- session.setAttribute("x509Auth", Boolean.TRUE);
- }
- } else {
- // No configured email domain to verify. Just flag
- // as authenticated so special groups are granted.
- session.setAttribute("x509Auth", Boolean.TRUE);
- }
- }
-
- /**
- * Return special groups configured in dspace.cfg for X509 certificate
- * authentication.
- *
- * @param context context
- * @param request object potentially containing the cert
- * @return An int array of group IDs
- * @throws SQLException if database error
- */
- @Override
- public List getSpecialGroups(Context context, HttpServletRequest request)
- throws SQLException {
- if (request == null) {
- return Collections.EMPTY_LIST;
- }
-
- Boolean authenticated = false;
- HttpSession session = request.getSession(false);
- authenticated = (Boolean) session.getAttribute("x509Auth");
- authenticated = (null == authenticated) ? false : authenticated;
-
- if (authenticated) {
- List groupNames = getX509Groups();
- List groups = new ArrayList<>();
-
- if (groupNames != null) {
- for (String groupName : groupNames) {
- if (groupName != null) {
- Group group = groupService.findByName(context, groupName);
- if (group != null) {
- groups.add(group);
- } else {
- log.warn(LogHelper.getHeader(context,
- "configuration_error", "unknown_group="
- + groupName));
- }
- }
- }
- }
-
- return groups;
- }
-
- return Collections.EMPTY_LIST;
- }
-
- /**
- * X509 certificate authentication. The client certificate is obtained from
- * the ServletRequest object.
- *
- *
If the certificate is valid, and corresponds to an existing EPerson,
- * and the user is allowed to login, return success.
- *
If the user is matched but is not allowed to login, it fails.
- *
If the certificate is valid, but there is no corresponding EPerson,
- * the "authentication.x509.autoregister" configuration
- * parameter is checked (via canSelfRegister())
- *
- *
If it's true, a new EPerson record is created for the certificate,
- * and the result is success.
- *
If it's false, return that the user was unknown.
- *
- *
- *
- *
- * @return One of: SUCCESS, BAD_CREDENTIALS, NO_SUCH_USER, BAD_ARGS
- * @throws SQLException if database error
- */
- @Override
- public int authenticate(Context context, String username, String password,
- String realm, HttpServletRequest request) throws SQLException {
- // Obtain the certificate from the request, if any
- X509Certificate[] certs = null;
- if (request != null) {
- certs = (X509Certificate[]) request
- .getAttribute("jakarta.servlet.request.X509Certificate");
- }
-
- if ((certs == null) || (certs.length == 0)) {
- return BAD_ARGS;
- } else {
- // We have a cert -- check it and get username from it.
- try {
- if (!isValid(context, certs[0])) {
- log
- .warn(LogHelper
- .getHeader(context, "authenticate",
- "type=x509certificate, status=BAD_CREDENTIALS (not valid)"));
- return BAD_CREDENTIALS;
- }
-
- // And it's valid - try and get an e-person
- String email = getEmail(certs[0]);
- EPerson eperson = null;
- if (email != null) {
- eperson = ePersonService.findByEmail(context, email);
- }
- if (eperson == null) {
- // Cert is valid, but no record.
- if (email != null
- && canSelfRegister(context, request, null)) {
- // Register the new user automatically
- log.info(LogHelper.getHeader(context, "autoregister",
- "from=x.509, email=" + email));
-
- // TEMPORARILY turn off authorisation
- context.turnOffAuthorisationSystem();
- eperson = ePersonService.create(context);
- eperson.setEmail(email);
- eperson.setCanLogIn(true);
- authenticationService.initEPerson(context, request,
- eperson);
- ePersonService.update(context, eperson);
- context.dispatchEvents();
- context.restoreAuthSystemState();
- context.setCurrentUser(eperson);
- request.setAttribute(X509_AUTHENTICATED, true);
- setSpecialGroupsFlag(request, email);
- return SUCCESS;
- } else {
- // No auto-registration for valid certs
- log
- .warn(LogHelper
- .getHeader(context, "authenticate",
- "type=cert_but_no_record, cannot auto-register"));
- return NO_SUCH_USER;
- }
- } else if (!eperson.canLogIn()) { // make sure this is a login account
- log.warn(LogHelper.getHeader(context, "authenticate",
- "type=x509certificate, email=" + email
- + ", canLogIn=false, rejecting."));
- return BAD_ARGS;
- } else {
- log.info(LogHelper.getHeader(context, "login",
- "type=x509certificate"));
- context.setCurrentUser(eperson);
- request.setAttribute(X509_AUTHENTICATED, true);
- setSpecialGroupsFlag(request, email);
- return SUCCESS;
- }
- } catch (AuthorizeException ce) {
- log.warn(LogHelper.getHeader(context, "authorize_exception",
- ""), ce);
- }
-
- return BAD_ARGS;
- }
- }
-
- /**
- * Returns URL of password-login servlet.
- *
- * @param context DSpace context, will be modified (EPerson set) upon success.
- * @param request The HTTP request that started this operation, or null if not
- * applicable.
- * @param response The HTTP response from the servlet method.
- * @return fully-qualified URL
- */
- @Override
- public String loginPageURL(Context context, HttpServletRequest request,
- HttpServletResponse response) {
- return loginPageURL;
- }
-
- @Override
- public String getName() {
- return "x509";
- }
-
- @Override
- public boolean isUsed(final Context context, final HttpServletRequest request) {
- if (request != null &&
- context.getCurrentUser() != null &&
- request.getAttribute(X509_AUTHENTICATED) != null) {
- return true;
- }
- return false;
- }
-
- @Override
- public boolean canChangePassword(Context context, EPerson ePerson, String currentPassword) {
- return false;
- }
-}
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 45ad8932daec..8409f1e27d05 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
@@ -29,11 +29,11 @@
* Configuration
* The stack of authentication methods is defined by one property in the DSpace configuration:
*
- * plugin.sequence.org.dspace.eperson.AuthenticationMethod = a list of method class names
+ * plugin.sequence.org.dspace.authenticate.AuthenticationMethod = a list of method class names
* e.g.
- * plugin.sequence.org.dspace.eperson.AuthenticationMethod = \
- * org.dspace.eperson.X509Authentication, \
- * org.dspace.eperson.PasswordAuthentication
+ * plugin.sequence.org.dspace.authenticate.AuthenticationMethod = \
+ * org.dspace.authenticate.IPAuthentication, \
+ * org.dspace.authenticate.PasswordAuthentication
*
*
* The "stack" is always traversed in order, with the methods
@@ -64,7 +64,7 @@ public interface AuthenticationService {
*
Meaning:
* SUCCESS - authenticated OK.
* BAD_CREDENTIALS - user exists, but credentials (e.g. password) don't match
- * CERT_REQUIRED - not allowed to login this way without X.509 cert.
+ * CERT_REQUIRED - not allowed to login this way without a cert.
* NO_SUCH_USER - user not found using this method.
* BAD_ARGS - user/password not appropriate for this method
*/
@@ -91,7 +91,7 @@ public int authenticate(Context context,
*
Meaning:
* SUCCESS - authenticated OK.
* BAD_CREDENTIALS - user exists, but credentials (e.g. password) don't match
- * CERT_REQUIRED - not allowed to login this way without X.509 cert.
+ * CERT_REQUIRED - not allowed to login this way without a cert.
* NO_SUCH_USER - user not found using this method.
* BAD_ARGS - user/password not appropriate for this method
*/
diff --git a/dspace-api/src/main/java/org/dspace/authority/orcid/Orcidv3SolrAuthorityImpl.java b/dspace-api/src/main/java/org/dspace/authority/orcid/Orcidv3SolrAuthorityImpl.java
index 494daa97734a..312a00c146af 100644
--- a/dspace-api/src/main/java/org/dspace/authority/orcid/Orcidv3SolrAuthorityImpl.java
+++ b/dspace-api/src/main/java/org/dspace/authority/orcid/Orcidv3SolrAuthorityImpl.java
@@ -10,6 +10,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
@@ -20,6 +21,7 @@
import org.apache.logging.log4j.Logger;
import org.dspace.authority.AuthorityValue;
import org.dspace.authority.SolrAuthorityInterface;
+import org.dspace.external.OrcidConnectionException;
import org.dspace.external.OrcidRestConnector;
import org.dspace.external.provider.orcid.xml.XMLtoBio;
import org.dspace.orcid.model.factory.OrcidFactoryUtils;
@@ -142,9 +144,15 @@ public Person getBio(String id) {
return null;
}
initializeAccessToken();
- InputStream bioDocument = orcidRestConnector.get(id + ((id.endsWith("/person")) ? "" : "/person"), accessToken);
- XMLtoBio converter = new XMLtoBio();
- return converter.convertSinglePerson(bioDocument);
+ try {
+ InputStream bioDocument = orcidRestConnector.get(id + ((id.endsWith("/person")) ? "" : "/person"),
+ accessToken);
+ XMLtoBio converter = new XMLtoBio();
+ return converter.convertSinglePerson(bioDocument);
+ } catch (OrcidConnectionException e) {
+ log.error("Error retrieving ORCID bio for ID=" + id, e);
+ return null;
+ }
}
@@ -167,29 +175,35 @@ public List queryBio(String text, int start, int rows) {
// Check / init access token
initializeAccessToken();
- String searchPath = "search?q=" + URLEncoder.encode(text) + "&start=" + start + "&rows=" + rows;
+ String searchPath = "search?q=" + URLEncoder.encode(text, StandardCharsets.UTF_8) + "&start=" + start +
+ "&rows=" + rows;
log.debug("queryBio searchPath=" + searchPath + " accessToken=" + accessToken);
- InputStream bioDocument = orcidRestConnector.get(searchPath, accessToken);
- XMLtoBio converter = new XMLtoBio();
- List results = converter.convert(bioDocument);
- List bios = new LinkedList<>();
- for (Result result : results) {
- OrcidIdentifier orcidIdentifier = result.getOrcidIdentifier();
- if (orcidIdentifier != null) {
- log.debug("Found OrcidId=" + orcidIdentifier.toString());
- String orcid = orcidIdentifier.getPath();
- Person bio = getBio(orcid);
- if (bio != null) {
- bios.add(bio);
+ try {
+ InputStream bioDocument = orcidRestConnector.get(searchPath, accessToken);
+ XMLtoBio converter = new XMLtoBio();
+ List results = converter.convert(bioDocument);
+ List bios = new LinkedList<>();
+ for (Result result : results) {
+ OrcidIdentifier orcidIdentifier = result.getOrcidIdentifier();
+ if (orcidIdentifier != null) {
+ log.debug("Found OrcidId=" + orcidIdentifier);
+ String orcid = orcidIdentifier.getPath();
+ Person bio = getBio(orcid);
+ if (bio != null) {
+ bios.add(bio);
+ }
}
}
+ try {
+ bioDocument.close();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ return bios;
+ } catch (OrcidConnectionException e) {
+ log.error("Error searching ORCID for query=" + text, e);
+ return Collections.emptyList();
}
- try {
- bioDocument.close();
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- }
- return bios;
}
/**
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 f2692cf394fc..60004bda9538 100644
--- a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java
@@ -16,6 +16,7 @@
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import java.util.Objects;
import java.util.UUID;
import org.apache.commons.collections4.CollectionUtils;
@@ -48,6 +49,7 @@
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
+import org.dspace.services.ConfigurationService;
import org.dspace.workflow.WorkflowItemService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -84,6 +86,8 @@ public class AuthorizeServiceImpl implements AuthorizeService {
protected WorkflowItemService workflowItemService;
@Autowired(required = true)
private SearchService searchService;
+ @Autowired(required = true)
+ private ConfigurationService configurationService;
protected AuthorizeServiceImpl() {
@@ -508,17 +512,26 @@ public List getPoliciesActionFilter(Context c, DSpaceObject o,
return resourcePolicyService.find(c, o, actionID);
}
+ @Override
+ public void inheritPolicies(Context c, DSpaceObject src, DSpaceObject dest)
+ throws SQLException, AuthorizeException {
+ inheritPolicies(c, src, dest, false);
+ }
+
@Override
public void inheritPolicies(Context c, DSpaceObject src,
- DSpaceObject dest) throws SQLException, AuthorizeException {
+ DSpaceObject dest, boolean includeCustom) throws SQLException, AuthorizeException {
// find all policies for the source object
List policies = getPolicies(c, src);
- //Only inherit non-ADMIN policies (since ADMIN policies are automatically inherited)
- //and non-custom policies as these are manually applied when appropriate
+ // Only inherit non-ADMIN policies (since ADMIN policies are automatically inherited)
+ // and non-custom policies (usually applied manually?) UNLESS specified otherwise with includCustom
+ // (for example, item.addBundle() will inherit custom policies to enforce access conditions)
List nonAdminPolicies = new ArrayList<>();
for (ResourcePolicy rp : policies) {
- if (rp.getAction() != Constants.ADMIN && !StringUtils.equals(rp.getRpType(), ResourcePolicy.TYPE_CUSTOM)) {
+ if (rp.getAction() != Constants.ADMIN && (!StringUtils.equals(rp.getRpType(), ResourcePolicy.TYPE_CUSTOM)
+ || (includeCustom && StringUtils.equals(rp.getRpType(), ResourcePolicy.TYPE_CUSTOM)
+ && isNotAlreadyACustomRPOfThisTypeOnDSO(c, dest)))) {
nonAdminPolicies.add(rp);
}
}
@@ -943,4 +956,100 @@ private String formatCustomQuery(String query) {
return query + " AND ";
}
}
+
+ /**
+ * Add the default policies, which have not been already added to the given DSpace object
+ *
+ * @param context The relevant DSpace Context.
+ * @param dso The DSpace Object to add policies to
+ * @param defaultCollectionPolicies list of policies
+ * @throws SQLException An exception that provides information on a database access error or other errors.
+ * @throws AuthorizeException Exception indicating the current user of the context does not have permission
+ * to perform a particular action.
+ */
+ @Override
+ public void addDefaultPoliciesNotInPlace(Context context, DSpaceObject dso,
+ List defaultCollectionPolicies) throws SQLException, AuthorizeException {
+ boolean appendMode = configurationService
+ .getBooleanProperty("core.authorization.installitem.inheritance-read.append-mode", false);
+ for (ResourcePolicy defaultPolicy : defaultCollectionPolicies) {
+ if (!isAnIdenticalPolicyAlreadyInPlace(context, dso, defaultPolicy.getGroup(), Constants.READ,
+ defaultPolicy.getID()) &&
+ (!appendMode && isNotAlreadyACustomRPOfThisTypeOnDSO(context, dso) ||
+ appendMode && shouldBeAppended(context, dso, defaultPolicy))) {
+ ResourcePolicy newPolicy = resourcePolicyService.clone(context, defaultPolicy);
+ newPolicy.setdSpaceObject(dso);
+ newPolicy.setAction(Constants.READ);
+ newPolicy.setRpType(ResourcePolicy.TYPE_INHERITED);
+ resourcePolicyService.update(context, newPolicy);
+ }
+ }
+ }
+
+ /**
+ * Add a list of custom policies if there are already NO custom policies in place
+ *
+ */
+ @Override
+ public void addCustomPoliciesNotInPlace(Context context, DSpaceObject dso, List customPolicies)
+ throws SQLException, AuthorizeException {
+ boolean customPoliciesAlreadyInPlace =
+ findPoliciesByDSOAndType(context, dso, ResourcePolicy.TYPE_CUSTOM).size() > 0;
+ if (!customPoliciesAlreadyInPlace) {
+ addPolicies(context, customPolicies, dso);
+ }
+ }
+
+ /**
+ * Check whether or not there is already an RP on the given dso, which has actionId={@link Constants.READ} and
+ * resourceTypeId={@link ResourcePolicy.TYPE_CUSTOM}
+ *
+ * @param context DSpace context
+ * @param dso DSpace object to check for custom read RP
+ * @return True if there is no RP on the item with custom read RP, otherwise false
+ * @throws SQLException If something goes wrong retrieving the RP on the DSO
+ */
+ private boolean isNotAlreadyACustomRPOfThisTypeOnDSO(Context context, DSpaceObject dso) throws SQLException {
+ return isNotAlreadyACustomRPOfThisTypeOnDSO(context, dso, Constants.READ);
+ }
+
+ private boolean isNotAlreadyACustomRPOfThisTypeOnDSO(Context context, DSpaceObject dso, int action)
+ throws SQLException {
+ List rps = resourcePolicyService.find(context, dso, action);
+ for (ResourcePolicy rp : rps) {
+ if (rp.getRpType() != null && rp.getRpType().equals(ResourcePolicy.TYPE_CUSTOM)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check if the provided default policy should be appended or not to the final
+ * item. If an item has at least one custom READ policy any anonymous READ
+ * policy with empty start/end date should be skipped
+ *
+ * @param context DSpace context
+ * @param dso DSpace object to check for custom read RP
+ * @param defaultPolicy The policy to check
+ * @return
+ * @throws SQLException If something goes wrong retrieving the RP on the DSO
+ */
+ private boolean shouldBeAppended(Context context, DSpaceObject dso, ResourcePolicy defaultPolicy)
+ throws SQLException {
+ boolean hasCustomPolicy = resourcePolicyService.find(context, dso, Constants.READ)
+ .stream()
+ .filter(rp -> (Objects.nonNull(rp.getRpType()) &&
+ Objects.equals(rp.getRpType(), ResourcePolicy.TYPE_CUSTOM)))
+ .findFirst()
+ .isPresent();
+
+ boolean isAnonymousGroup = Objects.nonNull(defaultPolicy.getGroup())
+ && StringUtils.equals(defaultPolicy.getGroup().getName(), Group.ANONYMOUS);
+
+ boolean datesAreNull = Objects.isNull(defaultPolicy.getStartDate())
+ && Objects.isNull(defaultPolicy.getEndDate());
+
+ return !(hasCustomPolicy && isAnonymousGroup && datesAreNull);
+ }
}
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 3b09f9cf300b..1f9e5ea26677 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
@@ -182,7 +182,7 @@ public List findByEPersonGroupTypeIdAction(Context context, EPer
compareEpersonOrGroups
)
);
- return list(context, criteriaQuery, false, ResourcePolicy.class, 1, -1);
+ return list(context, criteriaQuery, false, ResourcePolicy.class, -1, -1);
}
@Override
diff --git a/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java b/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java
index e0a94833d76c..0e542d98f6d4 100644
--- a/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java
+++ b/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java
@@ -322,6 +322,19 @@ public void addPolicy(Context c, DSpaceObject o, int actionID, Group g, String t
*/
public List getPoliciesActionFilterExceptRpType(Context c, DSpaceObject o, int actionID,
String rpType) throws SQLException;
+ /**
+ * Add policies to an object to match those from a previous object
+ *
+ * @param c context
+ * @param src source of policies
+ * @param dest destination of inherited policies
+ * @param includeCustom whether TYPE_CUSTOM policies should be inherited
+ * @throws SQLException if there's a database problem
+ * @throws AuthorizeException if the current user is not authorized to add these policies
+ */
+ public void inheritPolicies(Context c, DSpaceObject src, DSpaceObject dest, boolean includeCustom)
+ throws SQLException, AuthorizeException;
+
/**
* Add policies to an object to match those from a previous object
*
@@ -604,4 +617,10 @@ long countAdminAuthorizedCollection(Context context, String query)
public void replaceAllPolicies(Context context, DSpaceObject source, DSpaceObject dest)
throws SQLException, AuthorizeException;
+ public void addDefaultPoliciesNotInPlace(Context context, DSpaceObject dso,
+ List defaultCollectionPolicies) throws SQLException, AuthorizeException;
+
+ public void addCustomPoliciesNotInPlace(Context context, DSpaceObject dso,
+ List defaultCollectionPolicies) throws SQLException, AuthorizeException;
+
}
diff --git a/dspace-api/src/main/java/org/dspace/checker/CheckerCommand.java b/dspace-api/src/main/java/org/dspace/checker/CheckerCommand.java
index a12ac3b98a2e..9ad9f553b445 100644
--- a/dspace-api/src/main/java/org/dspace/checker/CheckerCommand.java
+++ b/dspace-api/src/main/java/org/dspace/checker/CheckerCommand.java
@@ -131,7 +131,7 @@ public void process() throws SQLException {
collector.collect(context, info);
}
- context.uncacheEntity(bitstream);
+ context.commit();
bitstream = dispatcher.next();
}
}
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 50ef4baa98e3..481b055fbb7d 100644
--- a/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java
+++ b/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java
@@ -75,6 +75,7 @@ public void sendReport(File attachment, int numberOfBitstreams)
email.setContent("Checker Report", "report is attached ...");
email.addAttachment(attachment, "checksum_checker_report.txt");
email.addRecipient(configurationService.getProperty("mail.admin"));
+ log.info("Sending checker report email to " + configurationService.getProperty("mail.admin"));
email.send();
}
}
@@ -109,18 +110,19 @@ public static void main(String[] args) {
Options options = new Options();
options.addOption("h", "help", false, "Help");
- options.addOption("d", "Deleted", false,
- "Send E-mail report for all bitstreams set as deleted for today");
- options.addOption("m", "Missing", false,
- "Send E-mail report for all bitstreams not found in assetstore for today");
- options.addOption("c", "Changed", false,
- "Send E-mail report for all bitstreams where checksum has been changed for today");
- options.addOption("a", "All", false,
- "Send all E-mail reports");
- options.addOption("u", "Unchecked", false,
- "Send the Unchecked bitstream report");
- options.addOption("n", "Not Processed", false,
- "Send E-mail report for all bitstreams set to longer be processed for today");
+ options.addOption("d", "deleted", false,
+ "Send email report for all bitstreams set as deleted for today");
+ options.addOption("m", "missing", false,
+ "Send email report for all bitstreams not found in assetstore for today");
+ options.addOption("c", "changed", false,
+ "Send email report for all bitstreams where checksum has been changed for today");
+ options.addOption("a", "all", false,
+ "Send all email reports (used by default)");
+ options.addOption("u", "unchecked", false,
+ "Send the unchecked (i.e. recently added) bitstream email report");
+ options.addOption("n", "not-processed", false,
+ "Send email report for all bitstreams set to no longer be processed for today (includes"
+ + " bitstreams marked as deleted or not found)");
try {
line = parser.parse(options, args);
@@ -133,13 +135,15 @@ public static void main(String[] args) {
if (line.hasOption('h')) {
HelpFormatter myhelp = new HelpFormatter();
- myhelp.printHelp("Checksum Reporter\n", options);
- System.out.println("\nSend Deleted bitstream email report: DailyReportEmailer -d");
- System.out.println("\nSend Missing bitstreams email report: DailyReportEmailer -m");
- System.out.println("\nSend Checksum Changed email report: DailyReportEmailer -c");
- System.out.println("\nSend bitstream not to be processed email report: DailyReportEmailer -n");
- System.out.println("\nSend Un-checked bitstream report: DailyReportEmailer -u");
- System.out.println("\nSend All email reports: DailyReportEmailer");
+ myhelp.printHelp("checker-emailer\n", options);
+ System.out.println("\nChecksum Checker Reporter usage examples:\n");
+ System.out.println(" - Send all email reports: checker-emailer -a");
+ System.out.println(" - Send deleted bitstream email report: checker-emailer -d");
+ System.out.println(" - Send missing bitstreams email report: checker-emailer -m");
+ System.out.println(" - Send checksum changed email report: checker-emailer -c");
+ System.out.println(" - Send bitstream not to be processed email report: checker-emailer -n");
+ System.out.println(" - Send unchecked bitstream email report: checker-emailer -u");
+ System.out.println("\nDefault (no arguments) is equivalent to 'checker-emailer -a'\n");
System.exit(0);
}
@@ -191,7 +195,9 @@ public static void main(String[] args) {
writer.write("\n--------------------------------- Report Spacer ---------------------------\n\n");
numBitstreams += reporter.getBitstreamNotFoundReport(context, yesterday, tomorrow, writer);
writer.write("\n--------------------------------- Report Spacer ---------------------------\n\n");
- numBitstreams += reporter.getNotToBeProcessedReport(context, yesterday, tomorrow, writer);
+ // not to be processed report includes deleted and not found bitstreams so it is not necessary to
+ // include the sum in the counter
+ reporter.getNotToBeProcessedReport(context, yesterday, tomorrow, writer);
writer.write("\n--------------------------------- Report Spacer ---------------------------\n\n");
numBitstreams += reporter.getUncheckedBitstreamsReport(context, writer);
writer.write("\n--------------------------------- End Report ---------------------------\n\n");
diff --git a/dspace-api/src/main/java/org/dspace/checker/SimpleReporterServiceImpl.java b/dspace-api/src/main/java/org/dspace/checker/SimpleReporterServiceImpl.java
index ddefb28e1b57..6c69764fdc79 100644
--- a/dspace-api/src/main/java/org/dspace/checker/SimpleReporterServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/checker/SimpleReporterServiceImpl.java
@@ -70,6 +70,7 @@ public int getDeletedBitstreamReport(Context context, Date startDate, Date endDa
osw.write("\n");
osw.write(msg("deleted-bitstream-intro"));
+ osw.write(" ");
osw.write(applyDateFormatShort(startDate));
osw.write(" ");
osw.write(msg("date-range-to"));
@@ -111,7 +112,6 @@ public int getChangedChecksumReport(Context context, Date startDate, Date endDat
osw.write("\n");
osw.write(msg("checksum-did-not-match"));
osw.write(" ");
- osw.write("\n");
osw.write(applyDateFormatShort(startDate));
osw.write(" ");
osw.write(msg("date-range-to"));
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 669621aeeb58..e37f0135dc59 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
@@ -56,8 +56,8 @@ public List findByNotProcessedInDateRange(Context context, D
criteriaQuery.where(criteriaBuilder.and(
criteriaBuilder.equal(mostRecentChecksumRoot.get(MostRecentChecksum_.toBeProcessed), false),
criteriaBuilder
- .lessThanOrEqualTo(mostRecentChecksumRoot.get(MostRecentChecksum_.processStartDate), startDate),
- criteriaBuilder.greaterThan(mostRecentChecksumRoot.get(MostRecentChecksum_.processStartDate), endDate)
+ .lessThanOrEqualTo(mostRecentChecksumRoot.get(MostRecentChecksum_.processStartDate), endDate),
+ criteriaBuilder.greaterThan(mostRecentChecksumRoot.get(MostRecentChecksum_.processStartDate), startDate)
)
);
List orderList = new LinkedList<>();
diff --git a/dspace-api/src/main/java/org/dspace/checker/service/SimpleReporterService.java b/dspace-api/src/main/java/org/dspace/checker/service/SimpleReporterService.java
index 1dc56c20a3de..f3e0b43d8899 100644
--- a/dspace-api/src/main/java/org/dspace/checker/service/SimpleReporterService.java
+++ b/dspace-api/src/main/java/org/dspace/checker/service/SimpleReporterService.java
@@ -72,7 +72,8 @@ public int getBitstreamNotFoundReport(Context context, Date startDate, Date endD
/**
* The bitstreams that were set to not be processed report for the specified
- * date range.
+ * date range. This includes bitstreams that are marked as deleted and bitstreams
+ * that are not found from the assetstore.
*
* @param context context
* @param startDate the start date range.
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 bd56ad465163..3a2670395dbe 100644
--- a/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java
@@ -19,6 +19,8 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
+import org.dspace.app.requestitem.RequestItem;
+import org.dspace.app.requestitem.service.RequestItemService;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.dao.BitstreamDAO;
@@ -63,6 +65,8 @@ public class BitstreamServiceImpl extends DSpaceObjectServiceImpl imp
protected BundleService bundleService;
@Autowired(required = true)
protected BitstreamStorageService bitstreamStorageService;
+ @Autowired(required = true)
+ protected RequestItemService requestItemService;
protected BitstreamServiceImpl() {
super();
@@ -287,6 +291,15 @@ public void delete(Context context, Bitstream bitstream) throws SQLException, Au
//Remove all bundles from the bitstream object, clearing the connection in 2 ways
bundles.clear();
+ // Remove any RequestItem entities associated with this bitstream ensuring there are no requests referencing
+ // a deleted bitstream
+ List requestItems = requestItemService.findAll(context);
+ for (RequestItem requestItem : requestItems) {
+ if (bitstream.equals(requestItem.getBitstream())) {
+ requestItemService.delete(context, requestItem);
+ }
+ }
+
// Remove policies only after the bitstream has been updated (otherwise the current user has not WRITE rights)
authorizeService.removeAllPolicies(context, bitstream);
}
diff --git a/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java
index f5ef4f4b14a4..10f458b81975 100644
--- a/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java
@@ -13,13 +13,17 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Objects;
+import java.util.Queue;
import java.util.Set;
import java.util.UUID;
+import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -838,6 +842,86 @@ public List findAuthorized(Context context, Community community, int
return myResults;
}
+ @Override
+ public List findAuthorized(Context context, Community community, List actions)
+ throws SQLException {
+
+ List myCollections = new ArrayList<>();
+ EPerson eperson = context.getCurrentUser();
+
+ //If eperson is Administrator return all colls or if a community is not null only the community's collections
+ if (authorizeService.isAdmin(context, eperson)) {
+ if (community != null) {
+ return community.getCollections();
+ }
+ myCollections = this.findAll(context);
+ return myCollections;
+ }
+
+ //Get the collections of the eperson where is is admin of a community
+ List directGroups = new ArrayList<>(eperson.getGroups()); // direct membership
+ Queue queue = new LinkedList<>(directGroups);
+ while (!queue.isEmpty()) {
+ Group current = queue.poll();
+ List parents = current.getParentGroups();
+
+ for (Group parent : parents) {
+ if (directGroups.add(parent)) {
+ queue.add(parent);
+ }
+ }
+ }
+
+ List resourcePolicies = resourcePolicyService
+ .find(context, eperson, directGroups, Constants.ADMIN, Constants.COMMUNITY);
+ List uuids = resourcePolicies.stream()
+ .map(policy -> policy.getdSpaceObject().getID())
+ .toList();
+
+ List communities = uuids.stream()
+ .map(uuid -> {
+ try {
+ return communityService.find(context, uuid);
+ } catch (SQLException e) {
+ return null; //ignore that uuid
+ }
+ })
+ .filter(Objects::nonNull)
+ .toList();
+
+ Set allCommunities = new HashSet<>(communities);
+ Set allCommAdminCollections = communities.stream()
+ .flatMap(cm -> cm.getCollections().stream())
+ .collect(Collectors.toSet());
+ Queue queueComm = new LinkedList<>(communities);
+
+ while (!queueComm.isEmpty()) {
+ Community com = queueComm.poll();
+ List childrenComms = com.getSubcommunities();
+ for (Community childComm : childrenComms) {
+ if (allCommunities.add(childComm)) {
+ queueComm.add(childComm);
+ allCommAdminCollections.addAll(childComm.getCollections());
+ }
+ }
+ }
+
+ //Now get the collection when the eperson can deposit or is admin or is in a group with those privileges
+ myCollections = collectionDAO.findAuthorizedByEPerson(context, eperson, actions);
+ Set allCollections = new HashSet<>(myCollections);
+ //Join EPerson Community Admin Collections with Collection Admins
+ allCollections.addAll(allCommAdminCollections);
+
+ List collsAllowed = new ArrayList<>(allCollections);
+
+ //A community is passed, only the community's collections will be used and existing in eperson Authorizations
+ if (community != null) {
+ collsAllowed.retainAll(community.getCollections());
+ }
+
+ return collsAllowed;
+ }
+
@Override
public Collection findByGroup(Context context, Group group) throws SQLException {
return collectionDAO.findByGroup(context, group);
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 157b891486f0..99dc9459d84f 100644
--- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java
@@ -480,7 +480,7 @@ public void addBundle(Context context, Item item, Bundle bundle) throws SQLExcep
// now add authorization policies from owning item
// hmm, not very "multiple-inclusion" friendly
- authorizeService.inheritPolicies(context, item, bundle);
+ authorizeService.inheritPolicies(context, item, bundle, true);
// Add the bundle to in-memory list
item.addBundle(bundle);
@@ -1046,8 +1046,8 @@ public void adjustBundleBitstreamPolicies(Context context, Item item, Collection
// if come from InstallItem: remove all submission/workflow policies
authorizeService.removeAllPoliciesByDSOAndType(context, mybundle, ResourcePolicy.TYPE_SUBMISSION);
authorizeService.removeAllPoliciesByDSOAndType(context, mybundle, ResourcePolicy.TYPE_WORKFLOW);
- addCustomPoliciesNotInPlace(context, mybundle, defaultItemPolicies);
- addDefaultPoliciesNotInPlace(context, mybundle, defaultCollectionBundlePolicies);
+ authorizeService.addCustomPoliciesNotInPlace(context, mybundle, defaultItemPolicies);
+ authorizeService.addDefaultPoliciesNotInPlace(context, mybundle, defaultCollectionBundlePolicies);
for (Bitstream bitstream : mybundle.getBitstreams()) {
// If collection has default READ policies, remove the bundle's READ policies.
@@ -1093,8 +1093,8 @@ private void removeAllPoliciesAndAddDefault(Context context, Bitstream bitstream
throws SQLException, AuthorizeException {
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_SUBMISSION);
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_WORKFLOW);
- addCustomPoliciesNotInPlace(context, bitstream, defaultItemPolicies);
- addDefaultPoliciesNotInPlace(context, bitstream, defaultCollectionPolicies);
+ authorizeService.addCustomPoliciesNotInPlace(context, bitstream, defaultItemPolicies);
+ authorizeService.addDefaultPoliciesNotInPlace(context, bitstream, defaultCollectionPolicies);
}
@Override
@@ -1132,7 +1132,7 @@ public void adjustItemPolicies(Context context, Item item, Collection collection
authorizeService.removeAllPoliciesByDSOAndType(context, item, ResourcePolicy.TYPE_WORKFLOW);
// add default policies only if not already in place
- addDefaultPoliciesNotInPlace(context, item, defaultCollectionPolicies);
+ authorizeService.addDefaultPoliciesNotInPlace(context, item, defaultCollectionPolicies);
} finally {
context.restoreAuthSystemState();
}
@@ -1322,91 +1322,7 @@ public boolean isInProgressSubmission(Context context, Item item) throws SQLExce
*/
- /**
- * Add the default policies, which have not been already added to the given DSpace object
- *
- * @param context The relevant DSpace Context.
- * @param dso The DSpace Object to add policies to
- * @param defaultCollectionPolicies list of policies
- * @throws SQLException An exception that provides information on a database access error or other errors.
- * @throws AuthorizeException Exception indicating the current user of the context does not have permission
- * to perform a particular action.
- */
- protected void addDefaultPoliciesNotInPlace(Context context, DSpaceObject dso,
- List defaultCollectionPolicies) throws SQLException, AuthorizeException {
- boolean appendMode = configurationService
- .getBooleanProperty("core.authorization.installitem.inheritance-read.append-mode", false);
- for (ResourcePolicy defaultPolicy : defaultCollectionPolicies) {
- if (!authorizeService
- .isAnIdenticalPolicyAlreadyInPlace(context, dso, defaultPolicy.getGroup(), Constants.READ,
- defaultPolicy.getID()) &&
- (!appendMode && isNotAlreadyACustomRPOfThisTypeOnDSO(context, dso) ||
- appendMode && shouldBeAppended(context, dso, defaultPolicy))) {
- ResourcePolicy newPolicy = resourcePolicyService.clone(context, defaultPolicy);
- newPolicy.setdSpaceObject(dso);
- newPolicy.setAction(Constants.READ);
- newPolicy.setRpType(ResourcePolicy.TYPE_INHERITED);
- resourcePolicyService.update(context, newPolicy);
- }
- }
- }
- private void addCustomPoliciesNotInPlace(Context context, DSpaceObject dso, List customPolicies)
- throws SQLException, AuthorizeException {
- boolean customPoliciesAlreadyInPlace = authorizeService
- .findPoliciesByDSOAndType(context, dso, ResourcePolicy.TYPE_CUSTOM).size() > 0;
- if (!customPoliciesAlreadyInPlace) {
- authorizeService.addPolicies(context, customPolicies, dso);
- }
- }
-
- /**
- * Check whether or not there is already an RP on the given dso, which has actionId={@link Constants.READ} and
- * resourceTypeId={@link ResourcePolicy.TYPE_CUSTOM}
- *
- * @param context DSpace context
- * @param dso DSpace object to check for custom read RP
- * @return True if there is no RP on the item with custom read RP, otherwise false
- * @throws SQLException If something goes wrong retrieving the RP on the DSO
- */
- private boolean isNotAlreadyACustomRPOfThisTypeOnDSO(Context context, DSpaceObject dso) throws SQLException {
- List readRPs = resourcePolicyService.find(context, dso, Constants.READ);
- for (ResourcePolicy readRP : readRPs) {
- if (readRP.getRpType() != null && readRP.getRpType().equals(ResourcePolicy.TYPE_CUSTOM)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Check if the provided default policy should be appended or not to the final
- * item. If an item has at least one custom READ policy any anonymous READ
- * policy with empty start/end date should be skipped
- *
- * @param context DSpace context
- * @param dso DSpace object to check for custom read RP
- * @param defaultPolicy The policy to check
- * @return
- * @throws SQLException If something goes wrong retrieving the RP on the DSO
- */
- private boolean shouldBeAppended(Context context, DSpaceObject dso, ResourcePolicy defaultPolicy)
- throws SQLException {
- boolean hasCustomPolicy = resourcePolicyService.find(context, dso, Constants.READ)
- .stream()
- .filter(rp -> (Objects.nonNull(rp.getRpType()) &&
- Objects.equals(rp.getRpType(), ResourcePolicy.TYPE_CUSTOM)))
- .findFirst()
- .isPresent();
-
- boolean isAnonimousGroup = Objects.nonNull(defaultPolicy.getGroup())
- && StringUtils.equals(defaultPolicy.getGroup().getName(), Group.ANONYMOUS);
-
- boolean datesAreNull = Objects.isNull(defaultPolicy.getStartDate())
- && Objects.isNull(defaultPolicy.getEndDate());
-
- return !(hasCustomPolicy && isAnonimousGroup && datesAreNull);
- }
/**
* Returns an iterator of Items possessing the passed metadata field, or only
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java
index 444332df97d2..1bef8b389898 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java
@@ -34,23 +34,25 @@
* from {@code ${dspace.dir}/config/controlled-vocabularies/*.xml} and turns
* them into autocompleting authorities.
*
- * Configuration: This MUST be configured as a self-named plugin, e.g.: {@code
- * plugin.selfnamed.org.dspace.content.authority.ChoiceAuthority = \
+ *
Configuration: This MUST be configured as a self-named plugin, e.g.: {@code
+ * plugin.selfnamed.org.dspace.content.authority.ChoiceAuthority =
* org.dspace.content.authority.DSpaceControlledVocabulary
* }
*
- * It AUTOMATICALLY configures a plugin instance for each XML file in the
+ *
It AUTOMATICALLY configures a plugin instance for each XML file in the
* controlled vocabularies directory. The name of the plugin is the basename of
* the file; e.g., {@code ${dspace.dir}/config/controlled-vocabularies/nsi.xml}
* would generate a plugin called "nsi".
*
- * Each configured plugin comes with three configuration options: {@code
- * vocabulary.plugin._plugin_.hierarchy.store =
- * # Store entire hierarchy along with selected value. Default: TRUE
- * vocabulary.plugin._plugin_.hierarchy.suggest =
- * # Display entire hierarchy in the suggestion list. Default: TRUE
- * vocabulary.plugin._plugin_.delimiter = ""
- * # Delimiter to use when building hierarchy strings. Default: "::"
+ *
Each configured plugin comes with three configuration options:
+ *
+ *
{@code vocabulary.plugin._plugin_.hierarchy.store =
+ * # Store entire hierarchy along with selected value. Default: TRUE}
+ *
{@code vocabulary.plugin._plugin_.hierarchy.suggest =
+ * # Display entire hierarchy in the suggestion list. Default: TRUE}
+ *
{@code vocabulary.plugin._plugin_.delimiter = ""
+ * # Delimiter to use when building hierarchy strings. Default: "::"}
+ *
* }
*
* @author Michael B. Klein
@@ -58,11 +60,12 @@
public class DSpaceControlledVocabulary extends SelfNamedPlugin implements HierarchicalAuthority {
- private static Logger log = org.apache.logging.log4j.LogManager.getLogger(DSpaceControlledVocabulary.class);
+ private static final Logger log = org.apache.logging.log4j.LogManager.getLogger();
protected static String xpathTemplate = "//node[contains(translate(@label,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'," +
- "'abcdefghijklmnopqrstuvwxyz'),'%s')]";
- protected static String idTemplate = "//node[@id = '%s']";
- protected static String labelTemplate = "//node[@label = '%s']";
+ "'abcdefghijklmnopqrstuvwxyz'),%s)]";
+ protected static String idTemplate = "//node[@id = %s]";
+ protected static String idTemplateQuoted = "//node[@id = '%s']";
+ protected static String labelTemplate = "//node[@label = %s]";
protected static String idParentTemplate = "//node[@id = '%s']/parent::isComposedBy/parent::node";
protected static String rootTemplate = "/node";
protected static String pluginNames[] = null;
@@ -106,7 +109,7 @@ public boolean accept(File dir, String name) {
File.separator + "config" +
File.separator + "controlled-vocabularies";
String[] xmlFiles = (new File(vocabulariesPath)).list(new xmlFilter());
- List names = new ArrayList();
+ List names = new ArrayList<>();
for (String filename : xmlFiles) {
names.add((new File(filename)).getName().replace(".xml", ""));
}
@@ -162,14 +165,23 @@ protected String buildString(Node node) {
public Choices getMatches(String text, int start, int limit, String locale) {
init();
log.debug("Getting matches for '" + text + "'");
- String xpathExpression = "";
String[] textHierarchy = text.split(hierarchyDelimiter, -1);
+ StringBuilder xpathExpressionBuilder = new StringBuilder();
for (int i = 0; i < textHierarchy.length; i++) {
- xpathExpression += String.format(xpathTemplate, textHierarchy[i].replaceAll("'", "'").toLowerCase());
+ xpathExpressionBuilder.append(String.format(xpathTemplate, "$var" + i));
}
+ String xpathExpression = xpathExpressionBuilder.toString();
XPath xpath = XPathFactory.newInstance().newXPath();
- int total = 0;
- List choices = new ArrayList();
+ xpath.setXPathVariableResolver(variableName -> {
+ String varName = variableName.getLocalPart();
+ if (varName.startsWith("var")) {
+ int index = Integer.parseInt(varName.substring(3));
+ return textHierarchy[index].toLowerCase();
+ }
+ throw new IllegalArgumentException("Unexpected variable: " + varName);
+ });
+ int total;
+ List choices;
try {
NodeList results = (NodeList) xpath.evaluate(xpathExpression, vocabulary, XPathConstants.NODESET);
total = results.getLength();
@@ -185,14 +197,23 @@ public Choices getMatches(String text, int start, int limit, String locale) {
@Override
public Choices getBestMatch(String text, String locale) {
init();
- log.debug("Getting best matches for '" + text + "'");
- String xpathExpression = "";
+ log.debug("Getting best matches for {}'", text);
String[] textHierarchy = text.split(hierarchyDelimiter, -1);
+ StringBuilder xpathExpressionBuilder = new StringBuilder();
for (int i = 0; i < textHierarchy.length; i++) {
- xpathExpression += String.format(labelTemplate, textHierarchy[i].replaceAll("'", "'"));
+ xpathExpressionBuilder.append(String.format(labelTemplate, "$var" + i));
}
+ String xpathExpression = xpathExpressionBuilder.toString();
XPath xpath = XPathFactory.newInstance().newXPath();
- List choices = new ArrayList();
+ xpath.setXPathVariableResolver(variableName -> {
+ String varName = variableName.getLocalPart();
+ if (varName.startsWith("var")) {
+ int index = Integer.parseInt(varName.substring(3));
+ return textHierarchy[index];
+ }
+ throw new IllegalArgumentException("Unexpected variable: " + varName);
+ });
+ List choices;
try {
NodeList results = (NodeList) xpath.evaluate(xpathExpression, vocabulary, XPathConstants.NODESET);
choices = getChoicesFromNodeList(results, 0, 1);
@@ -240,7 +261,7 @@ public Choices getTopChoices(String authorityName, int start, int limit, String
@Override
public Choices getChoicesByParent(String authorityName, String parentId, int start, int limit, String locale) {
init();
- String xpathExpression = String.format(idTemplate, parentId);
+ String xpathExpression = String.format(idTemplateQuoted, parentId);
return getChoicesByXpath(xpathExpression, start, limit);
}
@@ -264,15 +285,12 @@ public Integer getPreloadLevel() {
}
private boolean isRootElement(Node node) {
- if (node != null && node.getOwnerDocument().getDocumentElement().equals(node)) {
- return true;
- }
- return false;
+ return node != null && node.getOwnerDocument().getDocumentElement().equals(node);
}
private Node getNode(String key) throws XPathExpressionException {
init();
- String xpathExpression = String.format(idTemplate, key);
+ String xpathExpression = String.format(idTemplateQuoted, key);
Node node = getNodeFromXPath(xpathExpression);
return node;
}
@@ -284,7 +302,7 @@ private Node getNodeFromXPath(String xpathExpression) throws XPathExpressionExce
}
private List getChoicesFromNodeList(NodeList results, int start, int limit) {
- List choices = new ArrayList();
+ List choices = new ArrayList<>();
for (int i = 0; i < results.getLength(); i++) {
if (i < start) {
continue;
@@ -303,17 +321,17 @@ private List getChoicesFromNodeList(NodeList results, int start, int lim
private Map addOtherInformation(String parentCurr, String noteCurr,
List childrenCurr, String authorityCurr) {
- Map extras = new HashMap();
+ Map extras = new HashMap<>();
if (StringUtils.isNotBlank(parentCurr)) {
extras.put("parent", parentCurr);
}
if (StringUtils.isNotBlank(noteCurr)) {
extras.put("note", noteCurr);
}
- if (childrenCurr.size() > 0) {
- extras.put("hasChildren", "true");
- } else {
+ if (childrenCurr.isEmpty()) {
extras.put("hasChildren", "false");
+ } else {
+ extras.put("hasChildren", "true");
}
extras.put("id", authorityCurr);
return extras;
@@ -368,7 +386,7 @@ private String getNote(Node node) {
}
private List getChildren(Node node) {
- List children = new ArrayList();
+ List children = new ArrayList<>();
NodeList childNodes = node.getChildNodes();
for (int ci = 0; ci < childNodes.getLength(); ci++) {
Node firstChild = childNodes.item(ci);
@@ -391,7 +409,7 @@ private List getChildren(Node node) {
private boolean isSelectable(Node node) {
Node selectableAttr = node.getAttributes().getNamedItem("selectable");
if (null != selectableAttr) {
- return Boolean.valueOf(selectableAttr.getNodeValue());
+ return Boolean.parseBoolean(selectableAttr.getNodeValue());
} else { // Default is true
return true;
}
@@ -418,7 +436,7 @@ private String getAuthority(Node node) {
}
private Choices getChoicesByXpath(String xpathExpression, int start, int limit) {
- List choices = new ArrayList();
+ List choices = new ArrayList<>();
XPath xpath = XPathFactory.newInstance().newXPath();
try {
Node parentNode = (Node) xpath.evaluate(xpathExpression, vocabulary, XPathConstants.NODE);
diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/PREMISCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/PREMISCrosswalk.java
index 39b6c8f29c80..6b6c0fd7c5a4 100644
--- a/dspace-api/src/main/java/org/dspace/content/crosswalk/PREMISCrosswalk.java
+++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/PREMISCrosswalk.java
@@ -20,9 +20,7 @@
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat;
-import org.dspace.content.Bundle;
import org.dspace.content.DSpaceObject;
-import org.dspace.content.Item;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
@@ -224,29 +222,17 @@ public Element disseminateElement(Context context, DSpaceObject dso)
// c. made-up name based on sequence ID and extension.
String sid = String.valueOf(bitstream.getSequenceID());
String baseUrl = configurationService.getProperty("dspace.ui.url");
- String handle = null;
- // get handle of parent Item of this bitstream, if there is one:
- List bn = bitstream.getBundles();
- if (bn.size() > 0) {
- List bi = bn.get(0).getItems();
- if (bi.size() > 0) {
- handle = bi.get(0).getHandle();
- }
- }
// get or make up name for bitstream:
String bsName = bitstream.getName();
if (bsName == null) {
List ext = bitstream.getFormat(context).getExtensions();
bsName = "bitstream_" + sid + (ext.size() > 0 ? ext.get(0) : "");
}
- if (handle != null && baseUrl != null) {
+ if (baseUrl != null) {
oiv.setText(baseUrl
- + "/bitstream/"
- + URLEncoder.encode(handle, "UTF-8")
- + "/"
- + sid
- + "/"
- + URLEncoder.encode(bsName, "UTF-8"));
+ + "/bitstreams/"
+ + bitstream.getID()
+ + "/download");
} else {
oiv.setText(URLEncoder.encode(bsName, "UTF-8"));
}
diff --git a/dspace-api/src/main/java/org/dspace/content/dao/CollectionDAO.java b/dspace-api/src/main/java/org/dspace/content/dao/CollectionDAO.java
index 6bb65bbb46d8..13bcf5f52c02 100644
--- a/dspace-api/src/main/java/org/dspace/content/dao/CollectionDAO.java
+++ b/dspace-api/src/main/java/org/dspace/content/dao/CollectionDAO.java
@@ -48,6 +48,18 @@ public List findAll(Context context, MetadataField order, Integer li
List findAuthorizedByGroup(Context context, EPerson ePerson, List actions) throws SQLException;
+ /**
+ * Get all authorized collections of the current EPerson
+ *
+ * @param context DSpace context object
+ * @param ePerson the current EPerson
+ * @param actions list of actionsID ADD, READ, etc.
+ * @return the collections the eperson is defined
+ * @throws SQLException if database error
+ */
+ List findAuthorizedByEPerson(Context context, EPerson ePerson, List actions)
+ throws SQLException;
+
List findCollectionsWithSubscribers(Context context) throws SQLException;
int countRows(Context context) throws SQLException;
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 25f102f6def4..66a775e39d80 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
@@ -178,7 +178,7 @@ public int countDeleted(Context context) throws SQLException {
@Override
public int countWithNoPolicy(Context context) throws SQLException {
Query query = createQuery(context,
- "SELECT count(bit.id) from Bitstream bit where bit.deleted<>true and bit.id not in" +
+ "SELECT count(bit.id) from Bitstream bit where bit.deleted<>true and bit not in" +
" (select res.dSpaceObject from ResourcePolicy res where res.resourceTypeId = " +
":typeId )");
query.setParameter("typeId", Constants.BITSTREAM);
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 841da319f0b2..e47b1ed4a02b 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
@@ -10,8 +10,13 @@
import java.sql.SQLException;
import java.util.AbstractMap;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.UUID;
import jakarta.persistence.Query;
import jakarta.persistence.criteria.CriteriaBuilder;
@@ -19,6 +24,7 @@
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
+import org.apache.logging.log4j.Logger;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.ResourcePolicy_;
import org.dspace.content.Collection;
@@ -40,6 +46,11 @@
* @author kevinvandevelde at atmire.com
*/
public class CollectionDAOImpl extends AbstractHibernateDSODAO implements CollectionDAO {
+ /**
+ * log4j logger
+ */
+ private static Logger log = org.apache.logging.log4j.LogManager.getLogger(CollectionDAOImpl.class);
+
protected CollectionDAOImpl() {
super();
}
@@ -157,9 +168,103 @@ public List findAuthorizedByGroup(Context context, EPerson ePerson,
}
+ /**
+ * Get all authorized collections of the current EPerson
+ *
+ * @param context DSpace context object
+ * @param ePerson the current EPerson
+ * @param actions list of actionsID ADD, READ, etc.
+ * @return the collections the eperson is defined
+ * @throws SQLException if database error
+ */
+ @Override
+ public List findAuthorizedByEPerson(Context context, EPerson ePerson, List actions)
+ throws SQLException {
+
+ //NOTE steps 1) and 2) removes the need of WITH RECURSIVE and a NativeQuery
+
+ // 1) Get all groups a eperson belongs
+ /*ArrayList<>(ePerson.getGroups()) - This ensures you have a concrete copy and can modify it safely.
+ instead if List directGroups = ePerson.getGroups();
+ Also - Can be done using this query:
+ List directGroups = createQuery(context, """
+ SELECT g
+ FROM Group g
+ JOIN g.epeople e
+ WHERE e.id = :epersonId
+ """)
+ .setParameter("epersonId", ePerson.getID())
+ .getResultList();
+ */
+ List directGroups = new ArrayList<>(ePerson.getGroups()); // direct membership
+
+ // 2) Expand hierarquy of groups in memory (recursively)
+ Set allGroups = new HashSet<>(directGroups);
+ Queue queue = new LinkedList<>(directGroups);
+
+ /*
+ * Using the query avoids the change of the getParentGroups visibility in Group
+ * The List parents = current.getParentGroups() could be achieved using:
+ * List parents = createQuery(context,"""
+ SELECT g
+ FROM Group g
+ JOIN g.groups child
+ WHERE child = :child
+ """)
+ */
+ // //current.getMemberGroups()- Making public getParentGroups in Group Class (why it isn't already public?)
+ while (!queue.isEmpty()) {
+ Group current = queue.poll();
+ List parents = current.getParentGroups();
+
+ for (Group parent : parents) {
+ if (allGroups.add(parent)) {
+ queue.add(parent);
+ }
+ }
+ }
+
+ CriteriaBuilder cb = getCriteriaBuilder(context);
+ CriteriaQuery cq = getCriteriaQuery(cb, Collection.class);
+ Root collectionRoot = cq.from(Collection.class);
+
+ // Join to ResourcePolicy using metamodel
+ Join rpJoin = collectionRoot.join("resourcePolicies");
+ // Use metamodel for typesafe access
+ cq.select(collectionRoot).distinct(true);
+
+ List predicates = new ArrayList<>(actions.size());
+ // WHERE rp.resourceTypeId = :resourceType
+ predicates.add(cb.equal(rpJoin.get(ResourcePolicy_.resourceTypeId), Constants.COLLECTION));
+ // AND (:hasActions = false OR rp.actionId IN :actionIds)
+ if (actions != null && !actions.isEmpty()) {
+ predicates.add(rpJoin.get(ResourcePolicy_.actionId).in(actions));
+ }
+
+ // AND (rp.eperson.id = :epersonId OR (:hasGroups = true AND rp.epersonGroup.id IN :groupIds))
+ Predicate epersonPredicate = cb.equal(
+ rpJoin.get(ResourcePolicy_.eperson), ePerson
+ );
+ // Using only groups instead of groupsIDs
+ Predicate groupPredicate = cb.disjunction(); // false by default
+ if (allGroups != null && !allGroups.isEmpty()) {
+ groupPredicate = rpJoin.get(ResourcePolicy_.epersonGroup).in(allGroups);
+ }
+
+ // Combine access condition
+ Predicate accessPredicate = cb.or(epersonPredicate, groupPredicate);
+ predicates.add(accessPredicate);
+
+ // Apply WHERE clause
+ cq.where(cb.and(predicates.toArray(new Predicate[0])));
+
+ // Execute
+ return list(context, cq, true, Collection.class, -1, -1);
+ }
+
@Override
public List findCollectionsWithSubscribers(Context context) throws SQLException {
- return list(createQuery(context, "SELECT DISTINCT c FROM Collection c JOIN Subscription s ON c.id = " +
+ return list(createQuery(context, "SELECT DISTINCT c FROM Collection c JOIN Subscription s ON c = " +
"s.dSpaceObject"));
}
@@ -172,15 +277,26 @@ public int countRows(Context context) throws SQLException {
@SuppressWarnings("unchecked")
public List> getCollectionsWithBitstreamSizesTotal(Context context)
throws SQLException {
- String q = "select col as collection, sum(bit.sizeBytes) as totalBytes from Item i join i.collections col " +
- "join i.bundles bun join bun.bitstreams bit group by col";
+ String q = "select col.id, sum(bit.sizeBytes) as totalBytes from Item i join i.collections col " +
+ "join i.bundles bun join bun.bitstreams bit group by col.id";
Query query = createQuery(context, q);
+ CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
+
List