mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Merge remote-tracking branch 'DSpace/main' into issue-8479-Regular_search_can_contain_private_withdrawn_items
# Conflicts: # dspace/config/spring/api/discovery.xml
This commit is contained in:
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -11,9 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
# Give Maven 1GB of memory to work with
|
||||
# Suppress all Maven "downloading" messages in logs (see https://stackoverflow.com/a/35653426)
|
||||
# This also slightly speeds builds, as there is less logging
|
||||
MAVEN_OPTS: "-Xmx1024M -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn"
|
||||
MAVEN_OPTS: "-Xmx1024M"
|
||||
strategy:
|
||||
# Create a matrix of two separate configurations for Unit vs Integration Tests
|
||||
# This will ensure those tasks are run in parallel
|
||||
@@ -67,7 +65,7 @@ jobs:
|
||||
- name: Run Maven ${{ matrix.type }}
|
||||
env:
|
||||
TEST_FLAGS: ${{ matrix.mvnflags }}
|
||||
run: mvn install -B -V -P-assembly -Pcoverage-report $TEST_FLAGS
|
||||
run: mvn --no-transfer-progress -V install -P-assembly -Pcoverage-report $TEST_FLAGS
|
||||
|
||||
# If previous step failed, save results of tests to downloadable artifact for this job
|
||||
# (This artifact is downloadable at the bottom of any job's summary page)
|
||||
|
15
.github/workflows/docker.yml
vendored
15
.github/workflows/docker.yml
vendored
@@ -31,6 +31,11 @@ jobs:
|
||||
# We turn off 'latest' tag by default.
|
||||
TAGS_FLAVOR: |
|
||||
latest=false
|
||||
# Architectures / Platforms for which we will build Docker images
|
||||
# If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work.
|
||||
# If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. NOTE: The ARM64 build takes MUCH
|
||||
# longer (around 45mins or so) which is why we only run it when pushing a new Docker image.
|
||||
PLATFORMS: linux/amd64${{ github.event_name != 'pull_request' && ', linux/arm64' || '' }}
|
||||
|
||||
steps:
|
||||
# https://github.com/actions/checkout
|
||||
@@ -41,6 +46,10 @@ jobs:
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
# https://github.com/docker/setup-qemu-action
|
||||
- name: Set up QEMU emulation to build for multiple architectures
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
# https://github.com/docker/login-action
|
||||
- name: Login to DockerHub
|
||||
# Only login if not a PR, as PRs only trigger a Docker build and not a push
|
||||
@@ -70,6 +79,7 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.dependencies
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
@@ -95,6 +105,7 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
@@ -123,6 +134,7 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.test
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
@@ -148,9 +160,10 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.cli
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
# Use tags / labels provided by 'docker/metadata-action' above
|
||||
tags: ${{ steps.meta_build_cli.outputs.tags }}
|
||||
labels: ${{ steps.meta_build_cli.outputs.labels }}
|
||||
labels: ${{ steps.meta_build_cli.outputs.labels }}
|
||||
|
@@ -20,7 +20,7 @@ USER dspace
|
||||
ADD --chown=dspace . /app/
|
||||
# Build DSpace (note: this build doesn't include the optional, deprecated "dspace-rest" webapp)
|
||||
# Copy the dspace-installer directory to /install. Clean up the build to keep the docker image small
|
||||
RUN mvn package && \
|
||||
RUN mvn --no-transfer-progress package && \
|
||||
mv /app/dspace/target/${TARGET_DIR}/* /install && \
|
||||
mvn clean
|
||||
|
||||
|
@@ -19,7 +19,7 @@ USER dspace
|
||||
# Copy the DSpace source code (from local machine) into the workdir (excluding .dockerignore contents)
|
||||
ADD --chown=dspace . /app/
|
||||
# Build DSpace. Copy the dspace-installer directory to /install. Clean up the build to keep the docker image small
|
||||
RUN mvn package && \
|
||||
RUN mvn --no-transfer-progress package && \
|
||||
mv /app/dspace/target/${TARGET_DIR}/* /install && \
|
||||
mvn clean
|
||||
|
||||
|
@@ -22,7 +22,7 @@ USER dspace
|
||||
ADD --chown=dspace . /app/
|
||||
# Build DSpace (INCLUDING the optional, deprecated "dspace-rest" webapp)
|
||||
# Copy the dspace-installer directory to /install. Clean up the build to keep the docker image small
|
||||
RUN mvn package -Pdspace-rest && \
|
||||
RUN mvn --no-transfer-progress package -Pdspace-rest && \
|
||||
mv /app/dspace/target/${TARGET_DIR}/* /install && \
|
||||
mvn clean
|
||||
|
||||
|
@@ -25,24 +25,25 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* AWS Java SDK for AWS KMS (com.amazonaws:aws-java-sdk-kms:1.12.116 - https://aws.amazon.com/sdkforjava)
|
||||
* AWS Java SDK for Amazon S3 (com.amazonaws:aws-java-sdk-s3:1.12.116 - https://aws.amazon.com/sdkforjava)
|
||||
* JMES Path Query library (com.amazonaws:jmespath-java:1.12.116 - https://aws.amazon.com/sdkforjava)
|
||||
* jcommander (com.beust:jcommander:1.78 - https://jcommander.org)
|
||||
* HPPC Collections (com.carrotsearch:hppc:0.8.1 - http://labs.carrotsearch.com/hppc.html/hppc)
|
||||
* parso (com.epam:parso:2.0.11 - https://github.com/epam/parso)
|
||||
* com.drewnoakes:metadata-extractor (com.drewnoakes:metadata-extractor:2.16.0 - https://drewnoakes.com/code/exif/)
|
||||
* parso (com.epam:parso:2.0.14 - https://github.com/epam/parso)
|
||||
* Esri Geometry API for Java (com.esri.geometry:esri-geometry-api:2.2.0 - https://github.com/Esri/geometry-api-java)
|
||||
* ClassMate (com.fasterxml:classmate:1.3.0 - http://github.com/cowtowncoder/java-classmate)
|
||||
* Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.12.3 - http://github.com/FasterXML/jackson)
|
||||
* Jackson-core (com.fasterxml.jackson.core:jackson-core:2.12.3 - https://github.com/FasterXML/jackson-core)
|
||||
* jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.12.3 - http://github.com/FasterXML/jackson)
|
||||
* Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.12.6 - http://github.com/FasterXML/jackson)
|
||||
* Jackson-core (com.fasterxml.jackson.core:jackson-core:2.12.6 - https://github.com/FasterXML/jackson-core)
|
||||
* jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.12.6.1 - http://github.com/FasterXML/jackson)
|
||||
* Jackson dataformat: CBOR (com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.12.3 - http://github.com/FasterXML/jackson-dataformats-binary)
|
||||
* Jackson dataformat: Smile (com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.11.2 - http://github.com/FasterXML/jackson-dataformats-binary)
|
||||
* Jackson dataformat: Smile (com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.12.3 - http://github.com/FasterXML/jackson-dataformats-binary)
|
||||
* Jackson-dataformat-YAML (com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.11.1 - https://github.com/FasterXML/jackson-dataformats-text)
|
||||
* Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8)
|
||||
* Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310)
|
||||
* Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8)
|
||||
* Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.1 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310)
|
||||
* Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names)
|
||||
* Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310)
|
||||
* Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names)
|
||||
* Java UUID Generator (com.fasterxml.uuid:java-uuid-generator:4.0.1 - https://github.com/cowtowncoder/java-uuid-generator)
|
||||
* Woodstox (com.fasterxml.woodstox:woodstox-core:5.0.3 - https://github.com/FasterXML/woodstox)
|
||||
* Woodstox (com.fasterxml.woodstox:woodstox-core:6.2.4 - https://github.com/FasterXML/woodstox)
|
||||
* zjsonpatch (com.flipkart.zjsonpatch:zjsonpatch:0.4.6 - https://github.com/flipkart-incubator/zjsonpatch/)
|
||||
* Caffeine cache (com.github.ben-manes.caffeine:caffeine:2.8.4 - https://github.com/ben-manes/caffeine)
|
||||
* Caffeine cache (com.github.ben-manes.caffeine:caffeine:2.9.2 - https://github.com/ben-manes/caffeine)
|
||||
* 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)
|
||||
@@ -50,28 +51,27 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* json-schema-validator (com.github.java-json-tools:json-schema-validator:2.2.14 - https://github.com/java-json-tools/json-schema-validator)
|
||||
* msg-simple (com.github.java-json-tools:msg-simple:1.2 - https://github.com/java-json-tools/msg-simple)
|
||||
* uri-template (com.github.java-json-tools:uri-template:0.10 - https://github.com/java-json-tools/uri-template)
|
||||
* Open JSON (com.github.openjson:openjson:1.0.12 - https://github.com/openjson/openjson)
|
||||
* JCIP Annotations under Apache License (com.github.stephenc.jcip:jcip-annotations:1.0-1 - http://stephenc.github.com/jcip-annotations)
|
||||
* Google APIs Client Library for Java (com.google.api-client:google-api-client:1.23.0 - https://github.com/google/google-api-java-client/google-api-client)
|
||||
* Google Analytics API v3-rev145-1.23.0 (com.google.apis:google-api-services-analytics:v3-rev145-1.23.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-analytics)
|
||||
* FindBugs-jsr305 (com.google.code.findbugs:jsr305:3.0.1 - http://findbugs.sourceforge.net/)
|
||||
* Gson (com.google.code.gson:gson:2.8.6 - https://github.com/google/gson/gson)
|
||||
* error-prone annotations (com.google.errorprone:error_prone_annotations:2.3.4 - http://nexus.sonatype.org/oss-repository-hosting.html/error_prone_parent/error_prone_annotations)
|
||||
* Gson (com.google.code.gson:gson:2.9.0 - https://github.com/google/gson/gson)
|
||||
* error-prone annotations (com.google.errorprone:error_prone_annotations:2.7.1 - http://nexus.sonatype.org/oss-repository-hosting.html/error_prone_parent/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:30.0-jre - https://github.com/google/guava/guava)
|
||||
* Guava: Google Core Libraries for Java (com.google.guava:guava:31.0.1-jre - https://github.com/google/guava)
|
||||
* Guava: Google Core Libraries for Java (JDK5 Backport) (com.google.guava:guava-jdk5:17.0 - http://code.google.com/p/guava-libraries/guava-jdk5)
|
||||
* Guava ListenableFuture only (com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava - https://github.com/google/guava/listenablefuture)
|
||||
* Google HTTP Client Library for Java (com.google.http-client:google-http-client:1.23.0 - https://github.com/google/google-http-java-client/google-http-client)
|
||||
* GSON extensions to the Google HTTP Client Library for Java. (com.google.http-client:google-http-client-gson:1.41.7 - https://github.com/googleapis/google-http-java-client/google-http-client-gson)
|
||||
* Jackson 2 extensions to the Google HTTP Client Library for Java. (com.google.http-client:google-http-client-jackson2:1.23.0 - https://github.com/google/google-http-java-client/google-http-client-jackson2)
|
||||
* J2ObjC Annotations (com.google.j2objc:j2objc-annotations:1.3 - https://github.com/google/j2objc/)
|
||||
* Google OAuth Client Library for Java (com.google.oauth-client:google-oauth-client:1.32.1 - https://github.com/googleapis/google-oauth-java-client/google-oauth-client)
|
||||
* Google OAuth Client Library for Java (com.google.oauth-client:google-oauth-client:1.33.3 - https://github.com/googleapis/google-oauth-java-client/google-oauth-client)
|
||||
* ConcurrentLinkedHashMap (com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2 - http://code.google.com/p/concurrentlinkedhashmap)
|
||||
* JSON.simple (com.googlecode.json-simple:json-simple:1.1.1 - http://code.google.com/p/json-simple/)
|
||||
* libphonenumber (com.googlecode.libphonenumber:libphonenumber:8.11.1 - https://github.com/google/libphonenumber/)
|
||||
* Jackcess (com.healthmarketscience.jackcess:jackcess:3.0.1 - https://jackcess.sourceforge.io)
|
||||
* Jackcess Encrypt (com.healthmarketscience.jackcess:jackcess-encrypt:3.0.0 - http://jackcessencrypt.sf.net)
|
||||
* project ':json-path' (com.jayway.jsonpath:json-path:2.4.0 - https://github.com/jayway/JsonPath)
|
||||
* project ':json-path-assert' (com.jayway.jsonpath:json-path-assert:2.4.0 - https://github.com/jayway/JsonPath)
|
||||
* Jackcess (com.healthmarketscience.jackcess:jackcess:4.0.1 - https://jackcess.sourceforge.io)
|
||||
* Jackcess Encrypt (com.healthmarketscience.jackcess:jackcess-encrypt:4.0.1 - http://jackcessencrypt.sf.net)
|
||||
* project ':json-path' (com.jayway.jsonpath:json-path:2.6.0 - https://github.com/jayway/JsonPath)
|
||||
* project ':json-path-assert' (com.jayway.jsonpath:json-path-assert:2.6.0 - https://github.com/jayway/JsonPath)
|
||||
* Disruptor Framework (com.lmax:disruptor:3.4.2 - http://lmax-exchange.github.com/disruptor)
|
||||
* builder-commons (com.lyncode:builder-commons:1.0.2 - http://nexus.sonatype.org/oss-repository-hosting.html/builder-commons)
|
||||
* MaxMind DB Reader (com.maxmind.db:maxmind-db:1.2.2 - http://dev.maxmind.com/)
|
||||
@@ -79,12 +79,12 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* Nimbus JOSE+JWT (com.nimbusds:nimbus-jose-jwt:7.9 - https://bitbucket.org/connect2id/nimbus-jose-jwt)
|
||||
* opencsv (com.opencsv:opencsv:5.2 - http://opencsv.sf.net)
|
||||
* java-libpst (com.pff:java-libpst:0.9.3 - https://github.com/rjohnsondev/java-libpst)
|
||||
* rome (com.rometools:rome:1.12.2 - http://rometools.com/rome)
|
||||
* rome-utils (com.rometools:rome-utils:1.12.2 - http://rometools.com/rome-utils)
|
||||
* rome (com.rometools:rome:1.18.0 - http://rometools.com/rome)
|
||||
* rome-modules (com.rometools:rome-modules:1.18.0 - http://rometools.com/rome-modules)
|
||||
* rome-utils (com.rometools:rome-utils:1.18.0 - http://rometools.com/rome-utils)
|
||||
* fastinfoset (com.sun.xml.fastinfoset:FastInfoset:1.2.15 - http://fi.java.net)
|
||||
* T-Digest (com.tdunning:t-digest:3.1 - https://github.com/tdunning/t-digest)
|
||||
* JSON library from Android SDK (com.vaadin.external.google:android-json:0.0.20131108.vaadin1 - http://developer.android.com/sdk)
|
||||
* HikariCP (com.zaxxer:HikariCP-java7:2.4.13 - https://github.com/brettwooldridge/HikariCP)
|
||||
* SparseBitSet (com.zaxxer:SparseBitSet:1.2 - https://github.com/brettwooldridge/SparseBitSet)
|
||||
* Apache Commons BeanUtils (commons-beanutils:commons-beanutils:1.9.4 - https://commons.apache.org/proper/commons-beanutils/)
|
||||
* Apache Commons CLI (commons-cli:commons-cli:1.4 - http://commons.apache.org/proper/commons-cli/)
|
||||
@@ -98,30 +98,24 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* Apache Commons Validator (commons-validator:commons-validator:1.5.0 - http://commons.apache.org/proper/commons-validator/)
|
||||
* GeoJson POJOs for Jackson (de.grundid.opendatalab:geojson-jackson:1.14 - https://github.com/opendatalab-de/geojson-jackson)
|
||||
* Boilerpipe -- Boilerplate Removal and Fulltext Extraction from HTML pages (de.l3s.boilerpipe:boilerpipe:1.1.0 - http://code.google.com/p/boilerpipe/)
|
||||
* SentimentAnalysisParser (edu.usc.ir:sentiment-analysis-parser:0.1 - https://github.com/USCDataScience/SentimentAnalysisParser)
|
||||
* OpenAIRE Funders Model (eu.openaire:funders-model:2.0.0 - https://api.openaire.eu)
|
||||
* Metrics Core (io.dropwizard.metrics:metrics-core:4.1.5 - https://metrics.dropwizard.io/metrics-core)
|
||||
* Graphite Integration for Metrics (io.dropwizard.metrics:metrics-graphite:4.1.5 - https://metrics.dropwizard.io/metrics-graphite)
|
||||
* Metrics Integration for Jetty 9.3 and higher (io.dropwizard.metrics:metrics-jetty9:4.1.5 - https://metrics.dropwizard.io/metrics-jetty9)
|
||||
* 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)
|
||||
* Netty (io.netty:netty:3.10.6.Final - http://netty.io/)
|
||||
* Netty/Buffer (io.netty:netty-buffer:4.1.50.Final - https://netty.io/netty-buffer/)
|
||||
* micrometer-core (io.micrometer:micrometer-core:1.8.6 - https://github.com/micrometer-metrics/micrometer)
|
||||
* Netty/Buffer (io.netty:netty-buffer:4.1.68.Final - https://netty.io/netty-buffer/)
|
||||
* Netty/Codec (io.netty:netty-codec:4.1.50.Final - https://netty.io/netty-codec/)
|
||||
* Netty/Codec (io.netty:netty-codec:4.1.68.Final - https://netty.io/netty-codec/)
|
||||
* Netty/Codec/HTTP (io.netty:netty-codec-http:4.1.53.Final - https://netty.io/netty-codec-http/)
|
||||
* Netty/Codec/Socks (io.netty:netty-codec-socks:4.1.53.Final - https://netty.io/netty-codec-socks/)
|
||||
* Netty/Common (io.netty:netty-common:4.1.50.Final - https://netty.io/netty-common/)
|
||||
* Netty/Common (io.netty:netty-common:4.1.68.Final - https://netty.io/netty-common/)
|
||||
* Netty/Handler (io.netty:netty-handler:4.1.50.Final - https://netty.io/netty-handler/)
|
||||
* Netty/Handler (io.netty:netty-handler:4.1.68.Final - https://netty.io/netty-handler/)
|
||||
* Netty/Handler/Proxy (io.netty:netty-handler-proxy:4.1.53.Final - https://netty.io/netty-handler-proxy/)
|
||||
* Netty/Resolver (io.netty:netty-resolver:4.1.50.Final - https://netty.io/netty-resolver/)
|
||||
* Netty/Transport (io.netty:netty-transport:4.1.50.Final - https://netty.io/netty-transport/)
|
||||
* Netty/Resolver (io.netty:netty-resolver:4.1.68.Final - https://netty.io/netty-resolver/)
|
||||
* Netty/Transport (io.netty:netty-transport:4.1.68.Final - https://netty.io/netty-transport/)
|
||||
* Netty/Transport/Native/Epoll (io.netty:netty-transport-native-epoll:4.1.50.Final - https://netty.io/netty-transport-native-epoll/)
|
||||
* Netty/Transport/Native/Unix/Common (io.netty:netty-transport-native-unix-common:4.1.50.Final - https://netty.io/netty-transport-native-unix-common/)
|
||||
* Netty/Transport/Native/Epoll (io.netty:netty-transport-native-epoll:4.1.68.Final - https://netty.io/netty-transport-native-epoll/)
|
||||
* Netty/Transport/Native/Unix/Common (io.netty:netty-transport-native-unix-common:4.1.68.Final - https://netty.io/netty-transport-native-unix-common/)
|
||||
* OpenTracing API (io.opentracing:opentracing-api:0.33.0 - https://github.com/opentracing/opentracing-java/opentracing-api)
|
||||
* OpenTracing-noop (io.opentracing:opentracing-noop:0.33.0 - https://github.com/opentracing/opentracing-java/opentracing-noop)
|
||||
* OpenTracing-util (io.opentracing:opentracing-util:0.33.0 - https://github.com/opentracing/opentracing-java/opentracing-util)
|
||||
@@ -147,28 +141,27 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* Byte Buddy (without dependencies) (net.bytebuddy:byte-buddy:1.11.13 - 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.5.0 - https://github.com/java-native-access/jna)
|
||||
* json-unit-core (net.javacrumbs.json-unit:json-unit-core:2.19.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:1.2 - http://www.minidev.net/)
|
||||
* ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.4.7 - https://urielch.github.io/)
|
||||
* JSON Small and Fast Parser (net.minidev:json-smart:2.3 - http://www.minidev.net/)
|
||||
* ehcache (net.sf.ehcache:ehcache:2.10.6 - http://ehcache.org)
|
||||
* Ehcache Core (net.sf.ehcache:ehcache-core:2.6.11 - http://ehcache.org)
|
||||
* JSON Small and Fast Parser (net.minidev:json-smart:2.4.7 - 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)
|
||||
* Apache Ant Core (org.apache.ant:ant:1.10.11 - https://ant.apache.org/)
|
||||
* Apache Ant Launcher (org.apache.ant:ant-launcher:1.10.11 - https://ant.apache.org/)
|
||||
* Apache Commons BCEL (org.apache.bcel:bcel:6.4.0 - https://commons.apache.org/proper/commons-bcel)
|
||||
* Calcite Core (org.apache.calcite:calcite-core:1.18.0 - https://calcite.apache.org/calcite-core)
|
||||
* Calcite Linq4j (org.apache.calcite:calcite-linq4j:1.18.0 - https://calcite.apache.org/calcite-linq4j)
|
||||
* Apache Calcite Avatica (org.apache.calcite.avatica:avatica-core:1.13.0 - https://calcite.apache.org/avatica/avatica-core)
|
||||
* Calcite Core (org.apache.calcite:calcite-core:1.27.0 - https://calcite.apache.org)
|
||||
* Calcite Linq4j (org.apache.calcite:calcite-linq4j:1.27.0 - https://calcite.apache.org)
|
||||
* Apache Calcite Avatica (org.apache.calcite.avatica:avatica-core:1.18.0 - https://calcite.apache.org/avatica)
|
||||
* Apache Commons Collections (org.apache.commons:commons-collections4:4.1 - http://commons.apache.org/proper/commons-collections/)
|
||||
* Apache Commons Compress (org.apache.commons:commons-compress:1.20 - https://commons.apache.org/proper/commons-compress/)
|
||||
* Apache Commons Compress (org.apache.commons:commons-compress:1.21 - https://commons.apache.org/proper/commons-compress/)
|
||||
* Apache Commons Configuration (org.apache.commons:commons-configuration2:2.7 - https://commons.apache.org/proper/commons-configuration/)
|
||||
* Apache Commons CSV (org.apache.commons:commons-csv:1.8 - https://commons.apache.org/proper/commons-csv/)
|
||||
* Apache Commons CSV (org.apache.commons:commons-csv:1.9.0 - https://commons.apache.org/proper/commons-csv/)
|
||||
* Apache Commons DBCP (org.apache.commons:commons-dbcp2:2.8.0 - https://commons.apache.org/dbcp/)
|
||||
* Apache Commons Exec (org.apache.commons:commons-exec:1.3 - http://commons.apache.org/proper/commons-exec/)
|
||||
* Apache Commons Lang (org.apache.commons:commons-lang3:3.7 - http://commons.apache.org/proper/commons-lang/)
|
||||
* Apache Commons Lang (org.apache.commons:commons-lang3:3.12.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.9.0 - https://commons.apache.org/proper/commons-pool/)
|
||||
* Apache Commons Text (org.apache.commons:commons-text:1.8 - https://commons.apache.org/proper/commons-text)
|
||||
@@ -176,24 +169,17 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* 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)
|
||||
* Apache CXF Core (org.apache.cxf:cxf-core:3.3.6 - https://cxf.apache.org)
|
||||
* Apache CXF Runtime JAX-RS Frontend (org.apache.cxf:cxf-rt-frontend-jaxrs:3.3.6 - https://cxf.apache.org)
|
||||
* Apache CXF JAX-RS Client (org.apache.cxf:cxf-rt-rs-client:3.3.6 - https://cxf.apache.org)
|
||||
* Apache CXF Runtime Security functionality (org.apache.cxf:cxf-rt-security:3.3.6 - https://cxf.apache.org)
|
||||
* Apache CXF Runtime HTTP Transport (org.apache.cxf:cxf-rt-transports-http:3.3.6 - https://cxf.apache.org)
|
||||
* JTA 1.1 (org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1.1 - http://geronimo.apache.org/specs/geronimo-jta_1.1_spec)
|
||||
* Web Services Metadata 2.0 (org.apache.geronimo.specs:geronimo-ws-metadata_2.0_spec:1.1.3 - http://geronimo.apache.org/maven/specs/geronimo-ws-metadata_2.0_spec/1.1.3)
|
||||
* Apache Hadoop Annotations (org.apache.hadoop:hadoop-annotations:3.2.0 - no url defined)
|
||||
* Apache Hadoop Auth (org.apache.hadoop:hadoop-auth:3.2.0 - no url defined)
|
||||
* Apache Hadoop Common (org.apache.hadoop:hadoop-common:3.2.0 - no url defined)
|
||||
* Apache Hadoop HDFS Client (org.apache.hadoop:hadoop-hdfs-client:3.2.0 - no url defined)
|
||||
* Apache Hadoop Annotations (org.apache.hadoop:hadoop-annotations:3.2.2 - no url defined)
|
||||
* Apache Hadoop Auth (org.apache.hadoop:hadoop-auth:3.2.2 - no url defined)
|
||||
* Apache Hadoop Common (org.apache.hadoop:hadoop-common:3.2.2 - no url defined)
|
||||
* Apache Hadoop HDFS Client (org.apache.hadoop:hadoop-hdfs-client:3.2.2 - no url defined)
|
||||
* htrace-core4 (org.apache.htrace:htrace-core4:4.1.0-incubating - http://incubator.apache.org/projects/htrace.html)
|
||||
* Apache HttpClient (org.apache.httpcomponents:httpclient:4.5.13 - http://hc.apache.org/httpcomponents-client)
|
||||
* Apache HttpClient Cache (org.apache.httpcomponents:httpclient-cache:4.2.6 - http://hc.apache.org/httpcomponents-client)
|
||||
* Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.4 - http://hc.apache.org/httpcomponents-core-ga)
|
||||
* Apache HttpClient Mime (org.apache.httpcomponents:httpmime:4.5.12 - http://hc.apache.org/httpcomponents-client)
|
||||
* Apache James :: Mime4j :: Core (org.apache.james:apache-mime4j-core:0.8.3 - http://james.apache.org/mime4j/apache-mime4j-core)
|
||||
* Apache James :: Mime4j :: DOM (org.apache.james:apache-mime4j-dom:0.8.3 - http://james.apache.org/mime4j/apache-mime4j-dom)
|
||||
* Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.15 - http://hc.apache.org/httpcomponents-core-ga)
|
||||
* Apache HttpClient Mime (org.apache.httpcomponents:httpmime:4.5.13 - http://hc.apache.org/httpcomponents-client)
|
||||
* Apache James :: Mime4j :: Core (org.apache.james:apache-mime4j-core:0.8.4 - http://james.apache.org/mime4j/apache-mime4j-core)
|
||||
* Apache James :: Mime4j :: DOM (org.apache.james:apache-mime4j-dom:0.8.4 - http://james.apache.org/mime4j/apache-mime4j-dom)
|
||||
* Apache Jena - Libraries POM (org.apache.jena:apache-jena-libs:2.13.0 - http://jena.apache.org/apache-jena-libs/)
|
||||
* Apache Jena - ARQ (SPARQL 1.1 Query Engine) (org.apache.jena:jena-arq:2.13.0 - http://jena.apache.org/jena-arq/)
|
||||
* Apache Jena - Core (org.apache.jena:jena-core:2.13.0 - http://jena.apache.org/jena-core/)
|
||||
@@ -207,121 +193,131 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* Apache Log4j API (org.apache.logging.log4j:log4j-api:2.17.1 - https://logging.apache.org/log4j/2.x/log4j-api/)
|
||||
* Apache Log4j Core (org.apache.logging.log4j:log4j-core:2.17.1 - https://logging.apache.org/log4j/2.x/log4j-core/)
|
||||
* Apache Log4j JUL Adapter (org.apache.logging.log4j:log4j-jul:2.17.1 - https://logging.apache.org/log4j/2.x/log4j-jul/)
|
||||
* Apache Log4j Layout for JSON template (org.apache.logging.log4j:log4j-layout-template-json:2.16.0 - https://logging.apache.org/log4j/2.x/log4j-layout-template-json/)
|
||||
* Apache Log4j SLF4J Binding (org.apache.logging.log4j:log4j-slf4j-impl:2.17.1 - https://logging.apache.org/log4j/2.x/log4j-slf4j-impl/)
|
||||
* Apache Log4j Web (org.apache.logging.log4j:log4j-web:2.17.1 - https://logging.apache.org/log4j/2.x/log4j-web/)
|
||||
* Lucene Common Analyzers (org.apache.lucene:lucene-analyzers-common:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-common)
|
||||
* Lucene ICU Analysis Components (org.apache.lucene:lucene-analyzers-icu:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-icu)
|
||||
* Lucene Kuromoji Japanese Morphological Analyzer (org.apache.lucene:lucene-analyzers-kuromoji:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-kuromoji)
|
||||
* Lucene Nori Korean Morphological Analyzer (org.apache.lucene:lucene-analyzers-nori:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-nori)
|
||||
* Lucene Phonetic Filters (org.apache.lucene:lucene-analyzers-phonetic:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-phonetic)
|
||||
* Lucene Smart Chinese Analyzer (org.apache.lucene:lucene-analyzers-smartcn:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-smartcn)
|
||||
* Lucene Stempel Analyzer (org.apache.lucene:lucene-analyzers-stempel:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-stempel)
|
||||
* Lucene Memory (org.apache.lucene:lucene-backward-codecs:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-backward-codecs)
|
||||
* Lucene Classification (org.apache.lucene:lucene-classification:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-classification)
|
||||
* Lucene codecs (org.apache.lucene:lucene-codecs:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-codecs)
|
||||
* Lucene Core (org.apache.lucene:lucene-core:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-core)
|
||||
* Lucene Expressions (org.apache.lucene:lucene-expressions:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-expressions)
|
||||
* Lucene Grouping (org.apache.lucene:lucene-grouping:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-grouping)
|
||||
* Lucene Highlighter (org.apache.lucene:lucene-highlighter:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-highlighter)
|
||||
* Lucene Join (org.apache.lucene:lucene-join:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-join)
|
||||
* Lucene Memory (org.apache.lucene:lucene-memory:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-memory)
|
||||
* Lucene Miscellaneous (org.apache.lucene:lucene-misc:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-misc)
|
||||
* Lucene Queries (org.apache.lucene:lucene-queries:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-queries)
|
||||
* Lucene QueryParsers (org.apache.lucene:lucene-queryparser:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-queryparser)
|
||||
* Lucene Sandbox (org.apache.lucene:lucene-sandbox:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-sandbox)
|
||||
* Lucene Spatial Extras (org.apache.lucene:lucene-spatial-extras:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-spatial-extras)
|
||||
* Lucene Spatial 3D (org.apache.lucene:lucene-spatial3d:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-spatial3d)
|
||||
* Lucene Suggest (org.apache.lucene:lucene-suggest:8.8.1 - https://lucene.apache.org/lucene-parent/lucene-suggest)
|
||||
* Apache OpenNLP Tools (org.apache.opennlp:opennlp-tools:1.9.2 - https://www.apache.org/opennlp/opennlp-tools/)
|
||||
* Lucene Common Analyzers (org.apache.lucene:lucene-analyzers-common:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-common)
|
||||
* Lucene ICU Analysis Components (org.apache.lucene:lucene-analyzers-icu:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-icu)
|
||||
* Lucene Kuromoji Japanese Morphological Analyzer (org.apache.lucene:lucene-analyzers-kuromoji:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-kuromoji)
|
||||
* Lucene Nori Korean Morphological Analyzer (org.apache.lucene:lucene-analyzers-nori:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-nori)
|
||||
* Lucene Phonetic Filters (org.apache.lucene:lucene-analyzers-phonetic:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-phonetic)
|
||||
* Lucene Smart Chinese Analyzer (org.apache.lucene:lucene-analyzers-smartcn:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-smartcn)
|
||||
* Lucene Stempel Analyzer (org.apache.lucene:lucene-analyzers-stempel:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-analyzers-stempel)
|
||||
* Lucene Memory (org.apache.lucene:lucene-backward-codecs:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-backward-codecs)
|
||||
* Lucene Classification (org.apache.lucene:lucene-classification:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-classification)
|
||||
* Lucene codecs (org.apache.lucene:lucene-codecs:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-codecs)
|
||||
* Lucene Core (org.apache.lucene:lucene-core:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-core)
|
||||
* Lucene Expressions (org.apache.lucene:lucene-expressions:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-expressions)
|
||||
* Lucene Grouping (org.apache.lucene:lucene-grouping:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-grouping)
|
||||
* Lucene Highlighter (org.apache.lucene:lucene-highlighter:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-highlighter)
|
||||
* Lucene Join (org.apache.lucene:lucene-join:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-join)
|
||||
* Lucene Memory (org.apache.lucene:lucene-memory:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-memory)
|
||||
* Lucene Miscellaneous (org.apache.lucene:lucene-misc:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-misc)
|
||||
* Lucene Queries (org.apache.lucene:lucene-queries:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-queries)
|
||||
* Lucene QueryParsers (org.apache.lucene:lucene-queryparser:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-queryparser)
|
||||
* Lucene Sandbox (org.apache.lucene:lucene-sandbox:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-sandbox)
|
||||
* Lucene Spatial Extras (org.apache.lucene:lucene-spatial-extras:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-spatial-extras)
|
||||
* Lucene Spatial 3D (org.apache.lucene:lucene-spatial3d:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-spatial3d)
|
||||
* Lucene Suggest (org.apache.lucene:lucene-suggest:8.11.1 - https://lucene.apache.org/lucene-parent/lucene-suggest)
|
||||
* Apache FontBox (org.apache.pdfbox:fontbox:2.0.24 - http://pdfbox.apache.org/)
|
||||
* PDFBox JBIG2 ImageIO plugin (org.apache.pdfbox:jbig2-imageio:3.0.3 - https://www.apache.org/jbig2-imageio/)
|
||||
* Apache JempBox (org.apache.pdfbox:jempbox:1.8.16 - http://www.apache.org/pdfbox-parent/jempbox/)
|
||||
* Apache PDFBox (org.apache.pdfbox:pdfbox:2.0.24 - https://www.apache.org/pdfbox-parent/pdfbox/)
|
||||
* Apache PDFBox tools (org.apache.pdfbox:pdfbox-tools:2.0.19 - https://www.apache.org/pdfbox-parent/pdfbox-tools/)
|
||||
* Apache Preflight (org.apache.pdfbox:preflight:2.0.19 - https://www.apache.org/pdfbox-parent/preflight/)
|
||||
* Apache XmpBox (org.apache.pdfbox:xmpbox:2.0.19 - https://www.apache.org/pdfbox-parent/xmpbox/)
|
||||
* Apache POI (org.apache.poi:poi:3.17 - http://poi.apache.org/)
|
||||
* Apache POI (org.apache.poi:poi-ooxml:3.17 - http://poi.apache.org/)
|
||||
* Apache POI (org.apache.poi:poi-ooxml-schemas:3.17 - http://poi.apache.org/)
|
||||
* Apache POI (org.apache.poi:poi-scratchpad:3.17 - http://poi.apache.org/)
|
||||
* Apache SIS features (org.apache.sis.core:sis-feature:1.0 - http://sis.apache.org/core/sis-feature)
|
||||
* Apache SIS metadata (org.apache.sis.core:sis-metadata:1.0 - http://sis.apache.org/core/sis-metadata)
|
||||
* Apache SIS referencing (org.apache.sis.core:sis-referencing:1.0 - http://sis.apache.org/core/sis-referencing)
|
||||
* Apache SIS utilities (org.apache.sis.core:sis-utility:1.0 - http://sis.apache.org/core/sis-utility)
|
||||
* Apache SIS netCDF storage (org.apache.sis.storage:sis-netcdf:1.0 - http://sis.apache.org/storage/sis-netcdf)
|
||||
* Apache SIS common storage (org.apache.sis.storage:sis-storage:1.0 - http://sis.apache.org/storage/sis-storage)
|
||||
* Apache Solr Content Extraction Library (org.apache.solr:solr-cell:8.8.1 - https://lucene.apache.org/solr-parent/solr-cell)
|
||||
* Apache Solr Core (org.apache.solr:solr-core:8.8.1 - https://lucene.apache.org/solr-parent/solr-core)
|
||||
* Apache Solr Solrj (org.apache.solr:solr-solrj:8.8.1 - https://lucene.apache.org/solr-parent/solr-solrj)
|
||||
* Apache PDFBox Debugger (org.apache.pdfbox:pdfbox-debugger:2.0.25 - https://www.apache.org/pdfbox-parent/pdfbox-debugger/)
|
||||
* Apache PDFBox tools (org.apache.pdfbox:pdfbox-tools:2.0.25 - https://www.apache.org/pdfbox-parent/pdfbox-tools/)
|
||||
* Apache XmpBox (org.apache.pdfbox:xmpbox:2.0.25 - https://www.apache.org/pdfbox-parent/xmpbox/)
|
||||
* Apache POI - Common (org.apache.poi:poi:5.2.0 - https://poi.apache.org/)
|
||||
* Apache POI - API based on OPC and OOXML schemas (org.apache.poi:poi-ooxml:5.2.0 - https://poi.apache.org/)
|
||||
* Apache POI (org.apache.poi:poi-ooxml-lite:5.2.0 - https://poi.apache.org/)
|
||||
* Apache POI (org.apache.poi:poi-scratchpad:5.2.0 - https://poi.apache.org/)
|
||||
* Apache Solr Core (org.apache.solr:solr-core:8.11.1 - https://lucene.apache.org/solr-parent/solr-core)
|
||||
* Apache Solr Solrj (org.apache.solr:solr-solrj:8.11.1 - https://lucene.apache.org/solr-parent/solr-solrj)
|
||||
* Apache Standard Taglib Implementation (org.apache.taglibs:taglibs-standard-impl:1.2.5 - http://tomcat.apache.org/taglibs/standard-1.2.5/taglibs-standard-impl)
|
||||
* Apache Standard Taglib Specification API (org.apache.taglibs:taglibs-standard-spec:1.2.5 - http://tomcat.apache.org/taglibs/standard-1.2.5/taglibs-standard-spec)
|
||||
* Apache Thrift (org.apache.thrift:libthrift:0.9.2 - http://thrift.apache.org)
|
||||
* Apache Tika core (org.apache.tika:tika-core:1.24.1 - http://tika.apache.org/)
|
||||
* Apache Tika Java-7 Components (org.apache.tika:tika-java7:1.24.1 - http://tika.apache.org/)
|
||||
* Apache Tika parsers (org.apache.tika:tika-parsers:1.24.1 - http://tika.apache.org/)
|
||||
* Apache Tika XMP (org.apache.tika:tika-xmp:1.24.1 - http://tika.apache.org/)
|
||||
* tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:9.0.33 - https://tomcat.apache.org/)
|
||||
* tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:9.0.33 - https://tomcat.apache.org/)
|
||||
* tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:9.0.33 - https://tomcat.apache.org/)
|
||||
* Apache Velocity - Engine (org.apache.velocity:velocity-engine-core:2.2 - http://velocity.apache.org/engine/devel/velocity-engine-core/)
|
||||
* Apache Tika core (org.apache.tika:tika-core:2.3.0 - https://tika.apache.org/)
|
||||
* Apache Tika Apple parser module (org.apache.tika:tika-parser-apple-module:2.3.0 - https://tika.apache.org/tika-parser-apple-module/)
|
||||
* Apache Tika audiovideo parser module (org.apache.tika:tika-parser-audiovideo-module:2.3.0 - https://tika.apache.org/tika-parser-audiovideo-module/)
|
||||
* Apache Tika cad parser module (org.apache.tika:tika-parser-cad-module:2.3.0 - https://tika.apache.org/tika-parser-cad-module/)
|
||||
* Apache Tika code parser module (org.apache.tika:tika-parser-code-module:2.3.0 - https://tika.apache.org/tika-parser-code-module/)
|
||||
* Apache Tika crypto parser module (org.apache.tika:tika-parser-crypto-module:2.3.0 - https://tika.apache.org/tika-parser-crypto-module/)
|
||||
* Apache Tika digest commons (org.apache.tika:tika-parser-digest-commons:2.3.0 - https://tika.apache.org/tika-parser-digest-commons/)
|
||||
* Apache Tika font parser module (org.apache.tika:tika-parser-font-module:2.3.0 - https://tika.apache.org/tika-parser-font-module/)
|
||||
* Apache Tika html commons (org.apache.tika:tika-parser-html-commons:2.3.0 - https://tika.apache.org/tika-parser-html-commons/)
|
||||
* Apache Tika html parser module (org.apache.tika:tika-parser-html-module:2.3.0 - https://tika.apache.org/tika-parser-html-module/)
|
||||
* Apache Tika image parser module (org.apache.tika:tika-parser-image-module:2.3.0 - https://tika.apache.org/tika-parser-image-module/)
|
||||
* Apache Tika mail commons (org.apache.tika:tika-parser-mail-commons:2.3.0 - https://tika.apache.org/tika-parser-mail-commons/)
|
||||
* Apache Tika mail parser module (org.apache.tika:tika-parser-mail-module:2.3.0 - https://tika.apache.org/tika-parser-mail-module/)
|
||||
* Apache Tika Microsoft parser module (org.apache.tika:tika-parser-microsoft-module:2.3.0 - https://tika.apache.org/tika-parser-microsoft-module/)
|
||||
* Apache Tika miscellaneous office format parser module (org.apache.tika:tika-parser-miscoffice-module:2.3.0 - https://tika.apache.org/tika-parser-miscoffice-module/)
|
||||
* Apache Tika news parser module (org.apache.tika:tika-parser-news-module:2.3.0 - https://tika.apache.org/tika-parser-news-module/)
|
||||
* Apache Tika OCR parser module (org.apache.tika:tika-parser-ocr-module:2.3.0 - https://tika.apache.org/tika-parser-ocr-module/)
|
||||
* Apache Tika PDF parser module (org.apache.tika:tika-parser-pdf-module:2.3.0 - https://tika.apache.org/tika-parser-pdf-module/)
|
||||
* Apache Tika package parser module (org.apache.tika:tika-parser-pkg-module:2.3.0 - https://tika.apache.org/tika-parser-pkg-module/)
|
||||
* Apache Tika text parser module (org.apache.tika:tika-parser-text-module:2.3.0 - https://tika.apache.org/tika-parser-text-module/)
|
||||
* Apache Tika XML parser module (org.apache.tika:tika-parser-xml-module:2.3.0 - https://tika.apache.org/tika-parser-xml-module/)
|
||||
* Apache Tika XMP commons (org.apache.tika:tika-parser-xmp-commons:2.3.0 - https://tika.apache.org/tika-parser-xmp-commons/)
|
||||
* Apache Tika ZIP commons (org.apache.tika:tika-parser-zip-commons:2.3.0 - https://tika.apache.org/tika-parser-zip-commons/)
|
||||
* Apache Tika standard parser package (org.apache.tika:tika-parsers-standard-package:2.3.0 - https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/)
|
||||
* tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:9.0.63 - https://tomcat.apache.org/)
|
||||
* tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:9.0.63 - https://tomcat.apache.org/)
|
||||
* tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:9.0.63 - https://tomcat.apache.org/)
|
||||
* Apache Velocity - Engine (org.apache.velocity:velocity-engine-core:2.3 - http://velocity.apache.org/engine/devel/velocity-engine-core/)
|
||||
* Apache Velocity - JSR 223 Scripting (org.apache.velocity:velocity-engine-scripting:2.2 - http://velocity.apache.org/engine/devel/velocity-engine-scripting/)
|
||||
* Axiom API (org.apache.ws.commons.axiom:axiom-api:1.2.22 - http://ws.apache.org/axiom/)
|
||||
* LLOM (org.apache.ws.commons.axiom:axiom-impl:1.2.22 - http://ws.apache.org/axiom/implementations/axiom-impl/)
|
||||
* Abdera Model (FOM) Implementation (org.apache.ws.commons.axiom:fom-impl:1.2.22 - http://ws.apache.org/axiom/implementations/fom-impl/)
|
||||
* XmlSchema Core (org.apache.ws.xmlschema:xmlschema-core:2.2.5 - https://ws.apache.org/commons/xmlschema20/xmlschema-core/)
|
||||
* XmlBeans (org.apache.xmlbeans:xmlbeans:3.1.0 - https://xmlbeans.apache.org/)
|
||||
* zookeeper (org.apache.zookeeper:zookeeper:3.4.14 - no url defined)
|
||||
* XmlBeans (org.apache.xmlbeans:xmlbeans:5.0.3 - https://xmlbeans.apache.org/)
|
||||
* Apache ZooKeeper - Server (org.apache.zookeeper:zookeeper:3.6.2 - http://zookeeper.apache.org/zookeeper)
|
||||
* Apache ZooKeeper - Jute (org.apache.zookeeper:zookeeper-jute:3.6.2 - http://zookeeper.apache.org/zookeeper-jute)
|
||||
* AssertJ fluent assertions (org.assertj:assertj-core:3.13.2 - http://assertj.org/assertj-core)
|
||||
* Evo Inflector (org.atteo:evo-inflector:1.2.2 - http://atteo.org/static/evo-inflector)
|
||||
* org.apiguardian:apiguardian-api (org.apiguardian:apiguardian-api:1.1.0 - https://github.com/apiguardian-team/apiguardian)
|
||||
* AssertJ fluent assertions (org.assertj:assertj-core:3.21.0 - https://assertj.github.io/doc/assertj-core/)
|
||||
* Evo Inflector (org.atteo:evo-inflector:1.3 - http://atteo.org/static/evo-inflector)
|
||||
* 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:woodstox-core-asl:4.4.1 - 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)
|
||||
* 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.34.v20201102 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-client)
|
||||
* Jetty :: ALPN :: JDK9 Client Implementation (org.eclipse.jetty:jetty-alpn-java-client:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-java-client)
|
||||
* Jetty :: ALPN :: JDK9 Server Implementation (org.eclipse.jetty:jetty-alpn-java-server:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-java-server)
|
||||
* Jetty :: ALPN :: Server (org.eclipse.jetty:jetty-alpn-server:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-server)
|
||||
* Jetty :: ALPN :: Client (org.eclipse.jetty:jetty-alpn-client:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-client)
|
||||
* Jetty :: ALPN :: JDK9 Client Implementation (org.eclipse.jetty:jetty-alpn-java-client:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-java-client)
|
||||
* Jetty :: ALPN :: JDK9 Server Implementation (org.eclipse.jetty:jetty-alpn-java-server:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-java-server)
|
||||
* Jetty :: ALPN :: Server (org.eclipse.jetty:jetty-alpn-server:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-server)
|
||||
* Jetty :: Servlet Annotations (org.eclipse.jetty:jetty-annotations:9.4.15.v20190215 - http://www.eclipse.org/jetty)
|
||||
* Jetty :: Asynchronous HTTP Client (org.eclipse.jetty:jetty-client:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-client)
|
||||
* Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-continuation)
|
||||
* Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-deploy)
|
||||
* Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.41.v20210516 - https://eclipse.org/jetty/jetty-http)
|
||||
* Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.41.v20210516 - https://eclipse.org/jetty/jetty-io)
|
||||
* Jetty :: JMX Management (org.eclipse.jetty:jetty-jmx:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-jmx)
|
||||
* Jetty :: Asynchronous HTTP Client (org.eclipse.jetty:jetty-client:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-client)
|
||||
* Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-continuation)
|
||||
* Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-deploy)
|
||||
* Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-http)
|
||||
* Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-io)
|
||||
* Jetty :: JMX Management (org.eclipse.jetty:jetty-jmx:9.4.44.v20210927 - 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.34.v20201102 - https://eclipse.org/jetty/jetty-rewrite)
|
||||
* Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-security)
|
||||
* Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.41.v20210516 - https://eclipse.org/jetty/jetty-server)
|
||||
* Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-servlet)
|
||||
* Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-servlets)
|
||||
* Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.41.v20210516 - https://eclipse.org/jetty/jetty-util)
|
||||
* Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-webapp)
|
||||
* Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-xml)
|
||||
* Jetty :: HTTP2 :: Client (org.eclipse.jetty.http2:http2-client:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-client)
|
||||
* Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-common)
|
||||
* Jetty :: HTTP2 :: HPACK (org.eclipse.jetty.http2:http2-hpack:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-hpack)
|
||||
* Jetty :: HTTP2 :: HTTP Client Transport (org.eclipse.jetty.http2:http2-http-client-transport:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-http-client-transport)
|
||||
* Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-server)
|
||||
* Jetty :: Rewrite Handler (org.eclipse.jetty:jetty-rewrite:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-rewrite)
|
||||
* Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-security)
|
||||
* Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-server)
|
||||
* Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-servlet)
|
||||
* Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-servlets)
|
||||
* Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-util)
|
||||
* Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-webapp)
|
||||
* Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-xml)
|
||||
* Jetty :: HTTP2 :: Client (org.eclipse.jetty.http2:http2-client:9.4.44.v20210927 - https://eclipse.org/jetty/http2-parent/http2-client)
|
||||
* Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.44.v20210927 - https://eclipse.org/jetty/http2-parent/http2-common)
|
||||
* Jetty :: HTTP2 :: HPACK (org.eclipse.jetty.http2:http2-hpack:9.4.44.v20210927 - https://eclipse.org/jetty/http2-parent/http2-hpack)
|
||||
* Jetty :: HTTP2 :: HTTP Client Transport (org.eclipse.jetty.http2:http2-http-client-transport:9.4.44.v20210927 - https://eclipse.org/jetty/http2-parent/http2-http-client-transport)
|
||||
* Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.44.v20210927 - 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.4.0 - http://ehcache.org)
|
||||
* flyway-core (org.flywaydb:flyway-core:6.5.7 - https://flywaydb.org/flyway-core)
|
||||
* flyway-core (org.flywaydb:flyway-core:8.4.4 - https://flywaydb.org/flyway-core)
|
||||
* 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:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-core-common (org.glassfish.jersey.core:jersey-common:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Hibernate Validator Engine (org.hibernate.validator:hibernate-validator:6.0.18.Final - http://hibernate.org/validator/hibernate-validator)
|
||||
* Hibernate Validator Portable Extension (org.hibernate.validator:hibernate-validator-cdi:6.0.18.Final - http://hibernate.org/validator/hibernate-validator-cdi)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-core-common (org.glassfish.jersey.core:jersey-common:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Hibernate Validator Engine (org.hibernate.validator:hibernate-validator:6.0.23.Final - http://hibernate.org/validator/hibernate-validator)
|
||||
* Hibernate Validator Portable Extension (org.hibernate.validator:hibernate-validator-cdi:6.0.23.Final - http://hibernate.org/validator/hibernate-validator-cdi)
|
||||
* Javassist (org.javassist:javassist:3.25.0-GA - http://www.javassist.org/)
|
||||
* Java Annotation Indexer (org.jboss:jandex:2.1.1.Final - http://www.jboss.org/jandex)
|
||||
* JBoss Logging 3 (org.jboss.logging:jboss-logging:3.3.2.Final - http://www.jboss.org)
|
||||
* JDOM (org.jdom:jdom:1.1.3 - http://www.jdom.org)
|
||||
* JDOM (org.jdom:jdom2:2.0.6 - http://www.jdom.org)
|
||||
* Java Annotation Indexer (org.jboss:jandex:2.4.2.Final - http://www.jboss.org/jandex)
|
||||
* JBoss Logging 3 (org.jboss.logging:jboss-logging:3.4.3.Final - http://www.jboss.org)
|
||||
* JDOM (org.jdom:jdom2:2.0.6.1 - http://www.jdom.org)
|
||||
* jtwig-core (org.jtwig:jtwig-core:5.87.0.RELEASE - http://jtwig.org)
|
||||
* jtwig-reflection (org.jtwig:jtwig-reflection:5.87.0.RELEASE - http://jtwig.org)
|
||||
* jtwig-spring (org.jtwig:jtwig-spring:5.87.0.RELEASE - http://jtwig.org)
|
||||
@@ -341,69 +337,66 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* Objenesis (org.objenesis:objenesis:3.2 - http://objenesis.org/objenesis)
|
||||
* parboiled-core (org.parboiled:parboiled-core:1.3.1 - http://parboiled.org)
|
||||
* parboiled-java (org.parboiled:parboiled-java:1.3.1 - http://parboiled.org)
|
||||
* quartz (org.quartz-scheduler:quartz:2.3.2 - http://www.quartz-scheduler.org/quartz)
|
||||
* rome-modules (org.rometools:rome-modules:1.0 - http://www.rometools.org)
|
||||
* RRD4J (org.rrd4j:rrd4j:3.5 - https://github.com/rrd4j/rrd4j/)
|
||||
* JSONassert (org.skyscreamer:jsonassert:1.5.0 - https://github.com/skyscreamer/JSONassert)
|
||||
* Spring AOP (org.springframework:spring-aop:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Beans (org.springframework:spring-beans:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Context (org.springframework:spring-context:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Context Support (org.springframework:spring-context-support:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Core (org.springframework:spring-core:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Expression Language (SpEL) (org.springframework:spring-expression:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Commons Logging Bridge (org.springframework:spring-jcl:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring JDBC (org.springframework:spring-jdbc:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Object/Relational Mapping (org.springframework:spring-orm:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring TestContext Framework (org.springframework:spring-test:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Transaction (org.springframework:spring-tx:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Web (org.springframework:spring-web:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Web MVC (org.springframework:spring-webmvc:5.2.5.RELEASE - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Boot (org.springframework.boot:spring-boot:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot)
|
||||
* Spring Boot AutoConfigure (org.springframework.boot:spring-boot-autoconfigure:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-autoconfigure)
|
||||
* Spring AOP (org.springframework:spring-aop:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Beans (org.springframework:spring-beans:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Context (org.springframework:spring-context:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Context Support (org.springframework:spring-context-support:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Core (org.springframework:spring-core:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Expression Language (SpEL) (org.springframework:spring-expression:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Commons Logging Bridge (org.springframework:spring-jcl:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring JDBC (org.springframework:spring-jdbc:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Object/Relational Mapping (org.springframework:spring-orm:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring TestContext Framework (org.springframework:spring-test:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Transaction (org.springframework:spring-tx:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Web (org.springframework:spring-web:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* Spring Web MVC (org.springframework:spring-webmvc:5.3.20 - https://github.com/spring-projects/spring-framework)
|
||||
* spring-boot (org.springframework.boot:spring-boot:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-actuator (org.springframework.boot:spring-boot-actuator:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* Spring Boot Configuration Processor (org.springframework.boot:spring-boot-configuration-processor:2.0.0.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-tools/spring-boot-configuration-processor)
|
||||
* Spring Boot Starter (org.springframework.boot:spring-boot-starter:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter)
|
||||
* Spring Boot AOP Starter (org.springframework.boot:spring-boot-starter-aop:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-aop)
|
||||
* Spring Boot Cache Starter (org.springframework.boot:spring-boot-starter-cache:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-cache)
|
||||
* Spring Boot Data REST Starter (org.springframework.boot:spring-boot-starter-data-rest:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-data-rest)
|
||||
* Spring Boot Json Starter (org.springframework.boot:spring-boot-starter-json:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-json)
|
||||
* Spring Boot Log4j 2 Starter (org.springframework.boot:spring-boot-starter-log4j2:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-log4j2)
|
||||
* Spring Boot Security Starter (org.springframework.boot:spring-boot-starter-security:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-security)
|
||||
* Spring Boot Test Starter (org.springframework.boot:spring-boot-starter-test:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-test)
|
||||
* Spring Boot Tomcat Starter (org.springframework.boot:spring-boot-starter-tomcat:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-tomcat)
|
||||
* Spring Boot Validation Starter (org.springframework.boot:spring-boot-starter-validation:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-validation)
|
||||
* Spring Boot Web Starter (org.springframework.boot:spring-boot-starter-web:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-web)
|
||||
* Spring Boot Test (org.springframework.boot:spring-boot-test:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-test)
|
||||
* Spring Boot Test Auto-Configure (org.springframework.boot:spring-boot-test-autoconfigure:2.2.6.RELEASE - https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-test-autoconfigure)
|
||||
* Spring Data Core (org.springframework.data:spring-data-commons:2.2.6.RELEASE - https://www.spring.io/spring-data/spring-data-commons)
|
||||
* Spring Data REST - Core (org.springframework.data:spring-data-rest-core:3.2.6.RELEASE - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-core)
|
||||
* Spring Data REST - HAL Browser (org.springframework.data:spring-data-rest-hal-browser:3.2.6.RELEASE - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-hal-browser)
|
||||
* Spring Data REST - WebMVC (org.springframework.data:spring-data-rest-webmvc:3.2.6.RELEASE - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-webmvc)
|
||||
* Spring HATEOAS (org.springframework.hateoas:spring-hateoas:1.0.4.RELEASE - https://github.com/spring-projects/spring-hateoas)
|
||||
* spring-boot-starter (org.springframework.boot:spring-boot-starter:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-aop (org.springframework.boot:spring-boot-starter-aop:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-cache (org.springframework.boot:spring-boot-starter-cache:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-data-rest (org.springframework.boot:spring-boot-starter-data-rest:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-log4j2 (org.springframework.boot:spring-boot-starter-log4j2:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-security (org.springframework.boot:spring-boot-starter-security:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-test (org.springframework.boot:spring-boot-starter-test:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-test (org.springframework.boot:spring-boot-test:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* spring-boot-test-autoconfigure (org.springframework.boot:spring-boot-test-autoconfigure:2.6.8 - https://spring.io/projects/spring-boot)
|
||||
* Spring Data Core (org.springframework.data:spring-data-commons:2.6.4 - https://www.spring.io/spring-data/spring-data-commons)
|
||||
* Spring Data REST - Core (org.springframework.data:spring-data-rest-core:3.6.4 - 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:3.6.4 - https://www.spring.io/spring-data/spring-data-rest-parent/spring-data-rest-webmvc)
|
||||
* Spring HATEOAS (org.springframework.hateoas:spring-hateoas:1.4.2 - https://github.com/spring-projects/spring-hateoas)
|
||||
* Spring Plugin - Core (org.springframework.plugin:spring-plugin-core:2.0.0.RELEASE - https://github.com/spring-projects/spring-plugin/spring-plugin-core)
|
||||
* spring-security-config (org.springframework.security:spring-security-config:5.2.2.RELEASE - http://spring.io/spring-security)
|
||||
* spring-security-core (org.springframework.security:spring-security-core:5.2.2.RELEASE - http://spring.io/spring-security)
|
||||
* spring-security-test (org.springframework.security:spring-security-test:5.2.2.RELEASE - http://spring.io/spring-security)
|
||||
* spring-security-web (org.springframework.security:spring-security-web:5.2.2.RELEASE - http://spring.io/spring-security)
|
||||
* spring-security-config (org.springframework.security:spring-security-config:5.6.5 - https://spring.io/projects/spring-security)
|
||||
* spring-security-core (org.springframework.security:spring-security-core:5.6.5 - https://spring.io/projects/spring-security)
|
||||
* spring-security-crypto (org.springframework.security:spring-security-crypto:5.6.5 - https://spring.io/projects/spring-security)
|
||||
* spring-security-test (org.springframework.security:spring-security-test:5.6.5 - https://spring.io/projects/spring-security)
|
||||
* spring-security-web (org.springframework.security:spring-security-web:5.6.5 - https://spring.io/projects/spring-security)
|
||||
* SWORD v2 :: Common Server Library (org.swordapp:sword2-server:1.0 - http://www.swordapp.org/)
|
||||
* ISO Parser (org.tallison:isoparser:1.9.41.2 - https://github.com/tballison/mp4parser)
|
||||
* org.tallison:metadata-extractor (org.tallison:metadata-extractor:2.13.0 - https://drewnoakes.com/code/exif/)
|
||||
* XMPCore Shaded (org.tallison.xmp:xmpcore-shaded:6.1.10 - https://github.com/tballison)
|
||||
* snappy-java (org.xerial.snappy:snappy-java:1.1.7.6 - 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.6.4 - https://www.xmlunit.org/)
|
||||
* org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.8.0 - https://www.xmlunit.org/)
|
||||
* org.xmlunit:xmlunit-core (org.xmlunit:xmlunit-core:2.8.4 - https://www.xmlunit.org/)
|
||||
* org.xmlunit:xmlunit-placeholders (org.xmlunit:xmlunit-placeholders:2.8.0 - https://www.xmlunit.org/xmlunit-placeholders/)
|
||||
* SnakeYAML (org.yaml:snakeyaml:1.25 - http://www.snakeyaml.org)
|
||||
* SnakeYAML (org.yaml:snakeyaml:1.26 - http://www.snakeyaml.org)
|
||||
* ROME, RSS and atOM utilitiEs for Java (rome:rome:1.0 - https://rome.dev.java.net/)
|
||||
* SnakeYAML (org.yaml:snakeyaml:1.29 - http://www.snakeyaml.org)
|
||||
* software.amazon.ion:ion-java (software.amazon.ion:ion-java:1.0.2 - https://github.com/amznlabs/ion-java/)
|
||||
* xalan (xalan:xalan:2.7.0 - no url defined)
|
||||
* Xerces2-j (xerces:xercesImpl:2.12.0 - https://xerces.apache.org/xerces2-j/)
|
||||
* Xalan Java Serializer (xalan:serializer:2.7.2 - http://xml.apache.org/xalan-j/)
|
||||
* Xalan Java (xalan:xalan:2.7.2 - http://xml.apache.org/xalan-j/)
|
||||
* Xerces2-j (xerces:xercesImpl:2.12.2 - https://xerces.apache.org/xerces2-j/)
|
||||
* XML Commons External Components XML APIs (xml-apis:xml-apis:1.4.01 - http://xml.apache.org/commons/components/external/)
|
||||
|
||||
BSD License:
|
||||
|
||||
* AntLR Parser Generator (antlr:antlr:2.7.7 - http://www.antlr.org/)
|
||||
* Adobe XMPCore (com.adobe.xmp:xmpcore:6.1.11 - https://www.adobe.com/devnet/xmp/library/eula-xmp-library-java.html)
|
||||
* coverity-escapers (com.coverity.security:coverity-escapers:1.1.1 - http://coverity.com/security)
|
||||
* Java Advanced Imaging Image I/O Tools API core (standalone) (com.github.jai-imageio:jai-imageio-core:1.4.0 - https://github.com/jai-imageio/jai-imageio-core)
|
||||
* JSONLD Java :: Core (com.github.jsonld-java:jsonld-java:0.5.1 - http://github.com/jsonld-java/jsonld-java/jsonld-java/)
|
||||
@@ -411,41 +404,36 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* Protocol Buffers [Core] (com.google.protobuf:protobuf-java:3.11.0 - https://developers.google.com/protocol-buffers/protobuf-java/)
|
||||
* JZlib (com.jcraft:jzlib:1.1.3 - http://www.jcraft.com/jzlib/)
|
||||
* dnsjava (dnsjava:dnsjava:2.1.7 - http://www.dnsjava.org)
|
||||
* Units of Measurement API (javax.measure:unit-api:1.0 - http://unitsofmeasurement.github.io/)
|
||||
* jaxen (jaxen:jaxen:1.1.6 - http://jaxen.codehaus.org/)
|
||||
* JLine (jline:jline:0.9.94 - http://jline.sourceforge.net)
|
||||
* ANTLR 4 Runtime (org.antlr:antlr4-runtime:4.5.1-1 - http://www.antlr.org/antlr4-runtime)
|
||||
* commons-compiler (org.codehaus.janino:commons-compiler:3.0.9 - http://janino-compiler.github.io/commons-compiler/)
|
||||
* janino (org.codehaus.janino:janino:3.0.9 - http://janino-compiler.github.io/janino/)
|
||||
* Stax2 API (org.codehaus.woodstox:stax2-api:3.1.4 - http://wiki.fasterxml.com/WoodstoxStax2)
|
||||
* dom4j (org.dom4j:dom4j:2.1.1 - http://dom4j.github.io/)
|
||||
* Stax2 API (org.codehaus.woodstox:stax2-api:4.2.1 - http://github.com/FasterXML/stax2-api)
|
||||
* Hamcrest Date (org.exparity:hamcrest-date:2.0.7 - https://github.com/exparity/hamcrest-date)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Hamcrest (org.hamcrest:hamcrest:2.1 - http://hamcrest.org/JavaHamcrest/)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Hamcrest (org.hamcrest:hamcrest:2.2 - http://hamcrest.org/JavaHamcrest/)
|
||||
* Hamcrest All (org.hamcrest:hamcrest-all:1.3 - https://github.com/hamcrest/JavaHamcrest/hamcrest-all)
|
||||
* Hamcrest Core (org.hamcrest:hamcrest-core:1.3 - https://github.com/hamcrest/JavaHamcrest/hamcrest-core)
|
||||
* Hamcrest library (org.hamcrest:hamcrest-library:1.3 - https://github.com/hamcrest/JavaHamcrest/hamcrest-library)
|
||||
* HdrHistogram (org.hdrhistogram:HdrHistogram:2.1.12 - http://hdrhistogram.github.io/HdrHistogram/)
|
||||
* JBibTeX (org.jbibtex:jbibtex:1.0.10 - http://www.jbibtex.org)
|
||||
* asm (org.ow2.asm:asm:8.0.1 - http://asm.ow2.io/)
|
||||
* asm-analysis (org.ow2.asm:asm-analysis:7.1 - http://asm.ow2.org/)
|
||||
* asm-commons (org.ow2.asm:asm-commons:8.0.1 - http://asm.ow2.io/)
|
||||
* asm-tree (org.ow2.asm:asm-tree:7.1 - http://asm.ow2.org/)
|
||||
* asm-util (org.ow2.asm:asm-util:7.1 - http://asm.ow2.org/)
|
||||
* PostgreSQL JDBC Driver (org.postgresql:postgresql:42.2.25 - https://jdbc.postgresql.org)
|
||||
* PostgreSQL JDBC Driver (org.postgresql:postgresql:42.3.3 - https://jdbc.postgresql.org)
|
||||
* Reflections (org.reflections:reflections:0.9.12 - http://github.com/ronmamo/reflections)
|
||||
* JMatIO (org.tallison:jmatio:1.5 - https://github.com/tballison/jmatio)
|
||||
* XMLUnit for Java (xmlunit:xmlunit:1.3 - http://xmlunit.sourceforge.net/)
|
||||
|
||||
Common Development and Distribution License (CDDL):
|
||||
|
||||
* JavaBeans Activation Framework (com.sun.activation:javax.activation:1.2.0 - http://java.net/all/javax.activation/)
|
||||
* istack common utility code runtime (com.sun.istack:istack-commons-runtime:3.0.7 - http://java.net/istack-commons/istack-commons-runtime/)
|
||||
* JavaMail API (com.sun.mail:javax.mail:1.6.2 - http://javaee.github.io/javamail/javax.mail)
|
||||
* 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)
|
||||
* saaj-impl (com.sun.xml.messaging.saaj:saaj-impl:1.4.0-b03 - http://java.net/saaj-impl/)
|
||||
* Jakarta Annotations API (jakarta.annotation:jakarta.annotation-api:1.3.5 - https://projects.eclipse.org/projects/ee4j.ca)
|
||||
* jakarta.ws.rs-api (jakarta.ws.rs:jakarta.ws.rs-api:2.1.6 - https://github.com/eclipse-ee4j/jaxrs-api)
|
||||
* JavaBeans Activation Framework (JAF) (javax.activation:activation:1.1 - http://java.sun.com/products/javabeans/jaf/index.jsp)
|
||||
@@ -454,7 +442,6 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* Java Servlet API (javax.servlet:javax.servlet-api:3.1.0 - http://servlet-spec.java.net)
|
||||
* 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)
|
||||
* JAX-WS API (javax.xml.ws:jaxws-api:2.3.1 - https://github.com/javaee/jax-ws-spec)
|
||||
* JHighlight (org.codelibs:jhighlight:1.0.3 - https://github.com/codelibs/jhighlight)
|
||||
* HK2 API module (org.glassfish.hk2:hk2-api:2.6.1 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-api)
|
||||
* ServiceLocator Default Implementation (org.glassfish.hk2:hk2-locator:2.6.1 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-locator)
|
||||
@@ -464,10 +451,9 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* javax.inject:1 as OSGi bundle (org.glassfish.hk2.external:jakarta.inject:2.6.1 - https://github.com/eclipse-ee4j/glassfish-hk2/external/jakarta.inject)
|
||||
* JAXB Runtime (org.glassfish.jaxb:jaxb-runtime:2.3.1 - http://jaxb.java.net/jaxb-runtime-parent/jaxb-runtime)
|
||||
* TXW2 Runtime (org.glassfish.jaxb:txw2:2.3.1 - http://jaxb.java.net/jaxb-txw-parent/txw2)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Java Transaction API (org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final - http://www.jboss.org/jboss-transaction-api_1.2_spec)
|
||||
* MIME streaming extension (org.jvnet.mimepull:mimepull:1.9.7 - http://mimepull.java.net)
|
||||
* Extended StAX API (org.jvnet.staxex:stax-ex:1.8 - http://stax-ex.java.net/)
|
||||
|
||||
Cordra (Version 2) License Agreement:
|
||||
@@ -478,56 +464,51 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
|
||||
Eclipse Distribution License, Version 1.0:
|
||||
|
||||
* JavaBeans Activation Framework (com.sun.activation:jakarta.activation:1.2.1 - https://github.com/eclipse-ee4j/jaf/jakarta.activation)
|
||||
* JavaBeans Activation Framework API jar (jakarta.activation:jakarta.activation-api:1.2.1 - https://github.com/eclipse-ee4j/jaf/jakarta.activation-api)
|
||||
* Jakarta Activation API jar (jakarta.activation:jakarta.activation-api:1.2.2 - https://github.com/eclipse-ee4j/jaf/jakarta.activation-api)
|
||||
* jakarta.xml.bind-api (jakarta.xml.bind:jakarta.xml.bind-api:2.3.2 - https://github.com/eclipse-ee4j/jaxb-api/jakarta.xml.bind-api)
|
||||
* Jakarta XML Binding API (jakarta.xml.bind:jakarta.xml.bind-api:2.3.3 - https://github.com/eclipse-ee4j/jaxb-api/jakarta.xml.bind-api)
|
||||
* javax.persistence-api (javax.persistence:javax.persistence-api:2.2 - https://github.com/javaee/jpa-spec)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Java Persistence API, Version 2.1 (org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final - http://hibernate.org)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Java Persistence API, Version 2.1 (org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final - http://hibernate.org)
|
||||
|
||||
Eclipse Public License:
|
||||
|
||||
* System Rules (com.github.stefanbirkner:system-rules:1.19.0 - http://stefanbirkner.github.io/system-rules/)
|
||||
* c3p0 (com.mchange:c3p0:0.9.5.5 - https://github.com/swaldman/c3p0)
|
||||
* mchange-commons-java (com.mchange:mchange-commons-java:0.2.19 - https://github.com/swaldman/mchange-commons-java)
|
||||
* H2 Database Engine (com.h2database:h2:2.1.210 - https://h2database.com)
|
||||
* Jakarta Annotations API (jakarta.annotation:jakarta.annotation-api:1.3.5 - https://projects.eclipse.org/projects/ee4j.ca)
|
||||
* jakarta.ws.rs-api (jakarta.ws.rs:jakarta.ws.rs-api:2.1.6 - https://github.com/eclipse-ee4j/jaxrs-api)
|
||||
* javax.persistence-api (javax.persistence:javax.persistence-api:2.2 - https://github.com/javaee/jpa-spec)
|
||||
* JUnit (junit:junit:4.13.1 - http://junit.org)
|
||||
* AspectJ runtime (org.aspectj:aspectjrt:1.8.0 - http://www.aspectj.org)
|
||||
* AspectJ weaver (org.aspectj:aspectjweaver:1.9.5 - http://www.aspectj.org)
|
||||
* AspectJ Weaver (org.aspectj:aspectjweaver:1.9.7 - https://www.eclipse.org/aspectj/)
|
||||
* Eclipse Compiler for Java(TM) (org.eclipse.jdt:ecj:3.14.0 - http://www.eclipse.org/jdt)
|
||||
* 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.34.v20201102 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-client)
|
||||
* Jetty :: ALPN :: JDK9 Client Implementation (org.eclipse.jetty:jetty-alpn-java-client:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-java-client)
|
||||
* Jetty :: ALPN :: JDK9 Server Implementation (org.eclipse.jetty:jetty-alpn-java-server:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-java-server)
|
||||
* Jetty :: ALPN :: Server (org.eclipse.jetty:jetty-alpn-server:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-server)
|
||||
* Jetty :: ALPN :: Client (org.eclipse.jetty:jetty-alpn-client:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-client)
|
||||
* Jetty :: ALPN :: JDK9 Client Implementation (org.eclipse.jetty:jetty-alpn-java-client:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-java-client)
|
||||
* Jetty :: ALPN :: JDK9 Server Implementation (org.eclipse.jetty:jetty-alpn-java-server:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-java-server)
|
||||
* Jetty :: ALPN :: Server (org.eclipse.jetty:jetty-alpn-server:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-alpn-parent/jetty-alpn-server)
|
||||
* Jetty :: Servlet Annotations (org.eclipse.jetty:jetty-annotations:9.4.15.v20190215 - http://www.eclipse.org/jetty)
|
||||
* Jetty :: Asynchronous HTTP Client (org.eclipse.jetty:jetty-client:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-client)
|
||||
* Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-continuation)
|
||||
* Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-deploy)
|
||||
* Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.41.v20210516 - https://eclipse.org/jetty/jetty-http)
|
||||
* Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.41.v20210516 - https://eclipse.org/jetty/jetty-io)
|
||||
* Jetty :: JMX Management (org.eclipse.jetty:jetty-jmx:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-jmx)
|
||||
* Jetty :: Asynchronous HTTP Client (org.eclipse.jetty:jetty-client:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-client)
|
||||
* Jetty :: Continuation (org.eclipse.jetty:jetty-continuation:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-continuation)
|
||||
* Jetty :: Deployers (org.eclipse.jetty:jetty-deploy:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-deploy)
|
||||
* Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-http)
|
||||
* Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-io)
|
||||
* Jetty :: JMX Management (org.eclipse.jetty:jetty-jmx:9.4.44.v20210927 - 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.34.v20201102 - https://eclipse.org/jetty/jetty-rewrite)
|
||||
* Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-security)
|
||||
* Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.41.v20210516 - https://eclipse.org/jetty/jetty-server)
|
||||
* Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-servlet)
|
||||
* Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-servlets)
|
||||
* Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.41.v20210516 - https://eclipse.org/jetty/jetty-util)
|
||||
* Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-webapp)
|
||||
* Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.34.v20201102 - https://eclipse.org/jetty/jetty-xml)
|
||||
* Jetty :: HTTP2 :: Client (org.eclipse.jetty.http2:http2-client:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-client)
|
||||
* Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-common)
|
||||
* Jetty :: HTTP2 :: HPACK (org.eclipse.jetty.http2:http2-hpack:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-hpack)
|
||||
* Jetty :: HTTP2 :: HTTP Client Transport (org.eclipse.jetty.http2:http2-http-client-transport:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-http-client-transport)
|
||||
* Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.34.v20201102 - https://eclipse.org/jetty/http2-parent/http2-server)
|
||||
* Jetty :: Rewrite Handler (org.eclipse.jetty:jetty-rewrite:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-rewrite)
|
||||
* Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-security)
|
||||
* Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-server)
|
||||
* Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-servlet)
|
||||
* Jetty :: Utility Servlets and Filters (org.eclipse.jetty:jetty-servlets:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-servlets)
|
||||
* Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-util)
|
||||
* Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-webapp)
|
||||
* Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.44.v20210927 - https://eclipse.org/jetty/jetty-xml)
|
||||
* Jetty :: HTTP2 :: Client (org.eclipse.jetty.http2:http2-client:9.4.44.v20210927 - https://eclipse.org/jetty/http2-parent/http2-client)
|
||||
* Jetty :: HTTP2 :: Common (org.eclipse.jetty.http2:http2-common:9.4.44.v20210927 - https://eclipse.org/jetty/http2-parent/http2-common)
|
||||
* Jetty :: HTTP2 :: HPACK (org.eclipse.jetty.http2:http2-hpack:9.4.44.v20210927 - https://eclipse.org/jetty/http2-parent/http2-hpack)
|
||||
* Jetty :: HTTP2 :: HTTP Client Transport (org.eclipse.jetty.http2:http2-http-client-transport:9.4.44.v20210927 - https://eclipse.org/jetty/http2-parent/http2-http-client-transport)
|
||||
* Jetty :: HTTP2 :: Server (org.eclipse.jetty.http2:http2-server:9.4.44.v20210927 - 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)
|
||||
* HK2 API module (org.glassfish.hk2:hk2-api:2.6.1 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-api)
|
||||
* ServiceLocator Default Implementation (org.glassfish.hk2:hk2-locator:2.6.1 - https://github.com/eclipse-ee4j/glassfish-hk2/hk2-locator)
|
||||
@@ -535,10 +516,10 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* 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:2.6.1 - https://github.com/eclipse-ee4j/glassfish-hk2/external/aopalliance-repackaged)
|
||||
* javax.inject:1 as OSGi bundle (org.glassfish.hk2.external:jakarta.inject:2.6.1 - https://github.com/eclipse-ee4j/glassfish-hk2/external/jakarta.inject)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-core-common (org.glassfish.jersey.core:jersey-common:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Java Persistence API, Version 2.1 (org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final - http://hibernate.org)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-core-common (org.glassfish.jersey.core:jersey-common:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Java Persistence API, Version 2.1 (org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final - http://hibernate.org)
|
||||
* Jetty Server (org.mortbay.jetty:jetty:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/modules/jetty)
|
||||
* Jetty Servlet Tester (org.mortbay.jetty:jetty-servlet-tester:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/jetty-servlet-tester)
|
||||
* Jetty Utilities (org.mortbay.jetty:jetty-util:6.1.26 - http://www.eclipse.org/jetty/jetty-parent/project/jetty-util)
|
||||
@@ -552,21 +533,16 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* json-schema-validator (com.github.java-json-tools:json-schema-validator:2.2.14 - https://github.com/java-json-tools/json-schema-validator)
|
||||
* msg-simple (com.github.java-json-tools:msg-simple:1.2 - https://github.com/java-json-tools/msg-simple)
|
||||
* uri-template (com.github.java-json-tools:uri-template:0.10 - https://github.com/java-json-tools/uri-template)
|
||||
* SpotBugs Annotations (com.github.spotbugs:spotbugs-annotations:3.1.9 - https://spotbugs.github.io/)
|
||||
* FindBugs-Annotations (com.google.code.findbugs:annotations:3.0.1u2 - http://findbugs.sourceforge.net/)
|
||||
* c3p0 (com.mchange:c3p0:0.9.5.5 - https://github.com/swaldman/c3p0)
|
||||
* mchange-commons-java (com.mchange:mchange-commons-java:0.2.19 - https://github.com/swaldman/mchange-commons-java)
|
||||
* Java Native Access (net.java.dev.jna:jna:5.5.0 - https://github.com/java-native-access/jna)
|
||||
* JHighlight (org.codelibs:jhighlight:1.0.3 - https://github.com/codelibs/jhighlight)
|
||||
* Hibernate ORM - hibernate-core (org.hibernate:hibernate-core:5.4.10.Final - http://hibernate.org/orm)
|
||||
* Hibernate ORM - hibernate-ehcache (org.hibernate:hibernate-ehcache:5.4.10.Final - http://hibernate.org/orm)
|
||||
* Hibernate ORM - hibernate-jpamodelgen (org.hibernate:hibernate-jpamodelgen:5.4.10.Final - http://hibernate.org/orm)
|
||||
* Hibernate Commons Annotations (org.hibernate.common:hibernate-commons-annotations:5.1.0.Final - http://hibernate.org)
|
||||
* Hibernate ORM - hibernate-core (org.hibernate:hibernate-core:5.6.5.Final - https://hibernate.org/orm)
|
||||
* Hibernate ORM - hibernate-jcache (org.hibernate:hibernate-jcache:5.6.5.Final - https://hibernate.org/orm)
|
||||
* Hibernate ORM - hibernate-jpamodelgen (org.hibernate:hibernate-jpamodelgen:5.6.5.Final - https://hibernate.org/orm)
|
||||
* Hibernate Commons Annotations (org.hibernate.common:hibernate-commons-annotations:5.1.2.Final - http://hibernate.org)
|
||||
* im4java (org.im4java:im4java:1.4.0 - http://sourceforge.net/projects/im4java/)
|
||||
* JacORB OMG-API (org.jacorb:jacorb-omgapi:3.9 - http://www.jacorb.org)
|
||||
* Javassist (org.javassist:javassist:3.25.0-GA - http://www.javassist.org/)
|
||||
* Java RMI API (org.jboss.spec.javax.rmi:jboss-rmi-api_1.0_spec:1.0.6.Final - http://www.jboss.org/jboss-rmi-api_1.0_spec)
|
||||
* XOM (xom:xom:1.2.5 - http://xom.nu)
|
||||
* XOM (xom:xom:1.3.7 - https://xom.nu)
|
||||
|
||||
Go License:
|
||||
|
||||
@@ -576,29 +552,21 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
|
||||
* Handle Server (net.handle:handle:9.3.0 - https://www.handle.net)
|
||||
|
||||
JDOM License (Apache-style license):
|
||||
|
||||
* jdom (jdom:jdom:1.0 - no url defined)
|
||||
|
||||
MIT License:
|
||||
|
||||
* Java SemVer (com.github.zafarkhaja:java-semver:0.9.0 - https://github.com/zafarkhaja/jsemver)
|
||||
* dd-plist (com.googlecode.plist:dd-plist:1.23 - http://www.github.com/3breadt/dd-plist)
|
||||
* DigitalCollections: IIIF API Library (de.digitalcollections.iiif:iiif-apis:0.3.9 - https://github.com/dbmdz/iiif-apis)
|
||||
* CDM core library (edu.ucar:cdm:4.5.5 - http://www.unidata.ucar.edu/software/netcdf-java/documentation.htm)
|
||||
* GRIB IOSP and Feature Collection (edu.ucar:grib:4.5.5 - http://www.unidata.ucar.edu/software/netcdf-java/)
|
||||
* HttpClient Wrappers (edu.ucar:httpservices:4.5.5 - http://www.unidata.ucar.edu/software/netcdf-java/documentation.htm)
|
||||
* netCDF-4 IOSP JNI connection to C library (edu.ucar:netcdf4:4.5.5 - http://www.unidata.ucar.edu/software/netcdf-java/netcdf4/)
|
||||
* udunits (edu.ucar:udunits:4.5.5 - http://www.unidata.ucar.edu/software/udunits//)
|
||||
* JOpt Simple (net.sf.jopt-simple:jopt-simple:5.0.4 - http://jopt-simple.github.io/jopt-simple)
|
||||
* Bouncy Castle S/MIME API (org.bouncycastle:bcmail-jdk15on:1.65 - http://www.bouncycastle.org/java.html)
|
||||
* Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk15on:1.65 - http://www.bouncycastle.org/java.html)
|
||||
* Bouncy Castle Provider (org.bouncycastle:bcprov-jdk15on:1.65 - http://www.bouncycastle.org/java.html)
|
||||
* Bouncy Castle S/MIME API (org.bouncycastle:bcmail-jdk15on:1.70 - https://www.bouncycastle.org/java.html)
|
||||
* Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk15on:1.70 - https://www.bouncycastle.org/java.html)
|
||||
* Bouncy Castle Provider (org.bouncycastle:bcprov-jdk15on:1.70 - https://www.bouncycastle.org/java.html)
|
||||
* Bouncy Castle ASN.1 Extension and Utility APIs (org.bouncycastle:bcutil-jdk15on:1.70 - https://www.bouncycastle.org/java.html)
|
||||
* org.brotli:dec (org.brotli:dec:0.1.2 - http://brotli.org/dec)
|
||||
* Checker Qual (org.checkerframework:checker-qual:3.10.0 - https://checkerframework.org)
|
||||
* Checker Qual (org.checkerframework:checker-qual:3.5.0 - https://checkerframework.org)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* Itadaki jbzip2 (org.itadaki:bzip2:0.9.1 - https://code.google.com/p/jbzip2/)
|
||||
* jsoup Java HTML Parser (org.jsoup:jsoup:1.13.1 - https://jsoup.org/)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* 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)
|
||||
* ORCID - Model (org.orcid:orcid-model:3.0.2 - http://github.com/ORCID/orcid-model)
|
||||
@@ -606,29 +574,33 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
* JUL to SLF4J bridge (org.slf4j:jul-to-slf4j:1.7.25 - http://www.slf4j.org)
|
||||
* SLF4J API Module (org.slf4j:slf4j-api:1.7.25 - http://www.slf4j.org)
|
||||
* SLF4J Extensions Module (org.slf4j:slf4j-ext:1.7.28 - http://www.slf4j.org)
|
||||
* HAL Browser (org.webjars:hal-browser:ad9b865 - http://webjars.org)
|
||||
* toastr (org.webjars.bowergithub.codeseven:toastr:2.1.4 - http://webjars.org)
|
||||
* jquery (org.webjars.bowergithub.jquery:jquery-dist:3.5.1 - https://www.webjars.org)
|
||||
* bootstrap (org.webjars.bowergithub.twbs:bootstrap:4.5.2 - https://www.webjars.org)
|
||||
* backbone (org.webjars.bowergithub.jashkenas:backbone:1.4.1 - https://www.webjars.org)
|
||||
* underscore (org.webjars.bowergithub.jashkenas:underscore:1.13.2 - https://www.webjars.org)
|
||||
* jquery (org.webjars.bowergithub.jquery:jquery-dist:3.6.0 - https://www.webjars.org)
|
||||
* urijs (org.webjars.bowergithub.medialize:uri.js:1.19.10 - https://www.webjars.org)
|
||||
* bootstrap (org.webjars.bowergithub.twbs:bootstrap:4.6.1 - https://www.webjars.org)
|
||||
* core-js (org.webjars.npm:core-js:3.22.8 - https://www.webjars.org)
|
||||
* @json-editor/json-editor (org.webjars.npm:json-editor__json-editor:2.6.1 - https://www.webjars.org)
|
||||
|
||||
Mozilla Public License:
|
||||
|
||||
* juniversalchardet (com.googlecode.juniversalchardet:juniversalchardet:1.0.3 - http://juniversalchardet.googlecode.com/)
|
||||
* h2 (com.h2database:h2:1.4.187 - no url defined)
|
||||
* H2 Database Engine (com.h2database:h2:2.1.210 - https://h2database.com)
|
||||
* Saxon-HE (net.sf.saxon:Saxon-HE:9.8.0-14 - http://www.saxonica.com/)
|
||||
* Javassist (org.javassist:javassist:3.25.0-GA - http://www.javassist.org/)
|
||||
* Mozilla Rhino (org.mozilla:rhino:1.7.7.2 - https://developer.mozilla.org/en/Rhino)
|
||||
|
||||
OGC copyright:
|
||||
|
||||
* GeoAPI (org.opengis:geoapi:3.0.1 - http://www.geoapi.org/geoapi/)
|
||||
|
||||
Public Domain:
|
||||
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-core-common (org.glassfish.jersey.core:jersey-common:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-core-common (org.glassfish.jersey.core:jersey-common:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-common)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* HdrHistogram (org.hdrhistogram:HdrHistogram:2.1.12 - http://hdrhistogram.github.io/HdrHistogram/)
|
||||
* LatencyUtils (org.latencyutils:LatencyUtils:2.0.3 - http://latencyutils.github.io/LatencyUtils/)
|
||||
* Reflections (org.reflections:reflections:0.9.12 - http://github.com/ronmamo/reflections)
|
||||
* XZ for Java (org.tukaani:xz:1.8 - https://tukaani.org/xz/java.html)
|
||||
* XZ for Java (org.tukaani:xz:1.9 - https://tukaani.org/xz/java.html)
|
||||
|
||||
The JSON License:
|
||||
|
||||
@@ -636,7 +608,7 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
|
||||
UnRar License:
|
||||
|
||||
* Java UnRar (com.github.junrar:junrar:4.0.0 - https://github.com/junrar/junrar)
|
||||
* Java Unrar (com.github.junrar:junrar:7.4.1 - https://github.com/junrar/junrar)
|
||||
|
||||
Unicode/ICU License:
|
||||
|
||||
@@ -644,10 +616,10 @@ https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines
|
||||
|
||||
W3C license:
|
||||
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
|
||||
jQuery license:
|
||||
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.30.1 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
* jersey-core-client (org.glassfish.jersey.core:jersey-client:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/jersey-client)
|
||||
* jersey-inject-hk2 (org.glassfish.jersey.inject:jersey-hk2:2.35 - https://projects.eclipse.org/projects/ee4j.jersey/project/jersey-hk2)
|
||||
|
@@ -35,7 +35,7 @@ Documentation for each release may be viewed online or downloaded via our [Docum
|
||||
The latest DSpace Installation instructions are available at:
|
||||
https://wiki.lyrasis.org/display/DSDOC7x/Installing+DSpace
|
||||
|
||||
Please be aware that, as a Java web application, DSpace requires a database (PostgreSQL or Oracle)
|
||||
Please be aware that, as a Java web application, DSpace requires a database (PostgreSQL)
|
||||
and a servlet container (usually Tomcat) in order to function.
|
||||
More information about these and all other prerequisites can be found in the Installation instructions above.
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-parent</artifactId>
|
||||
<version>7.2</version>
|
||||
<version>7.4-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -334,18 +334,47 @@
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-ehcache</artifactId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<exclusions>
|
||||
<!-- Newer version pulled in via Jersey below -->
|
||||
<exclusion>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-jcache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>${ehcache.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-cache
|
||||
Caching dependencies for sherpa service. -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<exclusions>
|
||||
<!-- Newer version pulled in via Jersey below -->
|
||||
<exclusion>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.cache</groupId>
|
||||
<artifactId>cache-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-jpamodelgen</artifactId>
|
||||
@@ -358,7 +387,7 @@
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||
<version>1.0.0.Final</version>
|
||||
<version>1.0.2.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -379,7 +408,7 @@
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-commons</artifactId>
|
||||
</exclusion>
|
||||
<!-- Newer version of Bouncycastle brought in via solr-cell -->
|
||||
<!-- Newer version of Bouncycastle brought in via Tika -->
|
||||
<exclusion>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
@@ -505,7 +534,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jdom</groupId>
|
||||
<artifactId>jdom</artifactId>
|
||||
<artifactId>jdom2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
@@ -515,22 +544,11 @@
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>fontbox</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-scratchpad</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xalan</groupId>
|
||||
<artifactId>xalan</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xercesImpl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ibm.icu</groupId>
|
||||
<artifactId>icu4j</artifactId>
|
||||
</dependency>
|
||||
<!-- Codebase at https://github.com/DSpace/oclc-harvester2 -->
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>oclc-harvester2</artifactId>
|
||||
@@ -566,41 +584,38 @@
|
||||
</dependency>
|
||||
<!-- Used for RSS / ATOM syndication feeds -->
|
||||
<dependency>
|
||||
<groupId>org.rometools</groupId>
|
||||
<groupId>com.rometools</groupId>
|
||||
<artifactId>rome</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rometools</groupId>
|
||||
<artifactId>rome-modules</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jbibtex</groupId>
|
||||
<artifactId>jbibtex</artifactId>
|
||||
<version>1.0.10</version>
|
||||
<version>1.0.20</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpmime</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SolrJ is used to communicate with Solr throughout the dspace-api -->
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-solrj</artifactId>
|
||||
<version>${solr.client.version}</version>
|
||||
<exclusions>
|
||||
<!-- Newer Jetty version brought in via Parent POM -->
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-http</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Solr Core is needed for Integration Tests (to run a MockSolrServer) -->
|
||||
<!-- Solr Core is only needed for Integration Tests (to run a MockSolrServer) -->
|
||||
<!-- The following Solr / Lucene dependencies also support integration tests -->
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
@@ -628,39 +643,10 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-cell</artifactId>
|
||||
<exclusions>
|
||||
<!-- Newer version brought in by opencsv -->
|
||||
<exclusion>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
</exclusion>
|
||||
<!-- Newer Jetty version brought in via Parent POM -->
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-http</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-core</artifactId>
|
||||
</dependency>
|
||||
<!-- Used for full-text indexing with Solr -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-parsers</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-icu</artifactId>
|
||||
@@ -676,9 +662,15 @@
|
||||
<artifactId>lucene-analyzers-stempel</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Tika is used to extract full text from documents in order to index in Solr -->
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlbeans</groupId>
|
||||
<artifactId>xmlbeans</artifactId>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-parsers-standard-package</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -702,13 +694,6 @@
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Gson: Java to Json conversion -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
@@ -736,7 +721,7 @@
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
<version>6.5.7</version>
|
||||
<version>8.4.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Google Analytics -->
|
||||
@@ -792,44 +777,6 @@
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Axiom -->
|
||||
<dependency>
|
||||
<groupId>org.apache.ws.commons.axiom</groupId>
|
||||
<artifactId>axiom-impl</artifactId>
|
||||
<version>${axiom.version}</version>
|
||||
<exclusions>
|
||||
<!-- Exclude Geronimo as it is NOT necessary when using javax.activation (which we use)
|
||||
See: https://ws.apache.org/axiom/userguide/ch04.html#d0e732 -->
|
||||
<exclusion>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
<!-- Exclude Woodstox, as later version provided by Solr dependencies -->
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.woodstox</groupId>
|
||||
<artifactId>woodstox-core-asl</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ws.commons.axiom</groupId>
|
||||
<artifactId>axiom-api</artifactId>
|
||||
<version>${axiom.version}</version>
|
||||
<exclusions>
|
||||
<!-- Exclude Geronimo as it is NOT necessary when using javax.activation (which we use)
|
||||
See: https://ws.apache.org/axiom/userguide/ch04.html#d0e732 -->
|
||||
<exclusion>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
<!-- Exclude Woodstox, as later version provided by Solr dependencies -->
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.woodstox</groupId>
|
||||
<artifactId>woodstox-core-asl</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Jersey / JAX-RS client (javax.ws.rs.*) dependencies needed to integrate with external sources/services -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
@@ -848,7 +795,7 @@
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>1.12.116</version>
|
||||
<version>1.12.261</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -885,18 +832,25 @@
|
||||
<version>20180130</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Useful for testing command-line tools -->
|
||||
<dependency>
|
||||
<groupId>com.github.stefanbirkner</groupId>
|
||||
<artifactId>system-rules</artifactId>
|
||||
<version>1.19.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Used for Solr core export/import -->
|
||||
<dependency>
|
||||
<groupId>com.opencsv</groupId>
|
||||
<artifactId>opencsv</artifactId>
|
||||
<version>5.2</version>
|
||||
<version>5.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Email templating -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -918,18 +872,18 @@
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.stefanbirkner</groupId>
|
||||
<artifactId>system-rules</artifactId>
|
||||
<version>1.19.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-junit-rule</artifactId>
|
||||
<version>5.11.2</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<!-- Exclude snakeyaml to avoid conflicts with: spring-boot-starter-cache -->
|
||||
<exclusion>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -971,7 +925,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId>
|
||||
<version>2.2</version>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
|
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.access.status;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Plugin interface for the access status calculation.
|
||||
*/
|
||||
public interface AccessStatusHelper {
|
||||
/**
|
||||
* Calculate the access status for the item.
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param item the item
|
||||
* @return an access status value
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
public String getAccessStatusFromItem(Context context, Item item, Date threshold)
|
||||
throws SQLException;
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.access.status;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.dspace.access.status.service.AccessStatusService;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.service.PluginService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Implementation for the access status calculation service.
|
||||
*/
|
||||
public class AccessStatusServiceImpl implements AccessStatusService {
|
||||
// Plugin implementation, set from the DSpace configuration by init().
|
||||
protected AccessStatusHelper helper = null;
|
||||
|
||||
protected Date forever_date = null;
|
||||
|
||||
@Autowired(required = true)
|
||||
protected ConfigurationService configurationService;
|
||||
|
||||
@Autowired(required = true)
|
||||
protected PluginService pluginService;
|
||||
|
||||
/**
|
||||
* Initialize the bean (after dependency injection has already taken place).
|
||||
* Ensures the configurationService is injected, so that we can get the plugin
|
||||
* and the forever embargo date threshold from the configuration.
|
||||
* Called by "init-method" in Spring configuration.
|
||||
*
|
||||
* @throws Exception on generic exception
|
||||
*/
|
||||
public void init() throws Exception {
|
||||
if (helper == null) {
|
||||
helper = (AccessStatusHelper) pluginService.getSinglePlugin(AccessStatusHelper.class);
|
||||
if (helper == null) {
|
||||
throw new IllegalStateException("The AccessStatusHelper plugin was not defined in "
|
||||
+ "DSpace configuration.");
|
||||
}
|
||||
|
||||
// Defines the embargo forever date threshold for the access status.
|
||||
// Look at EmbargoService.FOREVER for some improvements?
|
||||
int year = configurationService.getIntProperty("access.status.embargo.forever.year");
|
||||
int month = configurationService.getIntProperty("access.status.embargo.forever.month");
|
||||
int day = configurationService.getIntProperty("access.status.embargo.forever.day");
|
||||
|
||||
forever_date = new LocalDate(year, month, day).toDate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessStatus(Context context, Item item) throws SQLException {
|
||||
return helper.getAccessStatusFromItem(context, item, forever_date);
|
||||
}
|
||||
}
|
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* 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.access.status;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
import org.dspace.content.Bitstream;
|
||||
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.ItemService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.Group;
|
||||
|
||||
/**
|
||||
* Default plugin implementation of the access status helper.
|
||||
* The getAccessStatusFromItem method provides a simple logic to
|
||||
* calculate the access status of an item based on the policies of
|
||||
* the primary or the first bitstream in the original bundle.
|
||||
* Users can override this method for enhanced functionality.
|
||||
*/
|
||||
public class DefaultAccessStatusHelper implements AccessStatusHelper {
|
||||
public static final String EMBARGO = "embargo";
|
||||
public static final String METADATA_ONLY = "metadata.only";
|
||||
public static final String OPEN_ACCESS = "open.access";
|
||||
public static final String RESTRICTED = "restricted";
|
||||
public static final String UNKNOWN = "unknown";
|
||||
|
||||
protected ItemService itemService =
|
||||
ContentServiceFactory.getInstance().getItemService();
|
||||
protected ResourcePolicyService resourcePolicyService =
|
||||
AuthorizeServiceFactory.getInstance().getResourcePolicyService();
|
||||
protected AuthorizeService authorizeService =
|
||||
AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||
|
||||
public DefaultAccessStatusHelper() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Look at the item's policies to determine an access status value.
|
||||
* It is also considering a date threshold for embargos and restrictions.
|
||||
*
|
||||
* If the item is null, simply returns the "unknown" value.
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param item the item to embargo
|
||||
* @param threshold the embargo threshold date
|
||||
* @return an access status value
|
||||
*/
|
||||
@Override
|
||||
public String getAccessStatusFromItem(Context context, Item item, Date threshold)
|
||||
throws SQLException {
|
||||
if (item == null) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
// Consider only the original bundles.
|
||||
List<Bundle> bundles = item.getBundles(Constants.DEFAULT_BUNDLE_NAME);
|
||||
// Check for primary bitstreams first.
|
||||
Bitstream bitstream = bundles.stream()
|
||||
.map(bundle -> bundle.getPrimaryBitstream())
|
||||
.filter(Objects::nonNull)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (bitstream == null) {
|
||||
// If there is no primary bitstream,
|
||||
// take the first bitstream in the bundles.
|
||||
bitstream = bundles.stream()
|
||||
.map(bundle -> bundle.getBitstreams())
|
||||
.flatMap(List::stream)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
return caculateAccessStatusForDso(context, bitstream, threshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look at the DSpace object's policies to determine an access status value.
|
||||
*
|
||||
* If the object is null, returns the "metadata.only" value.
|
||||
* If any policy attached to the object is valid for the anonymous group,
|
||||
* returns the "open.access" value.
|
||||
* Otherwise, if the policy start date is before the embargo threshold date,
|
||||
* returns the "embargo" value.
|
||||
* Every other cases return the "restricted" value.
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param dso the DSpace object
|
||||
* @param threshold the embargo threshold date
|
||||
* @return an access status value
|
||||
*/
|
||||
private String caculateAccessStatusForDso(Context context, DSpaceObject dso, Date threshold)
|
||||
throws SQLException {
|
||||
if (dso == null) {
|
||||
return METADATA_ONLY;
|
||||
}
|
||||
// Only consider read policies.
|
||||
List<ResourcePolicy> policies = authorizeService
|
||||
.getPoliciesActionFilter(context, dso, Constants.READ);
|
||||
int openAccessCount = 0;
|
||||
int embargoCount = 0;
|
||||
int restrictedCount = 0;
|
||||
int unknownCount = 0;
|
||||
// Looks at all read policies.
|
||||
for (ResourcePolicy policy : policies) {
|
||||
boolean isValid = resourcePolicyService.isDateValid(policy);
|
||||
Group group = policy.getGroup();
|
||||
// The group must not be null here. However,
|
||||
// if it is, consider this as an unexpected case.
|
||||
if (group == null) {
|
||||
unknownCount++;
|
||||
} else if (StringUtils.equals(group.getName(), Group.ANONYMOUS)) {
|
||||
// Only calculate the status for the anonymous group.
|
||||
if (isValid) {
|
||||
// If the policy is valid, the anonymous group have access
|
||||
// to the bitstream.
|
||||
openAccessCount++;
|
||||
} else {
|
||||
Date startDate = policy.getStartDate();
|
||||
if (startDate != null && !startDate.before(threshold)) {
|
||||
// If the policy start date have a value and if this value
|
||||
// is equal or superior to the configured forever date, the
|
||||
// access status is also restricted.
|
||||
restrictedCount++;
|
||||
} else {
|
||||
// If the current date is not between the policy start date
|
||||
// and end date, the access status is embargo.
|
||||
embargoCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (openAccessCount > 0) {
|
||||
return OPEN_ACCESS;
|
||||
}
|
||||
if (embargoCount > 0 && restrictedCount == 0) {
|
||||
return EMBARGO;
|
||||
}
|
||||
if (unknownCount > 0) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
return RESTRICTED;
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.access.status.factory;
|
||||
|
||||
import org.dspace.access.status.service.AccessStatusService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
/**
|
||||
* Abstract factory to get services for the access status package,
|
||||
* use AccessStatusServiceFactory.getInstance() to retrieve an implementation.
|
||||
*/
|
||||
public abstract class AccessStatusServiceFactory {
|
||||
|
||||
public abstract AccessStatusService getAccessStatusService();
|
||||
|
||||
public static AccessStatusServiceFactory getInstance() {
|
||||
return DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServiceByName("accessStatusServiceFactory", AccessStatusServiceFactory.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.access.status.factory;
|
||||
|
||||
import org.dspace.access.status.service.AccessStatusService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Factory implementation to get services for the access status package,
|
||||
* use AccessStatusServiceFactory.getInstance() to retrieve an implementation.
|
||||
*/
|
||||
public class AccessStatusServiceFactoryImpl extends AccessStatusServiceFactory {
|
||||
|
||||
@Autowired(required = true)
|
||||
private AccessStatusService accessStatusService;
|
||||
|
||||
@Override
|
||||
public AccessStatusService getAccessStatusService() {
|
||||
return accessStatusService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
/**
|
||||
* <p>
|
||||
* Access status allows the users to view the bitstreams availability before
|
||||
* browsing into the item itself.
|
||||
* </p>
|
||||
* <p>
|
||||
* The access status is calculated through a pluggable class:
|
||||
* {@link org.dspace.access.status.AccessStatusHelper}.
|
||||
* The {@link org.dspace.access.status.AccessStatusServiceImpl}
|
||||
* must be configured to specify this class, as well as a forever embargo date
|
||||
* threshold year, month and day.
|
||||
* </p>
|
||||
* <p>
|
||||
* See {@link org.dspace.access.status.DefaultAccessStatusHelper} for a simple calculation
|
||||
* based on the primary or the first bitstream of the original bundle. You can
|
||||
* supply your own class to implement more complex access statuses.
|
||||
* </p>
|
||||
* <p>
|
||||
* For now, the access status is calculated when the item is shown in a list.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
package org.dspace.access.status;
|
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.access.status.service;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Public interface to the access status subsystem.
|
||||
* <p>
|
||||
* Configuration properties: (with examples)
|
||||
* {@code
|
||||
* # values for the forever embargo date threshold
|
||||
* # This threshold date is used in the default access status helper to dermine if an item is
|
||||
* # restricted or embargoed based on the start date of the primary (or first) file policies.
|
||||
* # In this case, if the policy start date is inferior to the threshold date, the status will
|
||||
* # be embargo, else it will be restricted.
|
||||
* # You might want to change this threshold based on your needs. For example: some databases
|
||||
* # doesn't accept a date superior to 31 december 9999.
|
||||
* access.status.embargo.forever.year = 10000
|
||||
* access.status.embargo.forever.month = 1
|
||||
* access.status.embargo.forever.day = 1
|
||||
* # implementation of access status helper plugin - replace with local implementation if applicable
|
||||
* # This default access status helper provides an item status based on the policies of the primary
|
||||
* # bitstream (or first bitstream in the original bundles if no primary file is specified).
|
||||
* plugin.single.org.dspace.access.status.AccessStatusHelper = org.dspace.access.status.DefaultAccessStatusHelper
|
||||
* }
|
||||
*/
|
||||
public interface AccessStatusService {
|
||||
|
||||
/**
|
||||
* Calculate the access status for an Item while considering the forever embargo date threshold.
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param item the item
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
public String getAccessStatus(Context context, Item item) throws SQLException;
|
||||
}
|
@@ -14,6 +14,7 @@ import java.util.Locale;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.core.Context;
|
||||
@@ -54,14 +55,14 @@ public final class CreateAdministrator {
|
||||
protected GroupService groupService;
|
||||
|
||||
/**
|
||||
* For invoking via the command line. If called with no command line arguments,
|
||||
* For invoking via the command line. If called with no command line arguments,
|
||||
* it will negotiate with the user for the administrator details
|
||||
*
|
||||
* @param argv the command line arguments given
|
||||
* @throws Exception if error
|
||||
*/
|
||||
public static void main(String[] argv)
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
Options options = new Options();
|
||||
|
||||
@@ -69,19 +70,41 @@ public final class CreateAdministrator {
|
||||
|
||||
options.addOption("e", "email", true, "administrator email address");
|
||||
options.addOption("f", "first", true, "administrator first name");
|
||||
options.addOption("h", "help", false, "explain create-administrator options");
|
||||
options.addOption("l", "last", true, "administrator last name");
|
||||
options.addOption("c", "language", true, "administrator language");
|
||||
options.addOption("p", "password", true, "administrator password");
|
||||
|
||||
CommandLine line = parser.parse(options, argv);
|
||||
CommandLine line = null;
|
||||
|
||||
try {
|
||||
|
||||
line = parser.parse(options, argv);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
System.out.println(e.getMessage() + "\nTry \"dspace create-administrator -h\" to print help information.");
|
||||
System.exit(1);
|
||||
|
||||
}
|
||||
|
||||
if (line.hasOption("e") && line.hasOption("f") && line.hasOption("l") &&
|
||||
line.hasOption("c") && line.hasOption("p")) {
|
||||
line.hasOption("c") && line.hasOption("p")) {
|
||||
ca.createAdministrator(line.getOptionValue("e"),
|
||||
line.getOptionValue("f"), line.getOptionValue("l"),
|
||||
line.getOptionValue("c"), line.getOptionValue("p"));
|
||||
line.getOptionValue("f"), line.getOptionValue("l"),
|
||||
line.getOptionValue("c"), line.getOptionValue("p"));
|
||||
} else if (line.hasOption("h")) {
|
||||
String header = "\nA command-line tool for creating an initial administrator for setting up a" +
|
||||
" DSpace site. Unless all the required parameters are passed it will" +
|
||||
" prompt for an e-mail address, last name, first name and password from" +
|
||||
" standard input.. An administrator group is then created and the data passed" +
|
||||
" in used to create an e-person in that group.\n\n";
|
||||
String footer = "\n";
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
formatter.printHelp("dspace create-administrator", header, options, footer, true);
|
||||
return;
|
||||
} else {
|
||||
ca.negotiateAdministratorDetails();
|
||||
ca.negotiateAdministratorDetails(line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +114,7 @@ public final class CreateAdministrator {
|
||||
* @throws Exception if error
|
||||
*/
|
||||
protected CreateAdministrator()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
context = new Context();
|
||||
groupService = EPersonServiceFactory.getInstance().getGroupService();
|
||||
ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||
@@ -103,20 +126,20 @@ public final class CreateAdministrator {
|
||||
*
|
||||
* @throws Exception if error
|
||||
*/
|
||||
protected void negotiateAdministratorDetails()
|
||||
throws Exception {
|
||||
protected void negotiateAdministratorDetails(CommandLine line)
|
||||
throws Exception {
|
||||
Console console = System.console();
|
||||
|
||||
System.out.println("Creating an initial administrator account");
|
||||
|
||||
boolean dataOK = false;
|
||||
|
||||
String email = null;
|
||||
String firstName = null;
|
||||
String lastName = null;
|
||||
char[] password1 = null;
|
||||
char[] password2 = null;
|
||||
String email = line.getOptionValue('e');
|
||||
String firstName = line.getOptionValue('f');
|
||||
String lastName = line.getOptionValue('l');
|
||||
String language = I18nUtil.getDefaultLocale().getLanguage();
|
||||
ConfigurationService cfg = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
boolean flag = line.hasOption('p');
|
||||
char[] password = null;
|
||||
boolean dataOK = line.hasOption('f') && line.hasOption('e') && line.hasOption('l');
|
||||
|
||||
while (!dataOK) {
|
||||
System.out.print("E-mail address: ");
|
||||
@@ -147,8 +170,6 @@ public final class CreateAdministrator {
|
||||
if (lastName != null) {
|
||||
lastName = lastName.trim();
|
||||
}
|
||||
|
||||
ConfigurationService cfg = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
if (cfg.hasProperty("webui.supported.locales")) {
|
||||
System.out.println("Select one of the following languages: "
|
||||
+ cfg.getProperty("webui.supported.locales"));
|
||||
@@ -163,46 +184,59 @@ public final class CreateAdministrator {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Password will not display on screen.");
|
||||
System.out.print("Password: ");
|
||||
System.out.print("Is the above data correct? (y or n): ");
|
||||
System.out.flush();
|
||||
|
||||
password1 = console.readPassword();
|
||||
String s = console.readLine();
|
||||
|
||||
System.out.print("Again to confirm: ");
|
||||
System.out.flush();
|
||||
|
||||
password2 = console.readPassword();
|
||||
|
||||
//TODO real password validation
|
||||
if (password1.length > 1 && Arrays.equals(password1, password2)) {
|
||||
// password OK
|
||||
System.out.print("Is the above data correct? (y or n): ");
|
||||
System.out.flush();
|
||||
|
||||
String s = console.readLine();
|
||||
|
||||
if (s != null) {
|
||||
s = s.trim();
|
||||
if (s.toLowerCase().startsWith("y")) {
|
||||
dataOK = true;
|
||||
}
|
||||
if (s != null) {
|
||||
s = s.trim();
|
||||
if (s.toLowerCase().startsWith("y")) {
|
||||
dataOK = true;
|
||||
}
|
||||
} else {
|
||||
System.out.println("Passwords don't match");
|
||||
}
|
||||
|
||||
}
|
||||
if (!flag) {
|
||||
password = getPassword(console);
|
||||
if (password == null) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
password = line.getOptionValue("p").toCharArray();
|
||||
}
|
||||
|
||||
// if we make it to here, we are ready to create an administrator
|
||||
createAdministrator(email, firstName, lastName, language, String.valueOf(password1));
|
||||
createAdministrator(email, firstName, lastName, language, String.valueOf(password));
|
||||
|
||||
//Cleaning arrays that held password
|
||||
Arrays.fill(password1, ' ');
|
||||
Arrays.fill(password2, ' ');
|
||||
}
|
||||
|
||||
private char[] getPassword(Console console) {
|
||||
char[] password1 = null;
|
||||
char[] password2 = null;
|
||||
System.out.println("Password will not display on screen.");
|
||||
System.out.print("Password: ");
|
||||
System.out.flush();
|
||||
|
||||
password1 = console.readPassword();
|
||||
|
||||
System.out.print("Again to confirm: ");
|
||||
System.out.flush();
|
||||
|
||||
password2 = console.readPassword();
|
||||
|
||||
// TODO real password validation
|
||||
if (password1.length > 1 && Arrays.equals(password1, password2)) {
|
||||
// password OK
|
||||
Arrays.fill(password2, ' ');
|
||||
return password1;
|
||||
} else {
|
||||
System.out.println("Passwords don't match");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the administrator with the given details. If the user
|
||||
* Create the administrator with the given details. If the user
|
||||
* already exists then they are simply upped to administrator status
|
||||
*
|
||||
* @param email the email for the user
|
||||
@@ -213,8 +247,8 @@ public final class CreateAdministrator {
|
||||
* @throws Exception if error
|
||||
*/
|
||||
protected void createAdministrator(String email, String first, String last,
|
||||
String language, String pw)
|
||||
throws Exception {
|
||||
String language, String pw)
|
||||
throws Exception {
|
||||
// Of course we aren't an administrator yet so we need to
|
||||
// circumvent authorisation
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -11,13 +11,16 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.xpath.XPathAPI;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.MetadataField;
|
||||
import org.dspace.content.MetadataSchema;
|
||||
@@ -90,7 +93,7 @@ public class MetadataImporter {
|
||||
public static void main(String[] args)
|
||||
throws ParseException, SQLException, IOException, TransformerException,
|
||||
ParserConfigurationException, AuthorizeException, SAXException,
|
||||
NonUniqueMetadataException, RegistryImportException {
|
||||
NonUniqueMetadataException, RegistryImportException, XPathExpressionException {
|
||||
|
||||
// create an options object and populate it
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
@@ -124,8 +127,8 @@ public class MetadataImporter {
|
||||
* @throws RegistryImportException if import fails
|
||||
*/
|
||||
public static void loadRegistry(String file, boolean forceUpdate)
|
||||
throws SQLException, IOException, TransformerException, ParserConfigurationException,
|
||||
AuthorizeException, SAXException, NonUniqueMetadataException, RegistryImportException {
|
||||
throws SQLException, IOException, TransformerException, ParserConfigurationException, AuthorizeException,
|
||||
SAXException, NonUniqueMetadataException, RegistryImportException, XPathExpressionException {
|
||||
Context context = null;
|
||||
|
||||
try {
|
||||
@@ -137,7 +140,9 @@ public class MetadataImporter {
|
||||
Document document = RegistryImporter.loadXML(file);
|
||||
|
||||
// Get the nodes corresponding to types
|
||||
NodeList schemaNodes = XPathAPI.selectNodeList(document, "/dspace-dc-types/dc-schema");
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
NodeList schemaNodes = (NodeList) xPath.compile("/dspace-dc-types/dc-schema")
|
||||
.evaluate(document, XPathConstants.NODESET);
|
||||
|
||||
// Add each one as a new format to the registry
|
||||
for (int i = 0; i < schemaNodes.getLength(); i++) {
|
||||
@@ -146,7 +151,8 @@ public class MetadataImporter {
|
||||
}
|
||||
|
||||
// Get the nodes corresponding to types
|
||||
NodeList typeNodes = XPathAPI.selectNodeList(document, "/dspace-dc-types/dc-type");
|
||||
NodeList typeNodes = (NodeList) xPath.compile("/dspace-dc-types/dc-type")
|
||||
.evaluate(document, XPathConstants.NODESET);
|
||||
|
||||
// Add each one as a new format to the registry
|
||||
for (int i = 0; i < typeNodes.getLength(); i++) {
|
||||
@@ -178,8 +184,8 @@ public class MetadataImporter {
|
||||
* @throws RegistryImportException if import fails
|
||||
*/
|
||||
private static void loadSchema(Context context, Node node, boolean updateExisting)
|
||||
throws SQLException, IOException, TransformerException,
|
||||
AuthorizeException, NonUniqueMetadataException, RegistryImportException {
|
||||
throws SQLException, AuthorizeException, NonUniqueMetadataException, RegistryImportException,
|
||||
XPathExpressionException {
|
||||
// Get the values
|
||||
String name = RegistryImporter.getElementData(node, "name");
|
||||
String namespace = RegistryImporter.getElementData(node, "namespace");
|
||||
@@ -236,8 +242,8 @@ public class MetadataImporter {
|
||||
* @throws RegistryImportException if import fails
|
||||
*/
|
||||
private static void loadType(Context context, Node node)
|
||||
throws SQLException, IOException, TransformerException,
|
||||
AuthorizeException, NonUniqueMetadataException, RegistryImportException {
|
||||
throws SQLException, IOException, AuthorizeException, NonUniqueMetadataException, RegistryImportException,
|
||||
XPathExpressionException {
|
||||
// Get the values
|
||||
String schema = RegistryImporter.getElementData(node, "schema");
|
||||
String element = RegistryImporter.getElementData(node, "element");
|
||||
|
@@ -13,8 +13,11 @@ import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.xpath.XPathAPI;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
@@ -72,9 +75,10 @@ public class RegistryImporter {
|
||||
* @throws TransformerException if error
|
||||
*/
|
||||
public static String getElementData(Node parentElement, String childName)
|
||||
throws TransformerException {
|
||||
throws XPathExpressionException {
|
||||
// Grab the child node
|
||||
Node childNode = XPathAPI.selectSingleNode(parentElement, childName);
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
Node childNode = (Node) xPath.compile(childName).evaluate(parentElement, XPathConstants.NODE);
|
||||
|
||||
if (childNode == null) {
|
||||
// No child node, so no values
|
||||
@@ -115,9 +119,10 @@ public class RegistryImporter {
|
||||
* @throws TransformerException if error
|
||||
*/
|
||||
public static String[] getRepeatedElementData(Node parentElement,
|
||||
String childName) throws TransformerException {
|
||||
String childName) throws XPathExpressionException {
|
||||
// Grab the child node
|
||||
NodeList childNodes = XPathAPI.selectNodeList(parentElement, childName);
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
NodeList childNodes = (NodeList) xPath.compile(childName).evaluate(parentElement, XPathConstants.NODESET);
|
||||
|
||||
String[] data = new String[childNodes.getLength()];
|
||||
|
||||
|
@@ -16,9 +16,12 @@ import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.xpath.XPathAPI;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.BitstreamFormat;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
@@ -122,12 +125,13 @@ public class RegistryLoader {
|
||||
*/
|
||||
public static void loadBitstreamFormats(Context context, String filename)
|
||||
throws SQLException, IOException, ParserConfigurationException,
|
||||
SAXException, TransformerException, AuthorizeException {
|
||||
SAXException, TransformerException, AuthorizeException, XPathExpressionException {
|
||||
Document document = loadXML(filename);
|
||||
|
||||
// Get the nodes corresponding to formats
|
||||
NodeList typeNodes = XPathAPI.selectNodeList(document,
|
||||
"dspace-bitstream-types/bitstream-type");
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
NodeList typeNodes = (NodeList) xPath.compile("dspace-bitstream-types/bitstream-type")
|
||||
.evaluate(document, XPathConstants.NODESET);
|
||||
|
||||
// Add each one as a new format to the registry
|
||||
for (int i = 0; i < typeNodes.getLength(); i++) {
|
||||
@@ -151,8 +155,7 @@ public class RegistryLoader {
|
||||
* @throws AuthorizeException if authorization error
|
||||
*/
|
||||
private static void loadFormat(Context context, Node node)
|
||||
throws SQLException, IOException, TransformerException,
|
||||
AuthorizeException {
|
||||
throws SQLException, AuthorizeException, XPathExpressionException {
|
||||
// Get the values
|
||||
String mimeType = getElementData(node, "mimetype");
|
||||
String shortDesc = getElementData(node, "short_description");
|
||||
@@ -231,9 +234,10 @@ public class RegistryLoader {
|
||||
* @throws TransformerException if transformer error
|
||||
*/
|
||||
private static String getElementData(Node parentElement, String childName)
|
||||
throws TransformerException {
|
||||
throws XPathExpressionException {
|
||||
// Grab the child node
|
||||
Node childNode = XPathAPI.selectSingleNode(parentElement, childName);
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
Node childNode = (Node) xPath.compile(childName).evaluate(parentElement, XPathConstants.NODE);
|
||||
|
||||
if (childNode == null) {
|
||||
// No child node, so no values
|
||||
@@ -274,9 +278,10 @@ public class RegistryLoader {
|
||||
* @throws TransformerException if transformer error
|
||||
*/
|
||||
private static String[] getRepeatedElementData(Node parentElement,
|
||||
String childName) throws TransformerException {
|
||||
String childName) throws XPathExpressionException {
|
||||
// Grab the child node
|
||||
NodeList childNodes = XPathAPI.selectNodeList(parentElement, childName);
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
NodeList childNodes = (NodeList) xPath.compile(childName).evaluate(parentElement, XPathConstants.NODESET);
|
||||
|
||||
String[] data = new String[childNodes.getLength()];
|
||||
|
||||
|
@@ -30,6 +30,10 @@ import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
@@ -38,7 +42,7 @@ import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.xpath.XPathAPI;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
@@ -52,9 +56,11 @@ import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.output.Format;
|
||||
import org.jdom.output.XMLOutputter;
|
||||
import org.dspace.handle.factory.HandleServiceFactory;
|
||||
import org.dspace.handle.service.HandleService;
|
||||
import org.jdom2.Element;
|
||||
import org.jdom2.output.Format;
|
||||
import org.jdom2.output.XMLOutputter;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
@@ -76,6 +82,7 @@ import org.xml.sax.SAXException;
|
||||
* </community>
|
||||
* </import_structure>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* It can be arbitrarily deep, and supports all the metadata elements
|
||||
* that make up the community and collection metadata. See the system
|
||||
@@ -104,12 +111,14 @@ public class StructBuilder {
|
||||
*/
|
||||
private static final Map<String, MetadataFieldName> communityMap = new HashMap<>();
|
||||
|
||||
protected static CommunityService communityService
|
||||
protected static final CommunityService communityService
|
||||
= ContentServiceFactory.getInstance().getCommunityService();
|
||||
protected static CollectionService collectionService
|
||||
protected static final CollectionService collectionService
|
||||
= ContentServiceFactory.getInstance().getCollectionService();
|
||||
protected static EPersonService ePersonService
|
||||
protected static final EPersonService ePersonService
|
||||
= EPersonServiceFactory.getInstance().getEPersonService();
|
||||
protected static final HandleService handleService
|
||||
= HandleServiceFactory.getInstance().getHandleService();
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
@@ -135,16 +144,18 @@ public class StructBuilder {
|
||||
* @throws SQLException passed through.
|
||||
* @throws FileNotFoundException if input or output could not be opened.
|
||||
* @throws TransformerException if the input document is invalid.
|
||||
* @throws XPathExpressionException passed through.
|
||||
*/
|
||||
public static void main(String[] argv)
|
||||
throws ParserConfigurationException, SQLException,
|
||||
FileNotFoundException, IOException, TransformerException {
|
||||
throws ParserConfigurationException, SQLException,
|
||||
IOException, TransformerException, XPathExpressionException {
|
||||
// Define command line options.
|
||||
Options options = new Options();
|
||||
|
||||
options.addOption("h", "help", false, "Print this help message.");
|
||||
options.addOption("?", "help");
|
||||
options.addOption("x", "export", false, "Export the current structure as XML.");
|
||||
options.addOption("k", "keep-handles", false, "Apply Handles from input document.");
|
||||
|
||||
options.addOption(Option.builder("e").longOpt("eperson")
|
||||
.desc("User who is manipulating the repository's structure.")
|
||||
@@ -206,6 +217,7 @@ public class StructBuilder {
|
||||
// Export? Import?
|
||||
if (line.hasOption('x')) { // export
|
||||
exportStructure(context, outputStream);
|
||||
outputStream.close();
|
||||
} else { // Must be import
|
||||
String input = line.getOptionValue('f');
|
||||
if (null == input) {
|
||||
@@ -220,7 +232,12 @@ public class StructBuilder {
|
||||
inputStream = new FileInputStream(input);
|
||||
}
|
||||
|
||||
importStructure(context, inputStream, outputStream);
|
||||
boolean keepHandles = options.hasOption("k");
|
||||
importStructure(context, inputStream, outputStream, keepHandles);
|
||||
|
||||
inputStream.close();
|
||||
outputStream.close();
|
||||
|
||||
// save changes from import
|
||||
context.complete();
|
||||
}
|
||||
@@ -233,14 +250,17 @@ public class StructBuilder {
|
||||
* @param context
|
||||
* @param input XML which describes the new communities and collections.
|
||||
* @param output input, annotated with the new objects' identifiers.
|
||||
* @param keepHandles true if Handles should be set from input.
|
||||
* @throws IOException
|
||||
* @throws ParserConfigurationException
|
||||
* @throws SAXException
|
||||
* @throws TransformerException
|
||||
* @throws SQLException
|
||||
*/
|
||||
static void importStructure(Context context, InputStream input, OutputStream output)
|
||||
throws IOException, ParserConfigurationException, SQLException, TransformerException {
|
||||
static void importStructure(Context context, InputStream input,
|
||||
OutputStream output, boolean keepHandles)
|
||||
throws IOException, ParserConfigurationException, SQLException,
|
||||
TransformerException, XPathExpressionException {
|
||||
|
||||
// load the XML
|
||||
Document document = null;
|
||||
@@ -258,15 +278,29 @@ public class StructBuilder {
|
||||
// is properly structured.
|
||||
try {
|
||||
validate(document);
|
||||
} catch (TransformerException ex) {
|
||||
} catch (XPathExpressionException ex) {
|
||||
System.err.format("The input document is invalid: %s%n", ex.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Check for 'identifier' attributes -- possibly output by this class.
|
||||
NodeList identifierNodes = XPathAPI.selectNodeList(document, "//*[@identifier]");
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
NodeList identifierNodes = (NodeList) xPath.compile("//*[@identifier]")
|
||||
.evaluate(document, XPathConstants.NODESET);
|
||||
if (identifierNodes.getLength() > 0) {
|
||||
System.err.println("The input document has 'identifier' attributes, which will be ignored.");
|
||||
if (!keepHandles) {
|
||||
System.err.println("The input document has 'identifier' attributes, which will be ignored.");
|
||||
} else {
|
||||
for (int i = 0; i < identifierNodes.getLength() ; i++) {
|
||||
String identifier = identifierNodes.item(i).getAttributes().item(0).getTextContent();
|
||||
if (handleService.resolveToURL(context, identifier) != null) {
|
||||
System.err.printf("The input document contains handle %s,"
|
||||
+ " which is in use already. Aborting...%n",
|
||||
identifier);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load the mappings into the member variable hashmaps
|
||||
@@ -287,10 +321,11 @@ public class StructBuilder {
|
||||
Element[] elements = new Element[]{};
|
||||
try {
|
||||
// get the top level community list
|
||||
NodeList first = XPathAPI.selectNodeList(document, "/import_structure/community");
|
||||
NodeList first = (NodeList) xPath.compile("/import_structure/community")
|
||||
.evaluate(document, XPathConstants.NODESET);
|
||||
|
||||
// run the import starting with the top level communities
|
||||
elements = handleCommunities(context, first, null);
|
||||
elements = handleCommunities(context, first, null, keepHandles);
|
||||
} catch (TransformerException ex) {
|
||||
System.err.format("Input content not understood: %s%n", ex.getMessage());
|
||||
System.exit(1);
|
||||
@@ -307,7 +342,7 @@ public class StructBuilder {
|
||||
}
|
||||
|
||||
// finally write the string into the output file.
|
||||
final org.jdom.Document xmlOutput = new org.jdom.Document(root);
|
||||
final org.jdom2.Document xmlOutput = new org.jdom2.Document(root);
|
||||
try {
|
||||
new XMLOutputter().output(xmlOutput, output);
|
||||
} catch (IOException e) {
|
||||
@@ -411,7 +446,7 @@ public class StructBuilder {
|
||||
}
|
||||
|
||||
// Now write the structure out.
|
||||
org.jdom.Document xmlOutput = new org.jdom.Document(rootElement);
|
||||
org.jdom2.Document xmlOutput = new org.jdom2.Document(rootElement);
|
||||
try {
|
||||
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
|
||||
outputter.output(xmlOutput, output);
|
||||
@@ -456,14 +491,16 @@ public class StructBuilder {
|
||||
* @throws TransformerException if transformer error
|
||||
*/
|
||||
private static void validate(org.w3c.dom.Document document)
|
||||
throws TransformerException {
|
||||
throws XPathExpressionException {
|
||||
StringBuilder err = new StringBuilder();
|
||||
boolean trip = false;
|
||||
|
||||
err.append("The following errors were encountered parsing the source XML.\n");
|
||||
err.append("No changes have been made to the DSpace instance.\n\n");
|
||||
|
||||
NodeList first = XPathAPI.selectNodeList(document, "/import_structure/community");
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
NodeList first = (NodeList) xPath.compile("/import_structure/community")
|
||||
.evaluate(document, XPathConstants.NODESET);
|
||||
if (first.getLength() == 0) {
|
||||
err.append("-There are no top level communities in the source document.");
|
||||
System.out.println(err.toString());
|
||||
@@ -493,14 +530,15 @@ public class StructBuilder {
|
||||
* no errors.
|
||||
*/
|
||||
private static String validateCommunities(NodeList communities, int level)
|
||||
throws TransformerException {
|
||||
throws XPathExpressionException {
|
||||
StringBuilder err = new StringBuilder();
|
||||
boolean trip = false;
|
||||
String errs = null;
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
for (int i = 0; i < communities.getLength(); i++) {
|
||||
Node n = communities.item(i);
|
||||
NodeList name = XPathAPI.selectNodeList(n, "name");
|
||||
NodeList name = (NodeList) xPath.compile("name").evaluate(n, XPathConstants.NODESET);
|
||||
if (name.getLength() != 1) {
|
||||
String pos = Integer.toString(i + 1);
|
||||
err.append("-The level ").append(level)
|
||||
@@ -510,7 +548,7 @@ public class StructBuilder {
|
||||
}
|
||||
|
||||
// validate sub communities
|
||||
NodeList subCommunities = XPathAPI.selectNodeList(n, "community");
|
||||
NodeList subCommunities = (NodeList) xPath.compile("community").evaluate(n, XPathConstants.NODESET);
|
||||
String comErrs = validateCommunities(subCommunities, level + 1);
|
||||
if (comErrs != null) {
|
||||
err.append(comErrs);
|
||||
@@ -518,7 +556,7 @@ public class StructBuilder {
|
||||
}
|
||||
|
||||
// validate collections
|
||||
NodeList collections = XPathAPI.selectNodeList(n, "collection");
|
||||
NodeList collections = (NodeList) xPath.compile("collection").evaluate(n, XPathConstants.NODESET);
|
||||
String colErrs = validateCollections(collections, level + 1);
|
||||
if (colErrs != null) {
|
||||
err.append(colErrs);
|
||||
@@ -542,14 +580,15 @@ public class StructBuilder {
|
||||
* @return the errors to be generated by the calling method, or null if none
|
||||
*/
|
||||
private static String validateCollections(NodeList collections, int level)
|
||||
throws TransformerException {
|
||||
throws XPathExpressionException {
|
||||
StringBuilder err = new StringBuilder();
|
||||
boolean trip = false;
|
||||
String errs = null;
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
for (int i = 0; i < collections.getLength(); i++) {
|
||||
Node n = collections.item(i);
|
||||
NodeList name = XPathAPI.selectNodeList(n, "name");
|
||||
NodeList name = (NodeList) xPath.compile("name").evaluate(n, XPathConstants.NODESET);
|
||||
if (name.getLength() != 1) {
|
||||
String pos = Integer.toString(i + 1);
|
||||
err.append("-The level ").append(level)
|
||||
@@ -609,22 +648,29 @@ public class StructBuilder {
|
||||
* @param context the context of the request
|
||||
* @param communities a nodelist of communities to create along with their sub-structures
|
||||
* @param parent the parent community of the nodelist of communities to create
|
||||
* @param keepHandles use Handles from input.
|
||||
* @return an element array containing additional information regarding the
|
||||
* created communities (e.g. the handles they have been assigned)
|
||||
*/
|
||||
private static Element[] handleCommunities(Context context, NodeList communities, Community parent)
|
||||
throws TransformerException, SQLException, AuthorizeException {
|
||||
private static Element[] handleCommunities(Context context, NodeList communities,
|
||||
Community parent, boolean keepHandles)
|
||||
throws TransformerException, SQLException, AuthorizeException,
|
||||
XPathExpressionException {
|
||||
Element[] elements = new Element[communities.getLength()];
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
for (int i = 0; i < communities.getLength(); i++) {
|
||||
Community community;
|
||||
Element element = new Element("community");
|
||||
Node tn = communities.item(i);
|
||||
Node identifier = tn.getAttributes().getNamedItem("identifier");
|
||||
|
||||
// create the community or sub community
|
||||
if (parent != null) {
|
||||
Community community;
|
||||
if (null == identifier
|
||||
|| StringUtils.isBlank(identifier.getNodeValue())
|
||||
|| !keepHandles) {
|
||||
community = communityService.create(parent, context);
|
||||
} else {
|
||||
community = communityService.create(null, context);
|
||||
community = communityService.create(parent, context, identifier.getNodeValue());
|
||||
}
|
||||
|
||||
// default the short description to be an empty string
|
||||
@@ -632,9 +678,8 @@ public class StructBuilder {
|
||||
MD_SHORT_DESCRIPTION, null, " ");
|
||||
|
||||
// now update the metadata
|
||||
Node tn = communities.item(i);
|
||||
for (Map.Entry<String, MetadataFieldName> entry : communityMap.entrySet()) {
|
||||
NodeList nl = XPathAPI.selectNodeList(tn, entry.getKey());
|
||||
NodeList nl = (NodeList) xPath.compile(entry.getKey()).evaluate(tn, XPathConstants.NODESET);
|
||||
if (nl.getLength() == 1) {
|
||||
communityService.setMetadataSingleValue(context, community,
|
||||
entry.getValue(), null, getStringValue(nl.item(0)));
|
||||
@@ -658,6 +703,7 @@ public class StructBuilder {
|
||||
// but it's here to keep it separate from the create process in
|
||||
// case
|
||||
// we want to move it or make it switchable later
|
||||
Element element = new Element("community");
|
||||
element.setAttribute("identifier", community.getHandle());
|
||||
|
||||
Element nameElement = new Element("name");
|
||||
@@ -700,12 +746,16 @@ public class StructBuilder {
|
||||
}
|
||||
|
||||
// handle sub communities
|
||||
NodeList subCommunities = XPathAPI.selectNodeList(tn, "community");
|
||||
Element[] subCommunityElements = handleCommunities(context, subCommunities, community);
|
||||
NodeList subCommunities = (NodeList) xPath.compile("community")
|
||||
.evaluate(tn, XPathConstants.NODESET);
|
||||
Element[] subCommunityElements = handleCommunities(context,
|
||||
subCommunities, community, keepHandles);
|
||||
|
||||
// handle collections
|
||||
NodeList collections = XPathAPI.selectNodeList(tn, "collection");
|
||||
Element[] collectionElements = handleCollections(context, collections, community);
|
||||
NodeList collections = (NodeList) xPath.compile("collection")
|
||||
.evaluate(tn, XPathConstants.NODESET);
|
||||
Element[] collectionElements = handleCollections(context,
|
||||
collections, community, keepHandles);
|
||||
|
||||
int j;
|
||||
for (j = 0; j < subCommunityElements.length; j++) {
|
||||
@@ -730,22 +780,33 @@ public class StructBuilder {
|
||||
* @return an Element array containing additional information about the
|
||||
* created collections (e.g. the handle)
|
||||
*/
|
||||
private static Element[] handleCollections(Context context, NodeList collections, Community parent)
|
||||
throws TransformerException, SQLException, AuthorizeException {
|
||||
private static Element[] handleCollections(Context context,
|
||||
NodeList collections, Community parent, boolean keepHandles)
|
||||
throws SQLException, AuthorizeException, XPathExpressionException {
|
||||
Element[] elements = new Element[collections.getLength()];
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
for (int i = 0; i < collections.getLength(); i++) {
|
||||
Element element = new Element("collection");
|
||||
Collection collection = collectionService.create(context, parent);
|
||||
Node tn = collections.item(i);
|
||||
Node identifier = tn.getAttributes().getNamedItem("identifier");
|
||||
|
||||
// Create the Collection.
|
||||
Collection collection;
|
||||
if (null == identifier
|
||||
|| StringUtils.isBlank(identifier.getNodeValue())
|
||||
|| !keepHandles) {
|
||||
collection = collectionService.create(context, parent);
|
||||
} else {
|
||||
collection = collectionService.create(context, parent, identifier.getNodeValue());
|
||||
}
|
||||
|
||||
// default the short description to the empty string
|
||||
collectionService.setMetadataSingleValue(context, collection,
|
||||
MD_SHORT_DESCRIPTION, Item.ANY, " ");
|
||||
|
||||
// import the rest of the metadata
|
||||
Node tn = collections.item(i);
|
||||
for (Map.Entry<String, MetadataFieldName> entry : collectionMap.entrySet()) {
|
||||
NodeList nl = XPathAPI.selectNodeList(tn, entry.getKey());
|
||||
NodeList nl = (NodeList) xPath.compile(entry.getKey()).evaluate(tn, XPathConstants.NODESET);
|
||||
if (nl.getLength() == 1) {
|
||||
collectionService.setMetadataSingleValue(context, collection,
|
||||
entry.getValue(), null, getStringValue(nl.item(0)));
|
||||
@@ -754,6 +815,7 @@ public class StructBuilder {
|
||||
|
||||
collectionService.update(context, collection);
|
||||
|
||||
Element element = new Element("collection");
|
||||
element.setAttribute("identifier", collection.getHandle());
|
||||
|
||||
Element nameElement = new Element("name");
|
||||
|
@@ -41,10 +41,8 @@ public class MetadataDeletionScriptConfiguration<T extends MetadataDeletion> ext
|
||||
Options options = new Options();
|
||||
|
||||
options.addOption("m", "metadata", true, "metadata field name");
|
||||
options.getOption("m").setType(String.class);
|
||||
|
||||
options.addOption("l", "list", false, "lists the metadata fields that can be deleted");
|
||||
options.getOption("l").setType(boolean.class);
|
||||
|
||||
super.options = options;
|
||||
}
|
||||
|
@@ -54,12 +54,9 @@ public class MetadataExportScriptConfiguration<T extends MetadataExport> extends
|
||||
Options options = new Options();
|
||||
|
||||
options.addOption("i", "id", true, "ID or handle of thing to export (item, collection, or community)");
|
||||
options.getOption("i").setType(String.class);
|
||||
options.addOption("a", "all", false,
|
||||
"include all metadata fields that are not normally changed (e.g. provenance)");
|
||||
options.getOption("a").setType(boolean.class);
|
||||
options.addOption("h", "help", false, "help");
|
||||
options.getOption("h").setType(boolean.class);
|
||||
|
||||
|
||||
super.options = options;
|
||||
|
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.app.bulkedit;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataDSpaceCsvExportServiceImpl;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.content.service.MetadataDSpaceCsvExportService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.SearchService;
|
||||
import org.dspace.discovery.SearchUtils;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationService;
|
||||
import org.dspace.discovery.indexobject.IndexableCollection;
|
||||
import org.dspace.discovery.indexobject.IndexableCommunity;
|
||||
import org.dspace.discovery.utils.DiscoverQueryBuilder;
|
||||
import org.dspace.discovery.utils.parameter.QueryBuilderSearchFilter;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.sort.SortOption;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
/**
|
||||
* Metadata exporter to allow the batch export of metadata from a discovery search into a file
|
||||
*
|
||||
*/
|
||||
public class MetadataExportSearch extends DSpaceRunnable<MetadataExportSearchScriptConfiguration> {
|
||||
private static final String EXPORT_CSV = "exportCSV";
|
||||
private boolean help = false;
|
||||
private String identifier;
|
||||
private String discoveryConfigName;
|
||||
private String[] filterQueryStrings;
|
||||
private boolean hasScope = false;
|
||||
private String query;
|
||||
|
||||
private SearchService searchService;
|
||||
private MetadataDSpaceCsvExportService metadataDSpaceCsvExportService;
|
||||
private EPersonService ePersonService;
|
||||
private DiscoveryConfigurationService discoveryConfigurationService;
|
||||
private CommunityService communityService;
|
||||
private CollectionService collectionService;
|
||||
private DiscoverQueryBuilder queryBuilder;
|
||||
|
||||
@Override
|
||||
public MetadataExportSearchScriptConfiguration getScriptConfiguration() {
|
||||
return new DSpace().getServiceManager()
|
||||
.getServiceByName("metadata-export-search", MetadataExportSearchScriptConfiguration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() throws ParseException {
|
||||
searchService = SearchUtils.getSearchService();
|
||||
metadataDSpaceCsvExportService = new DSpace().getServiceManager()
|
||||
.getServiceByName(
|
||||
MetadataDSpaceCsvExportServiceImpl.class.getCanonicalName(),
|
||||
MetadataDSpaceCsvExportService.class
|
||||
);
|
||||
ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||
discoveryConfigurationService = SearchUtils.getConfigurationService();
|
||||
communityService = ContentServiceFactory.getInstance().getCommunityService();
|
||||
collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||
queryBuilder = SearchUtils.getQueryBuilder();
|
||||
|
||||
if (commandLine.hasOption('h')) {
|
||||
help = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (commandLine.hasOption('q')) {
|
||||
query = commandLine.getOptionValue('q');
|
||||
}
|
||||
|
||||
if (commandLine.hasOption('s')) {
|
||||
hasScope = true;
|
||||
identifier = commandLine.getOptionValue('s');
|
||||
}
|
||||
|
||||
if (commandLine.hasOption('c')) {
|
||||
discoveryConfigName = commandLine.getOptionValue('c');
|
||||
}
|
||||
|
||||
if (commandLine.hasOption('f')) {
|
||||
filterQueryStrings = commandLine.getOptionValues('f');
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalRun() throws Exception {
|
||||
if (help) {
|
||||
loghelpinfo();
|
||||
printHelp();
|
||||
return;
|
||||
}
|
||||
handler.logDebug("starting search export");
|
||||
|
||||
IndexableObject dso = null;
|
||||
Context context = new Context();
|
||||
context.setCurrentUser(ePersonService.find(context, this.getEpersonIdentifier()));
|
||||
|
||||
if (hasScope) {
|
||||
dso = resolveScope(context, identifier);
|
||||
}
|
||||
|
||||
DiscoveryConfiguration discoveryConfiguration =
|
||||
discoveryConfigurationService.getDiscoveryConfiguration(discoveryConfigName);
|
||||
|
||||
List<QueryBuilderSearchFilter> queryBuilderSearchFilters = new ArrayList<>();
|
||||
|
||||
handler.logDebug("processing filter queries");
|
||||
if (filterQueryStrings != null) {
|
||||
for (String filterQueryString: filterQueryStrings) {
|
||||
String field = filterQueryString.split(",", 2)[0];
|
||||
String operator = filterQueryString.split("(,|=)", 3)[1];
|
||||
String value = filterQueryString.split("=", 2)[1];
|
||||
QueryBuilderSearchFilter queryBuilderSearchFilter =
|
||||
new QueryBuilderSearchFilter(field, operator, value);
|
||||
queryBuilderSearchFilters.add(queryBuilderSearchFilter);
|
||||
}
|
||||
}
|
||||
handler.logDebug("building query");
|
||||
DiscoverQuery discoverQuery =
|
||||
queryBuilder.buildQuery(context, dso, discoveryConfiguration, query, queryBuilderSearchFilters,
|
||||
"Item", 10, Long.getLong("0"), null, SortOption.DESCENDING);
|
||||
handler.logDebug("creating iterator");
|
||||
|
||||
Iterator<Item> itemIterator = searchService.iteratorSearch(context, dso, discoverQuery);
|
||||
handler.logDebug("creating dspacecsv");
|
||||
DSpaceCSV dSpaceCSV = metadataDSpaceCsvExportService.export(context, itemIterator, true);
|
||||
handler.logDebug("writing to file " + getFileNameOrExportFile());
|
||||
handler.writeFilestream(context, getFileNameOrExportFile(), dSpaceCSV.getInputStream(), EXPORT_CSV);
|
||||
context.restoreAuthSystemState();
|
||||
context.complete();
|
||||
|
||||
}
|
||||
|
||||
protected void loghelpinfo() {
|
||||
handler.logInfo("metadata-export");
|
||||
}
|
||||
|
||||
protected String getFileNameOrExportFile() {
|
||||
return "metadataExportSearch.csv";
|
||||
}
|
||||
|
||||
public IndexableObject resolveScope(Context context, String id) throws SQLException {
|
||||
UUID uuid = UUID.fromString(id);
|
||||
IndexableObject scopeObj = new IndexableCommunity(communityService.find(context, uuid));
|
||||
if (scopeObj.getIndexedObject() == null) {
|
||||
scopeObj = new IndexableCollection(collectionService.find(context, uuid));
|
||||
}
|
||||
return scopeObj;
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.app.bulkedit;
|
||||
|
||||
/**
|
||||
* The cli version of the {@link MetadataExportSearch} script
|
||||
*/
|
||||
public class MetadataExportSearchCli extends MetadataExportSearch {
|
||||
|
||||
@Override
|
||||
protected String getFileNameOrExportFile() {
|
||||
return commandLine.getOptionValue('n');
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.app.bulkedit;
|
||||
|
||||
import org.apache.commons.cli.Options;
|
||||
|
||||
/**
|
||||
* This is the CLI version of the {@link MetadataExportSearchScriptConfiguration} class that handles the
|
||||
* configuration for the {@link MetadataExportSearchCli} script
|
||||
*/
|
||||
public class MetadataExportSearchCliScriptConfiguration
|
||||
extends MetadataExportSearchScriptConfiguration<MetadataExportSearchCli> {
|
||||
|
||||
@Override
|
||||
public Options getOptions() {
|
||||
Options options = super.getOptions();
|
||||
options.addOption("n", "filename", true, "the filename to export to");
|
||||
return super.getOptions();
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.app.bulkedit;
|
||||
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
|
||||
/**
|
||||
* The {@link ScriptConfiguration} for the {@link MetadataExportSearch} script
|
||||
*/
|
||||
public class MetadataExportSearchScriptConfiguration<T extends MetadataExportSearch> extends ScriptConfiguration<T> {
|
||||
|
||||
private Class<T> dspaceRunnableclass;
|
||||
|
||||
@Override
|
||||
public Class<T> getDspaceRunnableClass() {
|
||||
return dspaceRunnableclass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
|
||||
this.dspaceRunnableclass = dspaceRunnableClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowedToExecute(Context context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Options getOptions() {
|
||||
if (options == null) {
|
||||
Options options = new Options();
|
||||
options.addOption("q", "query", true,
|
||||
"The discovery search string to will be used to match records. Not URL encoded");
|
||||
options.getOption("q").setType(String.class);
|
||||
options.addOption("s", "scope", true,
|
||||
"UUID of a specific DSpace container (site, community or collection) to which the search has to be " +
|
||||
"limited");
|
||||
options.getOption("s").setType(String.class);
|
||||
options.addOption("c", "configuration", true,
|
||||
"The name of a Discovery configuration that should be used by this search");
|
||||
options.getOption("c").setType(String.class);
|
||||
options.addOption("f", "filter", true,
|
||||
"Advanced search filter that has to be used to filter the result set, with syntax `<:filter-name>," +
|
||||
"<:filter-operator>=<:filter-value>`. Not URL encoded. For example `author," +
|
||||
"authority=5df05073-3be7-410d-8166-e254369e4166` or `title,contains=sample text`");
|
||||
options.getOption("f").setType(String.class);
|
||||
options.addOption("h", "help", false, "help");
|
||||
|
||||
super.options = options;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
}
|
@@ -925,11 +925,10 @@ public class MetadataImport extends DSpaceRunnable<MetadataImportScriptConfigura
|
||||
rightItem = item;
|
||||
}
|
||||
|
||||
// Create the relationship
|
||||
int leftPlace = relationshipService.findNextLeftPlaceByLeftItem(c, leftItem);
|
||||
int rightPlace = relationshipService.findNextRightPlaceByRightItem(c, rightItem);
|
||||
Relationship persistedRelationship = relationshipService.create(c, leftItem, rightItem,
|
||||
foundRelationshipType, leftPlace, rightPlace);
|
||||
// Create the relationship, appending to the end
|
||||
Relationship persistedRelationship = relationshipService.create(
|
||||
c, leftItem, rightItem, foundRelationshipType, -1, -1
|
||||
);
|
||||
relationshipService.update(c, persistedRelationship);
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,6 @@ public class MetadataImportCliScriptConfiguration extends MetadataImportScriptCo
|
||||
public Options getOptions() {
|
||||
Options options = super.getOptions();
|
||||
options.addOption("e", "email", true, "email address or user id of user (required if adding new items)");
|
||||
options.getOption("e").setType(String.class);
|
||||
options.getOption("e").setRequired(true);
|
||||
super.options = options;
|
||||
return options;
|
||||
|
@@ -59,20 +59,14 @@ public class MetadataImportScriptConfiguration<T extends MetadataImport> extends
|
||||
options.getOption("f").setRequired(true);
|
||||
options.addOption("s", "silent", false,
|
||||
"silent operation - doesn't request confirmation of changes USE WITH CAUTION");
|
||||
options.getOption("s").setType(boolean.class);
|
||||
options.addOption("w", "workflow", false, "workflow - when adding new items, use collection workflow");
|
||||
options.getOption("w").setType(boolean.class);
|
||||
options.addOption("n", "notify", false,
|
||||
"notify - when adding new items using a workflow, send notification emails");
|
||||
options.getOption("n").setType(boolean.class);
|
||||
options.addOption("v", "validate-only", false,
|
||||
"validate - just validate the csv, don't run the import");
|
||||
options.getOption("v").setType(boolean.class);
|
||||
options.addOption("t", "template", false,
|
||||
"template - when adding new items, use the collection template (if it exists)");
|
||||
options.getOption("t").setType(boolean.class);
|
||||
options.addOption("h", "help", false, "help");
|
||||
options.getOption("h").setType(boolean.class);
|
||||
|
||||
super.options = options;
|
||||
}
|
||||
|
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.exception;
|
||||
|
||||
/**
|
||||
* This class provides an exception to be used when trying to save a resource
|
||||
* that already exists.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class ResourceAlreadyExistsException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Create a ResourceAlreadyExistsException with a message and the already
|
||||
* existing resource.
|
||||
*
|
||||
* @param message the error message
|
||||
*/
|
||||
public ResourceAlreadyExistsException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -43,22 +43,14 @@ public class HarvestScriptConfiguration<T extends Harvest> extends ScriptConfigu
|
||||
public Options getOptions() {
|
||||
Options options = new Options();
|
||||
options.addOption("p", "purge", false, "delete all items in the collection");
|
||||
options.getOption("p").setType(boolean.class);
|
||||
options.addOption("r", "run", false, "run the standard harvest procedure");
|
||||
options.getOption("r").setType(boolean.class);
|
||||
options.addOption("g", "ping", false, "test the OAI server and set");
|
||||
options.getOption("g").setType(boolean.class);
|
||||
options.addOption("s", "setup", false, "Set the collection up for harvesting");
|
||||
options.getOption("s").setType(boolean.class);
|
||||
options.addOption("S", "start", false, "start the harvest loop");
|
||||
options.getOption("S").setType(boolean.class);
|
||||
options.addOption("R", "reset", false, "reset harvest status on all collections");
|
||||
options.getOption("R").setType(boolean.class);
|
||||
options.addOption("P", "purgeCollections", false, "purge all harvestable collections");
|
||||
options.getOption("P").setType(boolean.class);
|
||||
options.addOption("o", "reimport", false, "reimport all items in the collection, " +
|
||||
"this is equivalent to -p -r, purging all items in a collection and reimporting them");
|
||||
options.getOption("o").setType(boolean.class);
|
||||
options.addOption("c", "collection", true,
|
||||
"harvesting collection (handle or id)");
|
||||
options.addOption("t", "type", true,
|
||||
@@ -72,7 +64,6 @@ public class HarvestScriptConfiguration<T extends Harvest> extends ScriptConfigu
|
||||
"crosswalk in dspace.cfg");
|
||||
|
||||
options.addOption("h", "help", false, "help");
|
||||
options.getOption("h").setType(boolean.class);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
@@ -204,7 +204,7 @@ public class ItemExportCLITool {
|
||||
|| (mycollection.getType() != Constants.COLLECTION)) {
|
||||
mycollection = null;
|
||||
}
|
||||
} else if (myIDString != null) {
|
||||
} else {
|
||||
mycollection = collectionService.find(c, UUID.fromString(myIDString));
|
||||
}
|
||||
|
||||
|
@@ -64,17 +64,21 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
* Item exporter to create simple AIPs for DSpace content. Currently exports
|
||||
* individual items, or entire collections. For instructions on use, see
|
||||
* printUsage() method.
|
||||
* <P>
|
||||
* <p>
|
||||
* ItemExport creates the simple AIP package that the importer also uses. It
|
||||
* consists of:
|
||||
* <P>
|
||||
* /exportdir/42/ (one directory per item) / dublin_core.xml - qualified dublin
|
||||
* core in RDF schema / contents - text file, listing one file per line / file1
|
||||
* - files contained in the item / file2 / ...
|
||||
* <P>
|
||||
* <pre>{@code
|
||||
* /exportdir/42/ (one directory per item)
|
||||
* / dublin_core.xml - qualified dublin core in RDF schema
|
||||
* / contents - text file, listing one file per line
|
||||
* / file1 - files contained in the item
|
||||
* / file2
|
||||
* / ...
|
||||
* }</pre>
|
||||
* <p>
|
||||
* issues -doesn't handle special characters in metadata (needs to turn {@code &'s} into
|
||||
* {@code &}, etc.)
|
||||
* <P>
|
||||
* <p>
|
||||
* Modified by David Little, UCSD Libraries 12/21/04 to allow the registration
|
||||
* of files (bitstreams) into DSpace.
|
||||
*
|
||||
@@ -101,7 +105,7 @@ public class ItemExportServiceImpl implements ItemExportService {
|
||||
/**
|
||||
* log4j logger
|
||||
*/
|
||||
private final Logger log = org.apache.logging.log4j.LogManager.getLogger(ItemExportServiceImpl.class);
|
||||
private final Logger log = org.apache.logging.log4j.LogManager.getLogger();
|
||||
|
||||
protected ItemExportServiceImpl() {
|
||||
|
||||
@@ -168,6 +172,7 @@ public class ItemExportServiceImpl implements ItemExportService {
|
||||
// make it this far, now start exporting
|
||||
writeMetadata(c, myItem, itemDir, migrate);
|
||||
writeBitstreams(c, myItem, itemDir, excludeBitstreams);
|
||||
writeCollections(myItem, itemDir);
|
||||
if (!migrate) {
|
||||
writeHandle(c, myItem, itemDir);
|
||||
}
|
||||
@@ -343,6 +348,33 @@ public class ItemExportServiceImpl implements ItemExportService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the 'collections' file. List handles of all Collections which
|
||||
* contain this Item. The "owning" Collection is listed first.
|
||||
*
|
||||
* @param item list collections holding this Item.
|
||||
* @param destDir write the file here.
|
||||
* @throws IOException if the file cannot be created or written.
|
||||
*/
|
||||
protected void writeCollections(Item item, File destDir)
|
||||
throws IOException {
|
||||
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);
|
||||
for (Collection collection : item.getCollections()) {
|
||||
String collectionHandle = collection.getHandle();
|
||||
if (!collectionHandle.equals(ownerHandle)) {
|
||||
out.println(collectionHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IOException("Cannot create 'collections' in " + destDir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create both the bitstreams and the contents file. Any bitstreams that
|
||||
* were originally registered will be marked in the contents file as such.
|
||||
@@ -630,11 +662,9 @@ public class ItemExportServiceImpl implements ItemExportService {
|
||||
Thread go = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
Context context = null;
|
||||
Context context = new Context();
|
||||
Iterator<Item> iitems = null;
|
||||
try {
|
||||
// create a new dspace context
|
||||
context = new Context();
|
||||
// ignore auths
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
|
@@ -51,6 +51,10 @@ import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.commons.collections4.ComparatorUtils;
|
||||
import org.apache.commons.io.FileDeleteStrategy;
|
||||
@@ -59,7 +63,6 @@ import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.xpath.XPathAPI;
|
||||
import org.dspace.app.itemimport.service.ItemImportService;
|
||||
import org.dspace.app.util.LocalSchemaFilenameFilter;
|
||||
import org.dspace.app.util.RelationshipUtils;
|
||||
@@ -261,16 +264,12 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
// sneaky isResume == true means open file in append mode
|
||||
outFile = new File(mapFile);
|
||||
mapOut = new PrintWriter(new FileWriter(outFile, isResume));
|
||||
|
||||
if (mapOut == null) {
|
||||
throw new Exception("can't open mapfile: " + mapFile);
|
||||
}
|
||||
}
|
||||
|
||||
// open and process the source directory
|
||||
File d = new java.io.File(sourceDir);
|
||||
|
||||
if (d == null || !d.isDirectory()) {
|
||||
if (!d.isDirectory()) {
|
||||
throw new Exception("Error, cannot open source directory " + sourceDir);
|
||||
}
|
||||
|
||||
@@ -400,10 +399,8 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
}
|
||||
|
||||
// Create the relationship
|
||||
int leftPlace = relationshipService.findNextLeftPlaceByLeftItem(c, leftItem);
|
||||
int rightPlace = relationshipService.findNextRightPlaceByRightItem(c, rightItem);
|
||||
Relationship persistedRelationship = relationshipService.create(
|
||||
c, leftItem, rightItem, foundRelationshipType, leftPlace, rightPlace);
|
||||
Relationship persistedRelationship =
|
||||
relationshipService.create(c, leftItem, rightItem, foundRelationshipType, -1, -1);
|
||||
// relationshipService.update(c, persistedRelationship);
|
||||
|
||||
System.out.println("\tAdded relationship (type: " + relationshipType + ") from " +
|
||||
@@ -432,12 +429,16 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
/**
|
||||
* Read the relationship manifest file.
|
||||
*
|
||||
* Each line in the file contains a relationship type id and an item identifier in the following format:
|
||||
*
|
||||
* relation.<relation_key> <handle|uuid|folderName:import_item_folder|schema.element[.qualifier]:value>
|
||||
*
|
||||
* The input_item_folder should refer the folder name of another item in this import batch.
|
||||
*
|
||||
* Each line in the file contains a relationship type id and an item
|
||||
* identifier in the following format:
|
||||
*
|
||||
* <p>
|
||||
* {@code relation.<relation_key> <handle|uuid|folderName:import_item_folder|schema.element[.qualifier]:value>}
|
||||
*
|
||||
* <p>
|
||||
* The {@code input_item_folder} should refer the folder name of another
|
||||
* item in this import batch.
|
||||
*
|
||||
* @param path The main import folder path.
|
||||
* @param filename The name of the manifest file to check ('relationships')
|
||||
* @return Map of found relationships
|
||||
@@ -557,9 +558,10 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
/**
|
||||
* Lookup an item by a (unique) meta value.
|
||||
*
|
||||
* @param metaKey
|
||||
* @param metaValue
|
||||
* @return Item
|
||||
* @param c current DSpace session.
|
||||
* @param metaKey name of the metadata field to match.
|
||||
* @param metaValue value to be matched.
|
||||
* @return the matching Item.
|
||||
* @throws Exception if single item not found.
|
||||
*/
|
||||
protected Item findItemByMetaValue(Context c, String metaKey, String metaValue) throws Exception {
|
||||
@@ -603,7 +605,7 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
// verify the source directory
|
||||
File d = new java.io.File(sourceDir);
|
||||
|
||||
if (d == null || !d.isDirectory()) {
|
||||
if (!d.isDirectory()) {
|
||||
throw new Exception("Error, cannot open source directory "
|
||||
+ sourceDir);
|
||||
}
|
||||
@@ -642,10 +644,6 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
File handleFile = new File(sourceDir + File.separatorChar + newItemName + File.separatorChar + "handle");
|
||||
PrintWriter handleOut = new PrintWriter(new FileWriter(handleFile, true));
|
||||
|
||||
if (handleOut == null) {
|
||||
throw new Exception("can't open handle file: " + handleFile.getCanonicalPath());
|
||||
}
|
||||
|
||||
handleOut.println(oldHandle);
|
||||
handleOut.close();
|
||||
|
||||
@@ -863,7 +861,7 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
// Load all metadata schemas into the item.
|
||||
protected void loadMetadata(Context c, Item myitem, String path)
|
||||
throws SQLException, IOException, ParserConfigurationException,
|
||||
SAXException, TransformerException, AuthorizeException {
|
||||
SAXException, TransformerException, AuthorizeException, XPathExpressionException {
|
||||
// Load the dublin core metadata
|
||||
loadDublinCore(c, myitem, path + "dublin_core.xml");
|
||||
|
||||
@@ -877,14 +875,15 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
|
||||
protected void loadDublinCore(Context c, Item myitem, String filename)
|
||||
throws SQLException, IOException, ParserConfigurationException,
|
||||
SAXException, TransformerException, AuthorizeException {
|
||||
SAXException, TransformerException, AuthorizeException, XPathExpressionException {
|
||||
Document document = loadXML(filename);
|
||||
|
||||
// Get the schema, for backward compatibility we will default to the
|
||||
// dublin core schema if the schema name is not available in the import
|
||||
// file
|
||||
String schema;
|
||||
NodeList metadata = XPathAPI.selectNodeList(document, "/dublin_core");
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
NodeList metadata = (NodeList) xPath.compile("/dublin_core").evaluate(document, XPathConstants.NODESET);
|
||||
Node schemaAttr = metadata.item(0).getAttributes().getNamedItem(
|
||||
"schema");
|
||||
if (schemaAttr == null) {
|
||||
@@ -894,8 +893,7 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
}
|
||||
|
||||
// Get the nodes corresponding to formats
|
||||
NodeList dcNodes = XPathAPI.selectNodeList(document,
|
||||
"/dublin_core/dcvalue");
|
||||
NodeList dcNodes = (NodeList) xPath.compile("/dublin_core/dcvalue").evaluate(document, XPathConstants.NODESET);
|
||||
|
||||
if (!isQuiet) {
|
||||
System.out.println("\tLoading dublin core from " + filename);
|
||||
@@ -1667,26 +1665,27 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
.trim();
|
||||
}
|
||||
|
||||
if (isTest) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Bitstream bs = null;
|
||||
boolean notfound = true;
|
||||
boolean updateRequired = false;
|
||||
|
||||
if (!isTest) {
|
||||
// find bitstream
|
||||
List<Bitstream> bitstreams = itemService.getNonInternalBitstreams(c, myItem);
|
||||
for (int j = 0; j < bitstreams.size() && notfound; j++) {
|
||||
if (bitstreams.get(j).getName().equals(bitstreamName)) {
|
||||
bs = bitstreams.get(j);
|
||||
notfound = false;
|
||||
}
|
||||
// find bitstream
|
||||
List<Bitstream> bitstreams = itemService.getNonInternalBitstreams(c, myItem);
|
||||
for (Bitstream bitstream : bitstreams) {
|
||||
if (bitstream.getName().equals(bitstreamName)) {
|
||||
bs = bitstream;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (notfound && !isTest) {
|
||||
if (null == bs) {
|
||||
// this should never happen
|
||||
System.out.println("\tdefault permissions set for "
|
||||
+ bitstreamName);
|
||||
} else if (!isTest) {
|
||||
System.out.printf("\tdefault permissions set for %s%n",
|
||||
bitstreamName);
|
||||
} else {
|
||||
if (permissionsExist) {
|
||||
if (myGroup == null) {
|
||||
System.out.println("\t" + groupName
|
||||
@@ -2027,15 +2026,11 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
Thread go = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
Context context = null;
|
||||
|
||||
Context context = new Context();
|
||||
String importDir = null;
|
||||
EPerson eperson = null;
|
||||
|
||||
try {
|
||||
|
||||
// create a new dspace context
|
||||
context = new Context();
|
||||
eperson = ePersonService.find(context, oldEPerson.getID());
|
||||
context.setCurrentUser(eperson);
|
||||
context.turnOffAuthorisationSystem();
|
||||
@@ -2046,7 +2041,8 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
if (theOtherCollections != null) {
|
||||
for (String colID : theOtherCollections) {
|
||||
UUID colId = UUID.fromString(colID);
|
||||
if (!theOwningCollection.getID().equals(colId)) {
|
||||
if (theOwningCollection != null
|
||||
&& !theOwningCollection.getID().equals(colId)) {
|
||||
Collection col = collectionService.find(context, colId);
|
||||
if (col != null) {
|
||||
collectionList.add(col);
|
||||
|
@@ -77,7 +77,7 @@ public class AddBitstreamsAction extends UpdateBitstreamsAction {
|
||||
ItemUpdate.pr("Contents bitstream count: " + contents.size());
|
||||
|
||||
String[] files = dir.list(ItemUpdate.fileFilter);
|
||||
List<String> fileList = new ArrayList<String>();
|
||||
List<String> fileList = new ArrayList<>();
|
||||
for (String filename : files) {
|
||||
fileList.add(filename);
|
||||
ItemUpdate.pr("file: " + filename);
|
||||
@@ -134,9 +134,6 @@ public class AddBitstreamsAction extends UpdateBitstreamsAction {
|
||||
ItemUpdate.pr("contents entry for bitstream: " + ce.toString());
|
||||
File f = new File(dir, ce.filename);
|
||||
|
||||
// get an input stream
|
||||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
|
||||
|
||||
Bitstream bs = null;
|
||||
String newBundleName = ce.bundlename;
|
||||
|
||||
@@ -173,7 +170,9 @@ public class AddBitstreamsAction extends UpdateBitstreamsAction {
|
||||
targetBundle = bundles.iterator().next();
|
||||
}
|
||||
|
||||
bs = bitstreamService.create(context, targetBundle, bis);
|
||||
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));) {
|
||||
bs = bitstreamService.create(context, targetBundle, bis);
|
||||
}
|
||||
bs.setName(context, ce.filename);
|
||||
|
||||
// Identify the format
|
||||
|
@@ -39,29 +39,34 @@ import org.dspace.handle.factory.HandleServiceFactory;
|
||||
import org.dspace.handle.service.HandleService;
|
||||
|
||||
/**
|
||||
* Provides some batch editing capabilities for items in DSpace:
|
||||
* Metadata fields - Add, Delete
|
||||
* Bitstreams - Add, Delete
|
||||
* Provides some batch editing capabilities for items in DSpace.
|
||||
* <ul>
|
||||
* <li>Metadata fields - Add, Delete</li>
|
||||
* <li>Bitstreams - Add, Delete</li>
|
||||
* </ul>
|
||||
*
|
||||
* The design has been for compatibility with ItemImporter
|
||||
* <p>
|
||||
* The design has been for compatibility with
|
||||
* {@link org.dspace.app.itemimport.service.ItemImportService}
|
||||
* in the use of the DSpace archive format which is used to
|
||||
* specify changes on a per item basis. The directory names
|
||||
* to correspond to each item are arbitrary and will only be
|
||||
* used for logging purposes. The reference to the item is
|
||||
* from a required dc.identifier with the item handle to be
|
||||
* included in the dublin_core.xml (or similar metadata) file.
|
||||
* from a required {@code dc.identifier} with the item handle to be
|
||||
* included in the {@code dublin_core.xml} (or similar metadata) file.
|
||||
*
|
||||
* Any combination of these actions is permitted in a single run of this class
|
||||
* <p>
|
||||
* Any combination of these actions is permitted in a single run of this class.
|
||||
* The order of actions is important when used in combination.
|
||||
* It is the responsibility of the calling class (here, ItemUpdate)
|
||||
* to register UpdateAction classes in the order to which they are
|
||||
* It is the responsibility of the calling class (here, {@code ItemUpdate})
|
||||
* to register {@link UpdateAction} classes in the order which they are
|
||||
* to be performed.
|
||||
*
|
||||
*
|
||||
* It is unfortunate that so much code needs to be borrowed
|
||||
* from ItemImport as it is not reusable in private methods, etc.
|
||||
* Some of this has been placed into the MetadataUtilities class
|
||||
* for possible reuse elsewhere.
|
||||
* <p>
|
||||
* It is unfortunate that so much code needs to be borrowed from
|
||||
* {@link org.dspace.app.itemimport.service.ItemImportService} as it is not
|
||||
* reusable in private methods, etc. Some of this has been placed into the
|
||||
* {@link MetadataUtilities} class for possible reuse elsewhere.
|
||||
*
|
||||
* @author W. Hays based on a conceptual design by R. Rodgers
|
||||
*/
|
||||
@@ -73,7 +78,7 @@ public class ItemUpdate {
|
||||
public static final String DELETE_CONTENTS_FILE = "delete_contents";
|
||||
|
||||
public static String HANDLE_PREFIX = null;
|
||||
public static final Map<String, String> filterAliases = new HashMap<String, String>();
|
||||
public static final Map<String, String> filterAliases = new HashMap<>();
|
||||
|
||||
public static boolean verbose = false;
|
||||
|
||||
@@ -375,7 +380,7 @@ public class ItemUpdate {
|
||||
// open and process the source directory
|
||||
File sourceDir = new File(sourceDirPath);
|
||||
|
||||
if ((sourceDir == null) || !sourceDir.exists() || !sourceDir.isDirectory()) {
|
||||
if (!sourceDir.exists() || !sourceDir.isDirectory()) {
|
||||
pr("Error, cannot open archive source directory " + sourceDirPath);
|
||||
throw new Exception("error with archive source directory " + sourceDirPath);
|
||||
}
|
||||
|
@@ -27,10 +27,12 @@ import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.xpath.XPathAPI;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataField;
|
||||
import org.dspace.content.MetadataSchema;
|
||||
@@ -170,24 +172,21 @@ public class MetadataUtilities {
|
||||
* @param docBuilder DocumentBuilder
|
||||
* @param is - InputStream of dublin_core.xml
|
||||
* @return list of DtoMetadata representing the metadata fields relating to an Item
|
||||
* @throws SQLException if database error
|
||||
* @throws IOException if IO error
|
||||
* @throws ParserConfigurationException if parser config error
|
||||
* @throws SAXException if XML error
|
||||
* @throws TransformerException if transformer error
|
||||
* @throws AuthorizeException if authorization error
|
||||
*/
|
||||
public static List<DtoMetadata> loadDublinCore(DocumentBuilder docBuilder, InputStream is)
|
||||
throws SQLException, IOException, ParserConfigurationException,
|
||||
SAXException, TransformerException, AuthorizeException {
|
||||
throws IOException, XPathExpressionException, SAXException {
|
||||
Document document = docBuilder.parse(is);
|
||||
|
||||
List<DtoMetadata> dtomList = new ArrayList<DtoMetadata>();
|
||||
|
||||
// Get the schema, for backward compatibility we will default to the
|
||||
// dublin core schema if the schema name is not available in the import file
|
||||
String schema = null;
|
||||
NodeList metadata = XPathAPI.selectNodeList(document, "/dublin_core");
|
||||
String schema;
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
NodeList metadata = (NodeList) xPath.compile("/dublin_core").evaluate(document, XPathConstants.NODESET);
|
||||
Node schemaAttr = metadata.item(0).getAttributes().getNamedItem("schema");
|
||||
if (schemaAttr == null) {
|
||||
schema = MetadataSchemaEnum.DC.getName();
|
||||
@@ -196,7 +195,7 @@ public class MetadataUtilities {
|
||||
}
|
||||
|
||||
// Get the nodes corresponding to formats
|
||||
NodeList dcNodes = XPathAPI.selectNodeList(document, "/dublin_core/dcvalue");
|
||||
NodeList dcNodes = (NodeList) xPath.compile("/dublin_core/dcvalue").evaluate(document, XPathConstants.NODESET);
|
||||
|
||||
for (int i = 0; i < dcNodes.getLength(); i++) {
|
||||
Node n = dcNodes.item(i);
|
||||
|
@@ -16,7 +16,7 @@ import java.io.StreamTokenizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jdom.Document;
|
||||
import org.jdom2.Document;
|
||||
|
||||
/**
|
||||
* @author mwood
|
||||
|
@@ -29,9 +29,9 @@ import org.dspace.scripts.service.ScriptService;
|
||||
import org.dspace.servicemanager.DSpaceKernelImpl;
|
||||
import org.dspace.servicemanager.DSpaceKernelInit;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.input.SAXBuilder;
|
||||
import org.jdom2.Document;
|
||||
import org.jdom2.Element;
|
||||
import org.jdom2.input.SAXBuilder;
|
||||
|
||||
/**
|
||||
* A DSpace script launcher.
|
||||
|
@@ -21,10 +21,10 @@ import java.awt.image.BufferedImage;
|
||||
*/
|
||||
|
||||
public class Brand {
|
||||
private int brandWidth;
|
||||
private int brandHeight;
|
||||
private Font font;
|
||||
private int xOffset;
|
||||
private final int brandWidth;
|
||||
private final int brandHeight;
|
||||
private final Font font;
|
||||
private final int xOffset;
|
||||
|
||||
/**
|
||||
* Constructor to set up footer image attributes.
|
||||
@@ -92,7 +92,7 @@ public class Brand {
|
||||
* do the text placements and preparatory work for the brand image generation
|
||||
*
|
||||
* @param brandImage a BufferedImage object where the image is created
|
||||
* @param identifier and Identifier object describing what text is to be placed in what
|
||||
* @param brandText an Identifier object describing what text is to be placed in what
|
||||
* position within the brand
|
||||
*/
|
||||
private void drawImage(BufferedImage brandImage,
|
||||
|
@@ -39,7 +39,7 @@ class BrandText {
|
||||
* its location within a rectangular area.
|
||||
*
|
||||
* @param location one of the class location constants e.g. <code>Identifier.BL</code>
|
||||
* @param the text associated with the location
|
||||
* @param text text associated with the location
|
||||
*/
|
||||
public BrandText(String location, String text) {
|
||||
this.location = location;
|
||||
|
@@ -1,99 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.poi.POITextExtractor;
|
||||
import org.apache.poi.extractor.ExtractorFactory;
|
||||
import org.apache.poi.hssf.extractor.ExcelExtractor;
|
||||
import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
|
||||
import org.dspace.content.Item;
|
||||
|
||||
/*
|
||||
* ExcelFilter
|
||||
*
|
||||
* Entries you must add to dspace.cfg:
|
||||
*
|
||||
* filter.plugins = blah, \
|
||||
* Excel Text Extractor
|
||||
*
|
||||
* plugin.named.org.dspace.app.mediafilter.FormatFilter = \
|
||||
* blah = blah, \
|
||||
* org.dspace.app.mediafilter.ExcelFilter = Excel Text Extractor
|
||||
*
|
||||
* #Configure each filter's input Formats
|
||||
* filter.org.dspace.app.mediafilter.ExcelFilter.inputFormats = Microsoft Excel, Microsoft Excel XML
|
||||
*
|
||||
*/
|
||||
public class ExcelFilter extends MediaFilter {
|
||||
|
||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(ExcelFilter.class);
|
||||
|
||||
public String getFilteredName(String oldFilename) {
|
||||
return oldFilename + ".txt";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String bundle name
|
||||
*/
|
||||
public String getBundleName() {
|
||||
return "TEXT";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String bitstream format
|
||||
*/
|
||||
public String getFormatString() {
|
||||
return "Text";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return "Extracted text";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param item item
|
||||
* @param source source input stream
|
||||
* @param verbose verbose mode
|
||||
* @return InputStream the resulting input stream
|
||||
* @throws Exception if error
|
||||
*/
|
||||
@Override
|
||||
public InputStream getDestinationStream(Item item, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
String extractedText = null;
|
||||
|
||||
try {
|
||||
POITextExtractor theExtractor = ExtractorFactory.createExtractor(source);
|
||||
if (theExtractor instanceof ExcelExtractor) {
|
||||
// for xls file
|
||||
extractedText = (theExtractor).getText();
|
||||
} else if (theExtractor instanceof XSSFExcelExtractor) {
|
||||
// for xlsx file
|
||||
extractedText = (theExtractor).getText();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error filtering bitstream: " + e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (extractedText != null) {
|
||||
// generate an input stream with the extracted text
|
||||
return IOUtils.toInputStream(extractedText, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
|
||||
/*
|
||||
*
|
||||
* to do: helpful error messages - can't find mediafilter.cfg - can't
|
||||
* instantiate filter - bitstream format doesn't exist
|
||||
*
|
||||
*/
|
||||
public class HTMLFilter extends MediaFilter {
|
||||
|
||||
@Override
|
||||
public String getFilteredName(String oldFilename) {
|
||||
return oldFilename + ".txt";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String bundle name
|
||||
*/
|
||||
@Override
|
||||
public String getBundleName() {
|
||||
return "TEXT";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String bitstream format
|
||||
*/
|
||||
@Override
|
||||
public String getFormatString() {
|
||||
return "Text";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String description
|
||||
*/
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Extracted text";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param currentItem item
|
||||
* @param source source input stream
|
||||
* @param verbose verbose mode
|
||||
* @return InputStream the resulting input stream
|
||||
* @throws Exception if error
|
||||
*/
|
||||
@Override
|
||||
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
// try and read the document - set to ignore character set directive,
|
||||
// assuming that the input stream is already set properly (I hope)
|
||||
HTMLEditorKit kit = new HTMLEditorKit();
|
||||
Document doc = kit.createDefaultDocument();
|
||||
|
||||
doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
|
||||
|
||||
kit.read(source, doc, 0);
|
||||
|
||||
String extractedText = doc.getText(0, doc.getLength());
|
||||
|
||||
// generate an input stream with the extracted text
|
||||
byte[] textBytes = extractedText.getBytes(StandardCharsets.UTF_8);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(textBytes);
|
||||
|
||||
return bais;
|
||||
}
|
||||
}
|
@@ -50,15 +50,11 @@ public class MediaFilterScriptConfiguration<T extends MediaFilterScript> extends
|
||||
public Options getOptions() {
|
||||
Options options = new Options();
|
||||
options.addOption("v", "verbose", false, "print all extracted text and other details to STDOUT");
|
||||
options.getOption("v").setType(boolean.class);
|
||||
options.addOption("q", "quiet", false, "do not print anything except in the event of errors.");
|
||||
options.getOption("q").setType(boolean.class);
|
||||
options.addOption("f", "force", false, "force all bitstreams to be processed");
|
||||
options.getOption("f").setType(boolean.class);
|
||||
options.addOption("i", "identifier", true, "ONLY process bitstreams belonging to identifier");
|
||||
options.addOption("m", "maximum", true, "process no more than maximum items");
|
||||
options.addOption("h", "help", false, "help");
|
||||
options.getOption("h").setType(boolean.class);
|
||||
|
||||
Option pluginOption = Option.builder("p")
|
||||
.longOpt("plugins")
|
||||
|
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
/*
|
||||
*
|
||||
* to do: helpful error messages - can't find mediafilter.cfg - can't
|
||||
* instantiate filter - bitstream format doesn't exist
|
||||
*
|
||||
*/
|
||||
public class PDFFilter extends MediaFilter {
|
||||
|
||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(PDFFilter.class);
|
||||
|
||||
@Override
|
||||
public String getFilteredName(String oldFilename) {
|
||||
return oldFilename + ".txt";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String bundle name
|
||||
*/
|
||||
@Override
|
||||
public String getBundleName() {
|
||||
return "TEXT";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String bitstreamformat
|
||||
*/
|
||||
@Override
|
||||
public String getFormatString() {
|
||||
return "Text";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String description
|
||||
*/
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Extracted text";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param currentItem item
|
||||
* @param source source input stream
|
||||
* @param verbose verbose mode
|
||||
* @return InputStream the resulting input stream
|
||||
* @throws Exception if error
|
||||
*/
|
||||
@Override
|
||||
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
try {
|
||||
boolean useTemporaryFile = configurationService.getBooleanProperty("pdffilter.largepdfs", false);
|
||||
|
||||
// get input stream from bitstream
|
||||
// pass to filter, get string back
|
||||
PDFTextStripper pts = new PDFTextStripper();
|
||||
pts.setSortByPosition(true);
|
||||
PDDocument pdfDoc = null;
|
||||
Writer writer = null;
|
||||
File tempTextFile = null;
|
||||
ByteArrayOutputStream byteStream = null;
|
||||
|
||||
if (useTemporaryFile) {
|
||||
tempTextFile = File.createTempFile("dspacepdfextract" + source.hashCode(), ".txt");
|
||||
tempTextFile.deleteOnExit();
|
||||
writer = new OutputStreamWriter(new FileOutputStream(tempTextFile));
|
||||
} else {
|
||||
byteStream = new ByteArrayOutputStream();
|
||||
writer = new OutputStreamWriter(byteStream);
|
||||
}
|
||||
|
||||
try {
|
||||
pdfDoc = PDDocument.load(source);
|
||||
pts.writeText(pdfDoc, writer);
|
||||
} catch (InvalidPasswordException ex) {
|
||||
log.error("PDF is encrypted. Cannot extract text (item: {})",
|
||||
() -> currentItem.getHandle());
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
if (pdfDoc != null) {
|
||||
pdfDoc.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error closing PDF file: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
writer.close();
|
||||
} catch (Exception e) {
|
||||
log.error("Error closing temporary extract file: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (useTemporaryFile) {
|
||||
return new FileInputStream(tempTextFile);
|
||||
} else {
|
||||
byte[] bytes = byteStream.toByteArray();
|
||||
return new ByteArrayInputStream(bytes);
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
log.error("Error parsing PDF document " + oome.getMessage(), oome);
|
||||
if (!configurationService.getBooleanProperty("pdffilter.skiponmemoryexception", false)) {
|
||||
throw oome;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.poi.POITextExtractor;
|
||||
import org.apache.poi.extractor.ExtractorFactory;
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.dspace.content.Item;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Extract flat text from Microsoft Word documents (.doc, .docx).
|
||||
*/
|
||||
public class PoiWordFilter
|
||||
extends MediaFilter {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PoiWordFilter.class);
|
||||
|
||||
@Override
|
||||
public String getFilteredName(String oldFilename) {
|
||||
return oldFilename + ".txt";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBundleName() {
|
||||
return "TEXT";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormatString() {
|
||||
return "Text";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Extracted text";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
String text;
|
||||
try {
|
||||
// get input stream from bitstream, pass to filter, get string back
|
||||
POITextExtractor extractor = ExtractorFactory.createExtractor(source);
|
||||
text = extractor.getText();
|
||||
} catch (IOException | OpenXML4JException | XmlException e) {
|
||||
System.err.format("Invalid File Format: %s%n", e.getMessage());
|
||||
LOG.error("Unable to parse the bitstream: ", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
// if verbose flag is set, print out extracted text to STDOUT
|
||||
if (verbose) {
|
||||
System.out.println(text);
|
||||
}
|
||||
|
||||
// return the extracted text as a stream.
|
||||
return new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
@@ -1,113 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.poi.POITextExtractor;
|
||||
import org.apache.poi.extractor.ExtractorFactory;
|
||||
import org.apache.poi.hslf.extractor.PowerPointExtractor;
|
||||
import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor;
|
||||
import org.dspace.content.Item;
|
||||
|
||||
/*
|
||||
* TODO: Allow user to configure extraction of only text or only notes
|
||||
*
|
||||
*/
|
||||
public class PowerPointFilter extends MediaFilter {
|
||||
|
||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(PowerPointFilter.class);
|
||||
|
||||
@Override
|
||||
public String getFilteredName(String oldFilename) {
|
||||
return oldFilename + ".txt";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String bundle name
|
||||
*/
|
||||
@Override
|
||||
public String getBundleName() {
|
||||
return "TEXT";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String bitstream format
|
||||
*
|
||||
* TODO: Check that this is correct
|
||||
*/
|
||||
@Override
|
||||
public String getFormatString() {
|
||||
return "Text";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String description
|
||||
*/
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Extracted text";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param currentItem item
|
||||
* @param source source input stream
|
||||
* @param verbose verbose mode
|
||||
* @return InputStream the resulting input stream
|
||||
* @throws Exception if error
|
||||
*/
|
||||
@Override
|
||||
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
|
||||
try {
|
||||
|
||||
String extractedText = null;
|
||||
new ExtractorFactory();
|
||||
POITextExtractor pptExtractor = ExtractorFactory
|
||||
.createExtractor(source);
|
||||
|
||||
// PowerPoint XML files and legacy format PowerPoint files
|
||||
// require different classes and APIs for text extraction
|
||||
|
||||
// If this is a PowerPoint XML file, extract accordingly
|
||||
if (pptExtractor instanceof XSLFPowerPointExtractor) {
|
||||
|
||||
// The true method arguments indicate that text from
|
||||
// the slides and the notes is desired
|
||||
extractedText = ((XSLFPowerPointExtractor) pptExtractor)
|
||||
.getText(true, true);
|
||||
} else if (pptExtractor instanceof PowerPointExtractor) { // Legacy PowerPoint files
|
||||
|
||||
extractedText = ((PowerPointExtractor) pptExtractor).getText()
|
||||
+ " " + ((PowerPointExtractor) pptExtractor).getNotes();
|
||||
|
||||
}
|
||||
if (extractedText != null) {
|
||||
// if verbose flag is set, print out extracted text
|
||||
// to STDOUT
|
||||
if (verbose) {
|
||||
System.out.println(extractedText);
|
||||
}
|
||||
|
||||
// generate an input stream with the extracted text
|
||||
byte[] textBytes = extractedText.getBytes();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(textBytes);
|
||||
|
||||
return bais;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error filtering bitstream: " + e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.tika.Tika;
|
||||
import org.apache.tika.exception.TikaException;
|
||||
import org.apache.tika.metadata.Metadata;
|
||||
import org.apache.tika.parser.AutoDetectParser;
|
||||
import org.apache.tika.sax.BodyContentHandler;
|
||||
import org.apache.tika.sax.ContentHandlerDecorator;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Text Extraction media filter which uses Apache Tika to extract text from a large number of file formats (including
|
||||
* all Microsoft formats, PDF, HTML, Text, etc). For a more complete list of file formats supported by Tika see the
|
||||
* Tika documentation: https://tika.apache.org/2.3.0/formats.html
|
||||
*/
|
||||
public class TikaTextExtractionFilter
|
||||
extends MediaFilter {
|
||||
private final static Logger log = LogManager.getLogger();
|
||||
|
||||
@Override
|
||||
public String getFilteredName(String oldFilename) {
|
||||
return oldFilename + ".txt";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBundleName() {
|
||||
return "TEXT";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormatString() {
|
||||
return "Text";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Extracted text";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
boolean useTemporaryFile = configurationService.getBooleanProperty("textextractor.use-temp-file", false);
|
||||
|
||||
if (useTemporaryFile) {
|
||||
// Extract text out of source file using a temp file, returning results as InputStream
|
||||
return extractUsingTempFile(source, verbose);
|
||||
}
|
||||
|
||||
// Not using temporary file. We'll use Tika's default in-memory parsing.
|
||||
// Get maximum characters to extract. Default is 100,000 chars, which is also Tika's default setting.
|
||||
String extractedText;
|
||||
int maxChars = configurationService.getIntProperty("textextractor.max-chars", 100000);
|
||||
try {
|
||||
// Use Tika to extract text from input. Tika will automatically detect the file type.
|
||||
Tika tika = new Tika();
|
||||
tika.setMaxStringLength(maxChars); // Tell Tika the maximum number of characters to extract
|
||||
extractedText = tika.parseToString(source);
|
||||
} catch (IOException e) {
|
||||
System.err.format("Unable to extract text from bitstream in Item %s%n", currentItem.getID().toString());
|
||||
e.printStackTrace();
|
||||
log.error("Unable to extract text from bitstream in Item {}", currentItem.getID().toString(), e);
|
||||
throw e;
|
||||
} catch (OutOfMemoryError oe) {
|
||||
System.err.format("OutOfMemoryError occurred when extracting text from bitstream in Item %s. " +
|
||||
"You may wish to enable 'textextractor.use-temp-file'.%n", currentItem.getID().toString());
|
||||
oe.printStackTrace();
|
||||
log.error("OutOfMemoryError occurred when extracting text from bitstream in Item {}. " +
|
||||
"You may wish to enable 'textextractor.use-temp-file'.", currentItem.getID().toString(), oe);
|
||||
throw oe;
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(extractedText)) {
|
||||
// if verbose flag is set, print out extracted text to STDOUT
|
||||
if (verbose) {
|
||||
System.out.println("(Verbose mode) Extracted text:");
|
||||
System.out.println(extractedText);
|
||||
}
|
||||
|
||||
// return the extracted text as a UTF-8 stream.
|
||||
return new ByteArrayInputStream(extractedText.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the text out of a given source InputStream, using a temporary file. This decreases the amount of memory
|
||||
* necessary for text extraction, but can be slower as it requires writing extracted text to a temporary file.
|
||||
* @param source source InputStream
|
||||
* @param verbose verbose mode enabled/disabled
|
||||
* @return InputStream for temporary file containing extracted text
|
||||
* @throws IOException
|
||||
* @throws SAXException
|
||||
* @throws TikaException
|
||||
*/
|
||||
private InputStream extractUsingTempFile(InputStream source, boolean verbose)
|
||||
throws IOException, TikaException, SAXException {
|
||||
File tempExtractedTextFile = File.createTempFile("dspacetextextract" + source.hashCode(), ".txt");
|
||||
|
||||
if (verbose) {
|
||||
System.out.println("(Verbose mode) Extracted text was written to temporary file at " +
|
||||
tempExtractedTextFile.getAbsolutePath());
|
||||
} else {
|
||||
tempExtractedTextFile.deleteOnExit();
|
||||
}
|
||||
|
||||
// Open temp file for writing
|
||||
try (FileWriter writer = new FileWriter(tempExtractedTextFile, StandardCharsets.UTF_8)) {
|
||||
// Initialize a custom ContentHandlerDecorator which is a BodyContentHandler.
|
||||
// This mimics the behavior of Tika().parseToString(), which only extracts text from the body of the file.
|
||||
// This custom Handler writes any extracted text to the temp file.
|
||||
ContentHandlerDecorator handler = new BodyContentHandler(new ContentHandlerDecorator() {
|
||||
/**
|
||||
* Write all extracted characters directly to the temp file.
|
||||
*/
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
try {
|
||||
writer.append(new String(ch), start, length);
|
||||
} catch (IOException e) {
|
||||
String errorMsg = String.format("Could not append to temporary file at %s " +
|
||||
"when performing text extraction",
|
||||
tempExtractedTextFile.getAbsolutePath());
|
||||
log.error(errorMsg, e);
|
||||
throw new SAXException(errorMsg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all ignorable whitespace directly to the temp file.
|
||||
* This mimics the behaviour of Tika().parseToString() which extracts ignorableWhitespace characters
|
||||
* (like blank lines, indentations, etc.), so that we get the same extracted text either way.
|
||||
*/
|
||||
@Override
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
|
||||
try {
|
||||
writer.append(new String(ch), start, length);
|
||||
} catch (IOException e) {
|
||||
String errorMsg = String.format("Could not append to temporary file at %s " +
|
||||
"when performing text extraction",
|
||||
tempExtractedTextFile.getAbsolutePath());
|
||||
log.error(errorMsg, e);
|
||||
throw new SAXException(errorMsg, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AutoDetectParser parser = new AutoDetectParser();
|
||||
Metadata metadata = new Metadata();
|
||||
// parse our source InputStream using the above custom handler
|
||||
parser.parse(source, handler, metadata);
|
||||
}
|
||||
|
||||
// At this point, all extracted text is written to our temp file. So, return a FileInputStream for that file
|
||||
return new FileInputStream(tempExtractedTextFile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -631,7 +631,7 @@ public class Packager {
|
||||
//otherwise, just disseminate a single object to a single package file
|
||||
dip.disseminate(context, dso, pkgParams, pkgFile);
|
||||
|
||||
if (pkgFile != null && pkgFile.exists()) {
|
||||
if (pkgFile.exists()) {
|
||||
System.out.println("\nCREATED package file: " + pkgFile.getCanonicalPath());
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.app.requestitem;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* Derive request recipients from groups of the Collection which owns an Item.
|
||||
* The list will include all members of the administrators group. If the
|
||||
* resulting list is empty, delegates to {@link RequestItemHelpdeskStrategy}.
|
||||
*
|
||||
* @author Mark H. Wood <mwood@iupui.edu>
|
||||
*/
|
||||
public class CollectionAdministratorsRequestItemStrategy
|
||||
extends RequestItemHelpdeskStrategy {
|
||||
@Override
|
||||
@NonNull
|
||||
public List<RequestItemAuthor> getRequestItemAuthor(Context context,
|
||||
Item item)
|
||||
throws SQLException {
|
||||
List<RequestItemAuthor> recipients = new ArrayList<>();
|
||||
Collection collection = item.getOwningCollection();
|
||||
for (EPerson admin : collection.getAdministrators().getMembers()) {
|
||||
recipients.add(new RequestItemAuthor(admin));
|
||||
}
|
||||
if (recipients.isEmpty()) {
|
||||
return super.getRequestItemAuthor(context, item);
|
||||
} else {
|
||||
return recipients;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.requestitem;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Assemble a list of recipients from the results of other strategies.
|
||||
* The list of strategy classes is injected as the constructor argument
|
||||
* {@code strategies}.
|
||||
* If the strategy list is not configured, returns an empty List.
|
||||
*
|
||||
* @author Mark H. Wood <mwood@iupui.edu>
|
||||
*/
|
||||
public class CombiningRequestItemStrategy
|
||||
implements RequestItemAuthorExtractor {
|
||||
/** The strategies to combine. */
|
||||
private final List<RequestItemAuthorExtractor> strategies;
|
||||
|
||||
/**
|
||||
* Initialize a combination of strategies.
|
||||
* @param strategies the author extraction strategies to combine.
|
||||
*/
|
||||
public CombiningRequestItemStrategy(@NonNull List<RequestItemAuthorExtractor> strategies) {
|
||||
Assert.notNull(strategies, "Strategy list may not be null");
|
||||
this.strategies = strategies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not call.
|
||||
* @throws IllegalArgumentException always
|
||||
*/
|
||||
private CombiningRequestItemStrategy() {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||
throws SQLException {
|
||||
List<RequestItemAuthor> recipients = new ArrayList<>();
|
||||
|
||||
for (RequestItemAuthorExtractor strategy : strategies) {
|
||||
recipients.addAll(strategy.getRequestItemAuthor(context, item));
|
||||
}
|
||||
|
||||
return recipients;
|
||||
}
|
||||
}
|
@@ -27,7 +27,7 @@ import org.dspace.core.Context;
|
||||
import org.dspace.core.ReloadableEntity;
|
||||
|
||||
/**
|
||||
* Object representing an Item Request
|
||||
* Object representing an Item Request.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "requestitem")
|
||||
@@ -94,6 +94,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
||||
this.allfiles = allfiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if all of the Item's files are requested.
|
||||
*/
|
||||
public boolean isAllfiles() {
|
||||
return allfiles;
|
||||
}
|
||||
@@ -102,6 +105,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
||||
this.reqMessage = reqMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a message from the requester.
|
||||
*/
|
||||
public String getReqMessage() {
|
||||
return reqMessage;
|
||||
}
|
||||
@@ -110,6 +116,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
||||
this.reqName = reqName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Human-readable name of the user requesting access.
|
||||
*/
|
||||
public String getReqName() {
|
||||
return reqName;
|
||||
}
|
||||
@@ -118,6 +127,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
||||
this.reqEmail = reqEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return address of the user requesting access.
|
||||
*/
|
||||
public String getReqEmail() {
|
||||
return reqEmail;
|
||||
}
|
||||
@@ -126,6 +138,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a unique request identifier which can be emailed.
|
||||
*/
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
@@ -11,20 +11,31 @@ import org.dspace.eperson.EPerson;
|
||||
|
||||
/**
|
||||
* Simple DTO to transfer data about the corresponding author for the Request
|
||||
* Copy feature
|
||||
* Copy feature.
|
||||
*
|
||||
* @author Andrea Bollini
|
||||
*/
|
||||
public class RequestItemAuthor {
|
||||
private String fullName;
|
||||
private String email;
|
||||
private final String fullName;
|
||||
private final String email;
|
||||
|
||||
/**
|
||||
* Construct an author record from given data.
|
||||
*
|
||||
* @param fullName the author's full name.
|
||||
* @param email the author's email address.
|
||||
*/
|
||||
public RequestItemAuthor(String fullName, String email) {
|
||||
super();
|
||||
this.fullName = fullName;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an author from an EPerson's metadata.
|
||||
*
|
||||
* @param ePerson the EPerson.
|
||||
*/
|
||||
public RequestItemAuthor(EPerson ePerson) {
|
||||
super();
|
||||
this.fullName = ePerson.getFullName();
|
||||
|
@@ -8,26 +8,28 @@
|
||||
package org.dspace.app.requestitem;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* Interface to abstract the strategy for select the author to contact for
|
||||
* request copy
|
||||
* Interface to abstract the strategy for selecting the author to contact for
|
||||
* request copy.
|
||||
*
|
||||
* @author Andrea Bollini
|
||||
*/
|
||||
public interface RequestItemAuthorExtractor {
|
||||
|
||||
/**
|
||||
* Retrieve the auhtor to contact for a request copy of the give item.
|
||||
* Retrieve the author to contact for requesting a copy of the given item.
|
||||
*
|
||||
* @param context DSpace context object
|
||||
* @param item item to request
|
||||
* @return An object containing name an email address to send the request to
|
||||
* or null if no valid email address was found.
|
||||
* @return Names and email addresses to send the request to.
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) throws SQLException;
|
||||
@NonNull
|
||||
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||
throws SQLException;
|
||||
}
|
||||
|
@@ -72,28 +72,48 @@ public class RequestItemEmailNotifier {
|
||||
static public void sendRequest(Context context, RequestItem ri, String responseLink)
|
||||
throws IOException, SQLException {
|
||||
// Who is making this request?
|
||||
RequestItemAuthor author = requestItemAuthorExtractor
|
||||
List<RequestItemAuthor> authors = requestItemAuthorExtractor
|
||||
.getRequestItemAuthor(context, ri.getItem());
|
||||
String authorEmail = author.getEmail();
|
||||
String authorName = author.getFullName();
|
||||
|
||||
// Build an email to the approver.
|
||||
Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(),
|
||||
"request_item.author"));
|
||||
email.addRecipient(authorEmail);
|
||||
for (RequestItemAuthor author : authors) {
|
||||
email.addRecipient(author.getEmail());
|
||||
}
|
||||
email.setReplyTo(ri.getReqEmail()); // Requester's address
|
||||
|
||||
email.addArgument(ri.getReqName()); // {0} Requester's name
|
||||
|
||||
email.addArgument(ri.getReqEmail()); // {1} Requester's address
|
||||
|
||||
email.addArgument(ri.isAllfiles() // {2} All bitstreams or just one?
|
||||
? I18nUtil.getMessage("itemRequest.all") : ri.getBitstream().getName());
|
||||
email.addArgument(handleService.getCanonicalForm(ri.getItem().getHandle()));
|
||||
|
||||
email.addArgument(handleService.getCanonicalForm(ri.getItem().getHandle())); // {3}
|
||||
|
||||
email.addArgument(ri.getItem().getName()); // {4} requested item's title
|
||||
|
||||
email.addArgument(ri.getReqMessage()); // {5} message from requester
|
||||
|
||||
email.addArgument(responseLink); // {6} Link back to DSpace for action
|
||||
email.addArgument(authorName); // {7} corresponding author name
|
||||
email.addArgument(authorEmail); // {8} corresponding author email
|
||||
email.addArgument(configurationService.getProperty("dspace.name"));
|
||||
email.addArgument(configurationService.getProperty("mail.helpdesk"));
|
||||
|
||||
StringBuilder names = new StringBuilder();
|
||||
StringBuilder addresses = new StringBuilder();
|
||||
for (RequestItemAuthor author : authors) {
|
||||
if (names.length() > 0) {
|
||||
names.append("; ");
|
||||
addresses.append("; ");
|
||||
}
|
||||
names.append(author.getFullName());
|
||||
addresses.append(author.getEmail());
|
||||
}
|
||||
email.addArgument(names.toString()); // {7} corresponding author name
|
||||
email.addArgument(addresses.toString()); // {8} corresponding author email
|
||||
|
||||
email.addArgument(configurationService.getProperty("dspace.name")); // {9}
|
||||
|
||||
email.addArgument(configurationService.getProperty("mail.helpdesk")); // {10}
|
||||
|
||||
// Send the email.
|
||||
try {
|
||||
|
@@ -8,6 +8,8 @@
|
||||
package org.dspace.app.requestitem;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.content.Item;
|
||||
@@ -16,11 +18,11 @@ import org.dspace.core.I18nUtil;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* RequestItem strategy to allow DSpace support team's helpdesk to receive requestItem request
|
||||
* RequestItem strategy to allow DSpace support team's helpdesk to receive requestItem request.
|
||||
* With this enabled, then the Item author/submitter doesn't receive the request, but the helpdesk instead does.
|
||||
*
|
||||
* Failover to the RequestItemSubmitterStrategy, which means the submitter would get the request if there is no
|
||||
@@ -33,19 +35,24 @@ public class RequestItemHelpdeskStrategy extends RequestItemSubmitterStrategy {
|
||||
@Autowired(required = true)
|
||||
protected EPersonService ePersonService;
|
||||
|
||||
@Autowired(required = true)
|
||||
private ConfigurationService configuration;
|
||||
|
||||
public RequestItemHelpdeskStrategy() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) throws SQLException {
|
||||
ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
boolean helpdeskOverridesSubmitter = configurationService
|
||||
@NonNull
|
||||
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||
throws SQLException {
|
||||
boolean helpdeskOverridesSubmitter = configuration
|
||||
.getBooleanProperty("request.item.helpdesk.override", false);
|
||||
String helpDeskEmail = configurationService.getProperty("mail.helpdesk");
|
||||
String helpDeskEmail = configuration.getProperty("mail.helpdesk");
|
||||
|
||||
if (helpdeskOverridesSubmitter && StringUtils.isNotBlank(helpDeskEmail)) {
|
||||
return getHelpDeskPerson(context, helpDeskEmail);
|
||||
List<RequestItemAuthor> authors = new ArrayList<>(1);
|
||||
authors.add(getHelpDeskPerson(context, helpDeskEmail));
|
||||
return authors;
|
||||
} else {
|
||||
//Fallback to default logic (author of Item) if helpdesk isn't fully enabled or setup
|
||||
return super.getRequestItemAuthor(context, item);
|
||||
|
@@ -8,6 +8,8 @@
|
||||
package org.dspace.app.requestitem;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -16,12 +18,13 @@ import org.dspace.content.MetadataValue;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.I18nUtil;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* Try to look to an item metadata for the corresponding author name and email.
|
||||
* Failover to the RequestItemSubmitterStrategy
|
||||
* Failover to the RequestItemSubmitterStrategy.
|
||||
*
|
||||
* @author Andrea Bollini
|
||||
*/
|
||||
@@ -30,6 +33,9 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
|
||||
protected String emailMetadata;
|
||||
protected String fullNameMetadata;
|
||||
|
||||
@Autowired(required = true)
|
||||
protected ConfigurationService configurationService;
|
||||
|
||||
@Autowired(required = true)
|
||||
protected ItemService itemService;
|
||||
|
||||
@@ -37,59 +43,72 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
|
||||
@NonNull
|
||||
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||
throws SQLException {
|
||||
RequestItemAuthor author = null;
|
||||
List<RequestItemAuthor> authors;
|
||||
if (emailMetadata != null) {
|
||||
List<MetadataValue> vals = itemService.getMetadataByMetadataString(item, emailMetadata);
|
||||
if (vals.size() > 0) {
|
||||
String email = vals.iterator().next().getValue();
|
||||
String fullname = null;
|
||||
if (fullNameMetadata != null) {
|
||||
List<MetadataValue> nameVals = itemService.getMetadataByMetadataString(item, fullNameMetadata);
|
||||
if (nameVals.size() > 0) {
|
||||
fullname = nameVals.iterator().next().getValue();
|
||||
List<MetadataValue> nameVals;
|
||||
if (null != fullNameMetadata) {
|
||||
nameVals = itemService.getMetadataByMetadataString(item, fullNameMetadata);
|
||||
} else {
|
||||
nameVals = Collections.EMPTY_LIST;
|
||||
}
|
||||
boolean useNames = vals.size() == nameVals.size();
|
||||
if (!vals.isEmpty()) {
|
||||
authors = new ArrayList<>(vals.size());
|
||||
for (int authorIndex = 0; authorIndex < vals.size(); authorIndex++) {
|
||||
String email = vals.get(authorIndex).getValue();
|
||||
String fullname = null;
|
||||
if (useNames) {
|
||||
fullname = nameVals.get(authorIndex).getValue();
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(fullname)) {
|
||||
fullname = I18nUtil.getMessage(
|
||||
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
|
||||
context);
|
||||
}
|
||||
RequestItemAuthor author = new RequestItemAuthor(
|
||||
fullname, email);
|
||||
authors.add(author);
|
||||
}
|
||||
if (StringUtils.isBlank(fullname)) {
|
||||
fullname = I18nUtil
|
||||
.getMessage(
|
||||
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
|
||||
context);
|
||||
}
|
||||
author = new RequestItemAuthor(fullname, email);
|
||||
return author;
|
||||
return authors;
|
||||
} else {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
} else {
|
||||
// Uses the basic strategy to look for the original submitter
|
||||
author = super.getRequestItemAuthor(context, item);
|
||||
// Is the author or his email null, so get the help desk or admin name and email
|
||||
if (null == author || null == author.getEmail()) {
|
||||
String email = null;
|
||||
String name = null;
|
||||
authors = super.getRequestItemAuthor(context, item);
|
||||
|
||||
// Remove from the list authors that do not have email addresses.
|
||||
for (RequestItemAuthor author : authors) {
|
||||
if (null == author.getEmail()) {
|
||||
authors.remove(author);
|
||||
}
|
||||
}
|
||||
|
||||
if (authors.isEmpty()) { // No author email addresses! Fall back
|
||||
//First get help desk name and email
|
||||
email = DSpaceServicesFactory.getInstance()
|
||||
.getConfigurationService().getProperty("mail.helpdesk");
|
||||
name = DSpaceServicesFactory.getInstance()
|
||||
.getConfigurationService().getProperty("mail.helpdesk.name");
|
||||
String email = configurationService.getProperty("mail.helpdesk");
|
||||
String name = configurationService.getProperty("mail.helpdesk.name");
|
||||
// If help desk mail is null get the mail and name of admin
|
||||
if (email == null) {
|
||||
email = DSpaceServicesFactory.getInstance()
|
||||
.getConfigurationService().getProperty("mail.admin");
|
||||
name = DSpaceServicesFactory.getInstance()
|
||||
.getConfigurationService().getProperty("mail.admin.name");
|
||||
email = configurationService.getProperty("mail.admin");
|
||||
name = configurationService.getProperty("mail.admin.name");
|
||||
}
|
||||
author = new RequestItemAuthor(name, email);
|
||||
authors.add(new RequestItemAuthor(name, email));
|
||||
}
|
||||
return authors;
|
||||
}
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setEmailMetadata(String emailMetadata) {
|
||||
public void setEmailMetadata(@NonNull String emailMetadata) {
|
||||
this.emailMetadata = emailMetadata;
|
||||
}
|
||||
|
||||
public void setFullNameMetadata(String fullNameMetadata) {
|
||||
public void setFullNameMetadata(@NonNull String fullNameMetadata) {
|
||||
this.fullNameMetadata = fullNameMetadata;
|
||||
}
|
||||
|
||||
|
@@ -8,10 +8,13 @@
|
||||
package org.dspace.app.requestitem;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* Basic strategy that looks to the original submitter.
|
||||
@@ -24,21 +27,23 @@ public class RequestItemSubmitterStrategy implements RequestItemAuthorExtractor
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the submitter of an Item as RequestItemAuthor or null if the
|
||||
* Submitter is deleted.
|
||||
* Returns the submitter of an Item as RequestItemAuthor or an empty List if
|
||||
* the Submitter is deleted.
|
||||
*
|
||||
* @return The submitter of the item or null if the submitter is deleted
|
||||
* @return The submitter of the item or empty List if the submitter is deleted
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
@Override
|
||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
|
||||
@NonNull
|
||||
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||
throws SQLException {
|
||||
EPerson submitter = item.getSubmitter();
|
||||
RequestItemAuthor author = null;
|
||||
List<RequestItemAuthor> authors = new ArrayList<>(1);
|
||||
if (null != submitter) {
|
||||
author = new RequestItemAuthor(
|
||||
submitter.getFullName(), submitter.getEmail());
|
||||
RequestItemAuthor author = new RequestItemAuthor(
|
||||
submitter.getFullName(), submitter.getEmail());
|
||||
authors.add(author);
|
||||
}
|
||||
return author;
|
||||
return authors;
|
||||
}
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@ import org.dspace.app.sherpa.v2.SHERPAResponse;
|
||||
import org.dspace.app.sherpa.v2.SHERPAUtils;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
|
||||
/**
|
||||
* SHERPAService is responsible for making the HTTP call to the SHERPA v2 API
|
||||
@@ -43,6 +44,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
* @author Kim Shepherd
|
||||
*/
|
||||
public class SHERPAService {
|
||||
|
||||
private CloseableHttpClient client = null;
|
||||
|
||||
private int maxNumberOfTries;
|
||||
@@ -91,6 +93,7 @@ public class SHERPAService {
|
||||
* @param query ISSN string to pass in an "issn equals" API query
|
||||
* @return SHERPAResponse containing an error or journal policies
|
||||
*/
|
||||
@Cacheable(key = "#query", cacheNames = "sherpa.searchByJournalISSN")
|
||||
public SHERPAResponse searchByJournalISSN(String query) {
|
||||
return performRequest("publication", "issn", "equals", query, 0, 1);
|
||||
}
|
||||
@@ -413,4 +416,5 @@ public class SHERPAService {
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
71
dspace-api/src/main/java/org/dspace/app/sherpa/cache/SherpaCacheEvictService.java
vendored
Normal file
71
dspace-api/src/main/java/org/dspace/app/sherpa/cache/SherpaCacheEvictService.java
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.sherpa.cache;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.dspace.app.sherpa.submit.SHERPASubmitService;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
/**
|
||||
* This service is responsible to deal with the SherpaService cache.
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
public class SherpaCacheEvictService {
|
||||
|
||||
// The cache that is managed by this service.
|
||||
static final String CACHE_NAME = "sherpa.searchByJournalISSN";
|
||||
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private SHERPASubmitService sherpaSubmitService;
|
||||
|
||||
/**
|
||||
* Remove immediately from the cache all the response that are related to a specific item
|
||||
* extracting the ISSNs from the item
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param item an Item
|
||||
*/
|
||||
public void evictCacheValues(Context context, Item item) {
|
||||
Set<String> ISSNs = sherpaSubmitService.getISSNs(context, item);
|
||||
for (String issn : ISSNs) {
|
||||
Objects.requireNonNull(cacheManager.getCache(CACHE_NAME)).evictIfPresent(issn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate immediately the Sherpa cache
|
||||
*/
|
||||
public void evictAllCacheValues() {
|
||||
Objects.requireNonNull(cacheManager.getCache(CACHE_NAME)).invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reference to the cacheManager
|
||||
*
|
||||
* @param cacheManager
|
||||
*/
|
||||
public void setCacheManager(CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reference to the SherpaSubmitService
|
||||
*
|
||||
* @param sherpaSubmitService
|
||||
*/
|
||||
public void setSherpaSubmitService(SHERPASubmitService sherpaSubmitService) {
|
||||
this.sherpaSubmitService = sherpaSubmitService;
|
||||
}
|
||||
|
||||
}
|
34
dspace-api/src/main/java/org/dspace/app/sherpa/cache/SherpaCacheLogger.java
vendored
Normal file
34
dspace-api/src/main/java/org/dspace/app/sherpa/cache/SherpaCacheLogger.java
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.sherpa.cache;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.ehcache.event.CacheEvent;
|
||||
import org.ehcache.event.CacheEventListener;
|
||||
|
||||
/**
|
||||
* This is a EHCache listner responsible for logging sherpa cache events. It is
|
||||
* bound to the sherpa cache via the dspace/config/ehcache.xml file. We need a
|
||||
* dedicated Logger for each cache as the CacheEvent doesn't include details
|
||||
* about where the event occur
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*
|
||||
*/
|
||||
public class SherpaCacheLogger implements CacheEventListener<Object, Object> {
|
||||
|
||||
private static final Logger log = LogManager.getLogger(SherpaCacheLogger.class);
|
||||
|
||||
@Override
|
||||
public void onEvent(CacheEvent<?, ?> cacheEvent) {
|
||||
log.debug("Sherpa Cache Event Type: {} | Key: {} ",
|
||||
cacheEvent.getType(), cacheEvent.getKey());
|
||||
}
|
||||
|
||||
}
|
@@ -9,7 +9,6 @@ package org.dspace.app.sherpa.submit;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -63,19 +62,19 @@ public class SHERPASubmitService {
|
||||
* issnItemExtractor(s) in the SHERPA spring configuration.
|
||||
* The ISSNs are not validated with a regular expression or other rules - any values
|
||||
* extracted will be included in API queries.
|
||||
* Return the first not empty response from Sherpa
|
||||
* @see "dspace-dspace-addon-sherpa-configuration-services.xml"
|
||||
* @param context DSpace context
|
||||
* @param item DSpace item containing ISSNs to be checked
|
||||
* @return SHERPA v2 API response (policy data)
|
||||
*/
|
||||
public List<SHERPAResponse> searchRelatedJournals(Context context, Item item) {
|
||||
public SHERPAResponse searchRelatedJournals(Context context, Item item) {
|
||||
Set<String> issns = getISSNs(context, item);
|
||||
if (issns == null || issns.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
// SHERPA v2 API no longer supports "OR'd" ISSN search, perform individual searches instead
|
||||
Iterator<String> issnIterator = issns.iterator();
|
||||
List<SHERPAResponse> responses = new LinkedList<>();
|
||||
while (issnIterator.hasNext()) {
|
||||
String issn = issnIterator.next();
|
||||
SHERPAResponse response = sherpaService.searchByJournalISSN(issn);
|
||||
@@ -83,14 +82,13 @@ public class SHERPASubmitService {
|
||||
// Continue with loop
|
||||
log.warn("Failed to look up SHERPA ROMeO result for ISSN: " + issn
|
||||
+ ": " + response.getMessage());
|
||||
return response;
|
||||
} else if (!response.getJournals().isEmpty()) {
|
||||
// return this response, if it is not empty
|
||||
return response;
|
||||
}
|
||||
// Store this response, even if it has an error (useful for UI reporting)
|
||||
responses.add(response);
|
||||
}
|
||||
if (responses.isEmpty()) {
|
||||
responses.add(new SHERPAResponse("SHERPA ROMeO lookup failed"));
|
||||
}
|
||||
return responses;
|
||||
return new SHERPAResponse();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Model class for the Embargo of SHERPAv2 API (JSON)
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||
*/
|
||||
public class SHERPAEmbargo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6140668058547523656L;
|
||||
|
||||
private int amount;
|
||||
private String units;
|
||||
|
||||
public SHERPAEmbargo(int amount, String units) {
|
||||
this.amount = amount;
|
||||
this.units = units;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(int amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public String getUnits() {
|
||||
return units;
|
||||
}
|
||||
|
||||
public void setUnits(String units) {
|
||||
this.units = units;
|
||||
}
|
||||
|
||||
}
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -21,7 +22,7 @@ import java.util.List;
|
||||
*
|
||||
* @author Kim Shepherd
|
||||
*/
|
||||
public class SHERPAJournal {
|
||||
public class SHERPAJournal implements Serializable {
|
||||
|
||||
private List<String> titles;
|
||||
private String url;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,9 @@ import java.util.List;
|
||||
*
|
||||
* @see SHERPAPublisherPolicy
|
||||
*/
|
||||
public class SHERPAPermittedVersion {
|
||||
public class SHERPAPermittedVersion implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4992181606327727442L;
|
||||
|
||||
// Version (submitted, accepted, published)
|
||||
private String articleVersion;
|
||||
@@ -47,11 +50,6 @@ public class SHERPAPermittedVersion {
|
||||
// Embargo
|
||||
private SHERPAEmbargo embargo;
|
||||
|
||||
protected static class SHERPAEmbargo {
|
||||
String units;
|
||||
int amount;
|
||||
}
|
||||
|
||||
public String getArticleVersion() {
|
||||
return articleVersion;
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Plain java representation of a SHERPA Publisher object, based on SHERPA API v2 responses.
|
||||
*
|
||||
@@ -18,7 +20,7 @@ package org.dspace.app.sherpa.v2;
|
||||
* @see SHERPAJournal
|
||||
* @see SHERPAPublisherResponse
|
||||
*/
|
||||
public class SHERPAPublisher {
|
||||
public class SHERPAPublisher implements Serializable {
|
||||
private String name = null;
|
||||
private String relationshipType;
|
||||
private String country;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -22,7 +23,7 @@ import java.util.Map;
|
||||
* @see SHERPAJournal
|
||||
* @see SHERPAPermittedVersion
|
||||
*/
|
||||
public class SHERPAPublisherPolicy {
|
||||
public class SHERPAPublisherPolicy implements Serializable {
|
||||
|
||||
private int id;
|
||||
private boolean openAccessPermitted;
|
||||
|
@@ -10,12 +10,15 @@ package org.dspace.app.sherpa.v2;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.json.JSONArray;
|
||||
@@ -33,7 +36,10 @@ import org.json.JSONTokener;
|
||||
* @author Kim Shepherd
|
||||
*
|
||||
*/
|
||||
public class SHERPAResponse {
|
||||
public class SHERPAResponse implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2732963970169240597L;
|
||||
|
||||
// Is this response to be treated as an error?
|
||||
private boolean error;
|
||||
|
||||
@@ -52,6 +58,9 @@ public class SHERPAResponse {
|
||||
// SHERPA URI (the human page version of this API response)
|
||||
private String uri;
|
||||
|
||||
@JsonIgnore
|
||||
private Date retrievalTime = new Date();
|
||||
|
||||
// Format enum - currently only JSON is supported
|
||||
public enum SHERPAFormat {
|
||||
JSON, XML
|
||||
@@ -71,6 +80,11 @@ public class SHERPAResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty SHERPAResponse representation
|
||||
*/
|
||||
public SHERPAResponse() {}
|
||||
|
||||
/**
|
||||
* Parse the SHERPA v2 API JSON and construct Romeo policy data for display
|
||||
* This method does not return a value, but rather populates the metadata and journals objects
|
||||
@@ -479,6 +493,12 @@ public class SHERPAResponse {
|
||||
}
|
||||
permittedVersion.setLicenses(sherpaLicenses);
|
||||
|
||||
if (permitted.has("embargo")) {
|
||||
JSONObject embargo = permitted.getJSONObject("embargo");
|
||||
SHERPAEmbargo SHERPAEmbargo = new SHERPAEmbargo(embargo.getInt("amount"), embargo.getString("units"));
|
||||
permittedVersion.setEmbargo(SHERPAEmbargo);
|
||||
}
|
||||
|
||||
return permittedVersion;
|
||||
}
|
||||
|
||||
@@ -542,4 +562,8 @@ public class SHERPAResponse {
|
||||
public SHERPASystemMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public Date getRetrievalTime() {
|
||||
return retrievalTime;
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Plain java representation of a SHERPA System Metadata object, based on SHERPA API v2 responses.
|
||||
*
|
||||
@@ -18,7 +20,7 @@ package org.dspace.app.sherpa.v2;
|
||||
*
|
||||
* @author Kim Shepherd
|
||||
*/
|
||||
public class SHERPASystemMetadata {
|
||||
public class SHERPASystemMetadata implements Serializable {
|
||||
|
||||
private int id;
|
||||
private String uri;
|
||||
|
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.solrdatabaseresync;
|
||||
|
||||
import static org.dspace.discovery.indexobject.ItemIndexFactoryImpl.STATUS_FIELD;
|
||||
import static org.dspace.discovery.indexobject.ItemIndexFactoryImpl.STATUS_FIELD_PREDB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.IndexingService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.SearchUtils;
|
||||
import org.dspace.discovery.SolrSearchCore;
|
||||
import org.dspace.discovery.indexobject.IndexableItem;
|
||||
import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.dspace.util.SolrUtils;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
/**
|
||||
* {@link DSpaceRunnable} implementation to update solr items with "predb" status to either:
|
||||
* - Delete them from solr if they're not present in the database
|
||||
* - Remove their status if they're present in the database
|
||||
*/
|
||||
public class SolrDatabaseResyncCli extends DSpaceRunnable<SolrDatabaseResyncCliScriptConfiguration> {
|
||||
/* Log4j logger */
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SolrDatabaseResyncCli.class);
|
||||
|
||||
public static final String TIME_UNTIL_REINDEX_PROPERTY = "solr-database-resync.time-until-reindex";
|
||||
|
||||
private IndexingService indexingService;
|
||||
private SolrSearchCore solrSearchCore;
|
||||
private IndexObjectFactoryFactory indexObjectServiceFactory;
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
private int timeUntilReindex = 0;
|
||||
private String maxTime;
|
||||
|
||||
@Override
|
||||
public SolrDatabaseResyncCliScriptConfiguration getScriptConfiguration() {
|
||||
return new DSpace().getServiceManager()
|
||||
.getServiceByName("solr-database-resync", SolrDatabaseResyncCliScriptConfiguration.class);
|
||||
}
|
||||
|
||||
public static void runScheduled() throws Exception {
|
||||
SolrDatabaseResyncCli script = new SolrDatabaseResyncCli();
|
||||
script.setup();
|
||||
script.internalRun();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() throws ParseException {
|
||||
indexingService = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServiceByName(IndexingService.class.getName(), IndexingService.class);
|
||||
solrSearchCore = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServicesByType(SolrSearchCore.class).get(0);
|
||||
indexObjectServiceFactory = IndexObjectFactoryFactory.getInstance();
|
||||
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalRun() throws Exception {
|
||||
logInfoAndOut("Starting Item resync of Solr and Database...");
|
||||
|
||||
timeUntilReindex = getTimeUntilReindex();
|
||||
maxTime = getMaxTime();
|
||||
|
||||
Context context = new Context();
|
||||
|
||||
try {
|
||||
context.turnOffAuthorisationSystem();
|
||||
performStatusUpdate(context);
|
||||
} finally {
|
||||
context.restoreAuthSystemState();
|
||||
context.complete();
|
||||
}
|
||||
}
|
||||
|
||||
private void performStatusUpdate(Context context) throws SearchServiceException, SolrServerException, IOException {
|
||||
SolrQuery solrQuery = new SolrQuery();
|
||||
solrQuery.setQuery(STATUS_FIELD + ":" + STATUS_FIELD_PREDB);
|
||||
solrQuery.addFilterQuery(SearchUtils.RESOURCE_TYPE_FIELD + ":" + IndexableItem.TYPE);
|
||||
String dateRangeFilter = SearchUtils.LAST_INDEXED_FIELD + ":[* TO " + maxTime + "]";
|
||||
logDebugAndOut("Date range filter used; " + dateRangeFilter);
|
||||
solrQuery.addFilterQuery(dateRangeFilter);
|
||||
solrQuery.addField(SearchUtils.RESOURCE_ID_FIELD);
|
||||
solrQuery.addField(SearchUtils.RESOURCE_UNIQUE_ID);
|
||||
QueryResponse response = solrSearchCore.getSolr().query(solrQuery, solrSearchCore.REQUEST_METHOD);
|
||||
|
||||
if (response != null) {
|
||||
logInfoAndOut(response.getResults().size() + " items found to process");
|
||||
|
||||
for (SolrDocument doc : response.getResults()) {
|
||||
String uuid = (String) doc.getFirstValue(SearchUtils.RESOURCE_ID_FIELD);
|
||||
String uniqueId = (String) doc.getFirstValue(SearchUtils.RESOURCE_UNIQUE_ID);
|
||||
logDebugAndOut("Processing item with UUID: " + uuid);
|
||||
|
||||
Optional<IndexableObject> indexableObject = Optional.empty();
|
||||
try {
|
||||
indexableObject = indexObjectServiceFactory
|
||||
.getIndexableObjectFactory(uniqueId).findIndexableObject(context, uuid);
|
||||
} catch (SQLException e) {
|
||||
log.warn("An exception occurred when attempting to retrieve item with UUID \"" + uuid +
|
||||
"\" from the database, removing related solr document", e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (indexableObject.isPresent()) {
|
||||
logDebugAndOut("Item exists in DB, updating solr document");
|
||||
updateItem(context, indexableObject.get());
|
||||
} else {
|
||||
logDebugAndOut("Item doesn't exist in DB, removing solr document");
|
||||
removeItem(context, uniqueId);
|
||||
}
|
||||
} catch (SQLException | IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indexingService.commit();
|
||||
}
|
||||
|
||||
private void updateItem(Context context, IndexableObject indexableObject) throws SolrServerException, IOException {
|
||||
Map<String,Object> fieldModifier = new HashMap<>(1);
|
||||
fieldModifier.put("remove", STATUS_FIELD_PREDB);
|
||||
indexingService.atomicUpdate(context, indexableObject.getUniqueIndexID(), STATUS_FIELD, fieldModifier);
|
||||
}
|
||||
|
||||
private void removeItem(Context context, String uniqueId) throws IOException, SQLException {
|
||||
indexingService.unIndexContent(context, uniqueId);
|
||||
}
|
||||
|
||||
private String getMaxTime() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
if (timeUntilReindex > 0) {
|
||||
cal.add(Calendar.MILLISECOND, -timeUntilReindex);
|
||||
}
|
||||
return SolrUtils.getDateFormatter().format(cal.getTime());
|
||||
}
|
||||
|
||||
private int getTimeUntilReindex() {
|
||||
return configurationService.getIntProperty(TIME_UNTIL_REINDEX_PROPERTY, 0);
|
||||
}
|
||||
|
||||
private void logInfoAndOut(String message) {
|
||||
log.info(message);
|
||||
System.out.println(message);
|
||||
}
|
||||
|
||||
private void logDebugAndOut(String message) {
|
||||
log.debug(message);
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.solrdatabaseresync;
|
||||
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
|
||||
/**
|
||||
* The {@link ScriptConfiguration} for the {@link SolrDatabaseResyncCli} script.
|
||||
*/
|
||||
public class SolrDatabaseResyncCliScriptConfiguration extends ScriptConfiguration<SolrDatabaseResyncCli> {
|
||||
private Class<SolrDatabaseResyncCli> dspaceRunnableClass;
|
||||
|
||||
@Override
|
||||
public Class<SolrDatabaseResyncCli> getDspaceRunnableClass() {
|
||||
return dspaceRunnableClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDspaceRunnableClass(Class<SolrDatabaseResyncCli> dspaceRunnableClass) {
|
||||
this.dspaceRunnableClass = dspaceRunnableClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowedToExecute(Context context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Options getOptions() {
|
||||
if (options == null) {
|
||||
options = new Options();
|
||||
}
|
||||
return options;
|
||||
}
|
||||
}
|
@@ -29,6 +29,10 @@ import java.util.TimeZone;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogHelper;
|
||||
@@ -44,6 +48,7 @@ import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
* files. Most input can be configured; use the -help flag for a full list
|
||||
* of usage information.
|
||||
*
|
||||
* <p>
|
||||
* The output of this file is plain text and forms an "aggregation" file which
|
||||
* can then be used for display purposes using the related ReportGenerator
|
||||
* class.
|
||||
@@ -167,7 +172,7 @@ public class LogAnalyser {
|
||||
/**
|
||||
* the average number of views per item
|
||||
*/
|
||||
private static int views = 0;
|
||||
private static long views = 0;
|
||||
|
||||
///////////////////////
|
||||
// regular expressions
|
||||
@@ -236,12 +241,12 @@ public class LogAnalyser {
|
||||
/**
|
||||
* pattern to match commented out lines from the config file
|
||||
*/
|
||||
private static final Pattern comment = Pattern.compile("^#");
|
||||
private static final Pattern COMMENT = Pattern.compile("^#");
|
||||
|
||||
/**
|
||||
* pattern to match genuine lines from the config file
|
||||
*/
|
||||
private static final Pattern real = Pattern.compile("^(.+)=(.+)");
|
||||
private static final Pattern REAL = Pattern.compile("^(.+)=(.+)");
|
||||
|
||||
/**
|
||||
* pattern to match all search types
|
||||
@@ -337,44 +342,73 @@ public class LogAnalyser {
|
||||
Date myEndDate = null;
|
||||
boolean myLookUp = false;
|
||||
|
||||
// read in our command line options
|
||||
for (int i = 0; i < argv.length; i++) {
|
||||
if (argv[i].equals("-log")) {
|
||||
myLogDir = argv[i + 1];
|
||||
}
|
||||
// Define command line options.
|
||||
Options options = new Options();
|
||||
Option option;
|
||||
|
||||
if (argv[i].equals("-file")) {
|
||||
myFileTemplate = argv[i + 1];
|
||||
}
|
||||
option = Option.builder().longOpt("log").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-cfg")) {
|
||||
myConfigFile = argv[i + 1];
|
||||
}
|
||||
option = Option.builder().longOpt("file").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-out")) {
|
||||
myOutFile = argv[i + 1];
|
||||
}
|
||||
option = Option.builder().longOpt("cfg").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-help")) {
|
||||
LogAnalyser.usage();
|
||||
System.exit(0);
|
||||
}
|
||||
option = Option.builder().longOpt("out").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-start")) {
|
||||
myStartDate = parseDate(argv[i + 1]);
|
||||
}
|
||||
option = Option.builder().longOpt("help").build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-end")) {
|
||||
myEndDate = parseDate(argv[i + 1]);
|
||||
}
|
||||
option = Option.builder().longOpt("start").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-lookup")) {
|
||||
myLookUp = true;
|
||||
}
|
||||
option = Option.builder().longOpt("end").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
option = Option.builder().longOpt("lookup").build();
|
||||
options.addOption(option);
|
||||
|
||||
// Parse the command.
|
||||
DefaultParser cmdParser = new DefaultParser();
|
||||
CommandLine cmd = cmdParser.parse(options, argv);
|
||||
|
||||
// Analyze the command.
|
||||
if (cmd.hasOption("help")) {
|
||||
LogAnalyser.usage();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
if (cmd.hasOption("log")) {
|
||||
myLogDir = cmd.getOptionValue("log");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("file")) {
|
||||
myFileTemplate = cmd.getOptionValue("file");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("cfg")) {
|
||||
myConfigFile = cmd.getOptionValue("cfg");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("out")) {
|
||||
myOutFile = cmd.getOptionValue("out");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("start")) {
|
||||
myStartDate = parseDate(cmd.getOptionValue("start"));
|
||||
}
|
||||
|
||||
if (cmd.hasOption("end")) {
|
||||
myEndDate = parseDate(cmd.getOptionValue("end"));
|
||||
}
|
||||
|
||||
myLookUp = cmd.hasOption("lookup");
|
||||
|
||||
// now call the method which actually processes the logs
|
||||
processLogs(context, myLogDir, myFileTemplate, myConfigFile, myOutFile, myStartDate, myEndDate, myLookUp);
|
||||
processLogs(context, myLogDir, myFileTemplate, myConfigFile, myOutFile,
|
||||
myStartDate, myEndDate, myLookUp);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -406,18 +440,18 @@ public class LogAnalyser {
|
||||
startTime = new GregorianCalendar();
|
||||
|
||||
//instantiate aggregators
|
||||
actionAggregator = new HashMap<String, Integer>();
|
||||
searchAggregator = new HashMap<String, Integer>();
|
||||
userAggregator = new HashMap<String, Integer>();
|
||||
itemAggregator = new HashMap<String, Integer>();
|
||||
archiveStats = new HashMap<String, Integer>();
|
||||
actionAggregator = new HashMap<>();
|
||||
searchAggregator = new HashMap<>();
|
||||
userAggregator = new HashMap<>();
|
||||
itemAggregator = new HashMap<>();
|
||||
archiveStats = new HashMap<>();
|
||||
|
||||
//instantiate lists
|
||||
generalSummary = new ArrayList<String>();
|
||||
excludeWords = new ArrayList<String>();
|
||||
excludeTypes = new ArrayList<String>();
|
||||
excludeChars = new ArrayList<String>();
|
||||
itemTypes = new ArrayList<String>();
|
||||
generalSummary = new ArrayList<>();
|
||||
excludeWords = new ArrayList<>();
|
||||
excludeTypes = new ArrayList<>();
|
||||
excludeChars = new ArrayList<>();
|
||||
itemTypes = new ArrayList<>();
|
||||
|
||||
// set the parameters for this analysis
|
||||
setParameters(myLogDir, myFileTemplate, myConfigFile, myOutFile, myStartDate, myEndDate, myLookUp);
|
||||
@@ -529,10 +563,11 @@ public class LogAnalyser {
|
||||
|
||||
// for each search word add to the aggregator or
|
||||
// increment the aggregator's counter
|
||||
for (int j = 0; j < words.length; j++) {
|
||||
for (String word : words) {
|
||||
// FIXME: perhaps aggregators ought to be objects
|
||||
// themselves
|
||||
searchAggregator.put(words[j], increment(searchAggregator, words[j]));
|
||||
searchAggregator.put(word,
|
||||
increment(searchAggregator, word));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,13 +626,13 @@ public class LogAnalyser {
|
||||
}
|
||||
|
||||
// do the average views analysis
|
||||
if ((archiveStats.get("All Items")).intValue() != 0) {
|
||||
if ((archiveStats.get("All Items")) != 0) {
|
||||
// FIXME: this is dependent on their being a query on the db, which
|
||||
// there might not always be if it becomes configurable
|
||||
Double avg = Math.ceil(
|
||||
double avg = Math.ceil(
|
||||
(actionAggregator.get("view_item")).doubleValue() /
|
||||
(archiveStats.get("All Items")).doubleValue());
|
||||
views = avg.intValue();
|
||||
views = Math.round(avg);
|
||||
}
|
||||
|
||||
// finally, write the output
|
||||
@@ -672,55 +707,55 @@ public class LogAnalyser {
|
||||
Iterator<String> keys = null;
|
||||
|
||||
// output the number of lines parsed
|
||||
summary.append("log_lines=" + Integer.toString(lineCount) + "\n");
|
||||
summary.append("log_lines=").append(Integer.toString(lineCount)).append("\n");
|
||||
|
||||
// output the number of warnings encountered
|
||||
summary.append("warnings=" + Integer.toString(warnCount) + "\n");
|
||||
summary.append("exceptions=" + Integer.toString(excCount) + "\n");
|
||||
summary.append("warnings=").append(Integer.toString(warnCount)).append("\n");
|
||||
summary.append("exceptions=").append(Integer.toString(excCount)).append("\n");
|
||||
|
||||
// set the general summary config up in the aggregator file
|
||||
for (int i = 0; i < generalSummary.size(); i++) {
|
||||
summary.append("general_summary=" + generalSummary.get(i) + "\n");
|
||||
summary.append("general_summary=").append(generalSummary.get(i)).append("\n");
|
||||
}
|
||||
|
||||
// output the host name
|
||||
summary.append("server_name=" + hostName + "\n");
|
||||
summary.append("server_name=").append(hostName).append("\n");
|
||||
|
||||
// output the service name
|
||||
summary.append("service_name=" + name + "\n");
|
||||
summary.append("service_name=").append(name).append("\n");
|
||||
|
||||
// output the date information if necessary
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd'/'MM'/'yyyy");
|
||||
|
||||
if (startDate != null) {
|
||||
summary.append("start_date=" + sdf.format(startDate) + "\n");
|
||||
summary.append("start_date=").append(sdf.format(startDate)).append("\n");
|
||||
} else if (logStartDate != null) {
|
||||
summary.append("start_date=" + sdf.format(logStartDate) + "\n");
|
||||
summary.append("start_date=").append(sdf.format(logStartDate)).append("\n");
|
||||
}
|
||||
|
||||
if (endDate != null) {
|
||||
summary.append("end_date=" + sdf.format(endDate) + "\n");
|
||||
summary.append("end_date=").append(sdf.format(endDate)).append("\n");
|
||||
} else if (logEndDate != null) {
|
||||
summary.append("end_date=" + sdf.format(logEndDate) + "\n");
|
||||
summary.append("end_date=").append(sdf.format(logEndDate)).append("\n");
|
||||
}
|
||||
|
||||
// write out the archive stats
|
||||
keys = archiveStats.keySet().iterator();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
summary.append("archive." + key + "=" + archiveStats.get(key) + "\n");
|
||||
summary.append("archive.").append(key).append("=").append(archiveStats.get(key)).append("\n");
|
||||
}
|
||||
|
||||
// write out the action aggregation results
|
||||
keys = actionAggregator.keySet().iterator();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
summary.append("action." + key + "=" + actionAggregator.get(key) + "\n");
|
||||
summary.append("action.").append(key).append("=").append(actionAggregator.get(key)).append("\n");
|
||||
}
|
||||
|
||||
// depending on the config settings for reporting on emails output the
|
||||
// login information
|
||||
summary.append("user_email=" + userEmail + "\n");
|
||||
summary.append("user_email=").append(userEmail).append("\n");
|
||||
int address = 1;
|
||||
keys = userAggregator.keySet().iterator();
|
||||
|
||||
@@ -731,9 +766,10 @@ public class LogAnalyser {
|
||||
String key = keys.next();
|
||||
summary.append("user.");
|
||||
if (userEmail.equals("on")) {
|
||||
summary.append(key + "=" + userAggregator.get(key) + "\n");
|
||||
summary.append(key).append("=").append(userAggregator.get(key)).append("\n");
|
||||
} else if (userEmail.equals("alias")) {
|
||||
summary.append("Address " + Integer.toString(address++) + "=" + userAggregator.get(key) + "\n");
|
||||
summary.append("Address ").append(Integer.toString(address++))
|
||||
.append("=").append(userAggregator.get(key)).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -742,12 +778,13 @@ public class LogAnalyser {
|
||||
// the listing there are
|
||||
|
||||
// output the search word information
|
||||
summary.append("search_floor=" + searchFloor + "\n");
|
||||
summary.append("search_floor=").append(searchFloor).append("\n");
|
||||
keys = searchAggregator.keySet().iterator();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
if ((searchAggregator.get(key)).intValue() >= searchFloor) {
|
||||
summary.append("search." + key + "=" + searchAggregator.get(key) + "\n");
|
||||
if ((searchAggregator.get(key)) >= searchFloor) {
|
||||
summary.append("search.").append(key).append("=")
|
||||
.append(searchAggregator.get(key)).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,35 +796,35 @@ public class LogAnalyser {
|
||||
// be the same thing.
|
||||
|
||||
// item viewing information
|
||||
summary.append("item_floor=" + itemFloor + "\n");
|
||||
summary.append("host_url=" + url + "\n");
|
||||
summary.append("item_lookup=" + itemLookup + "\n");
|
||||
summary.append("item_floor=").append(itemFloor).append("\n");
|
||||
summary.append("host_url=").append(url).append("\n");
|
||||
summary.append("item_lookup=").append(itemLookup).append("\n");
|
||||
|
||||
// write out the item access information
|
||||
keys = itemAggregator.keySet().iterator();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
if ((itemAggregator.get(key)).intValue() >= itemFloor) {
|
||||
summary.append("item." + key + "=" + itemAggregator.get(key) + "\n");
|
||||
if ((itemAggregator.get(key)) >= itemFloor) {
|
||||
summary.append("item.").append(key).append("=")
|
||||
.append(itemAggregator.get(key)).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// output the average views per item
|
||||
if (views > 0) {
|
||||
summary.append("avg_item_views=" + views + "\n");
|
||||
summary.append("avg_item_views=").append(views).append("\n");
|
||||
}
|
||||
|
||||
// insert the analysis processing time information
|
||||
Calendar endTime = new GregorianCalendar();
|
||||
long timeInMillis = (endTime.getTimeInMillis() - startTime.getTimeInMillis());
|
||||
summary.append("analysis_process_time=" + Long.toString(timeInMillis / 1000) + "\n");
|
||||
summary.append("analysis_process_time=")
|
||||
.append(Long.toString(timeInMillis / 1000)).append("\n");
|
||||
|
||||
// finally write the string into the output file
|
||||
try {
|
||||
BufferedWriter out = new BufferedWriter(new FileWriter(outFile));
|
||||
try (BufferedWriter out = new BufferedWriter(new FileWriter(outFile));) {
|
||||
out.write(summary.toString());
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("Unable to write to output file " + outFile);
|
||||
System.exit(0);
|
||||
@@ -891,11 +928,11 @@ public class LogAnalyser {
|
||||
if (i > 0) {
|
||||
wordRXString.append("|");
|
||||
}
|
||||
wordRXString.append(" " + excludeWords.get(i) + " ");
|
||||
wordRXString.append(" ").append(excludeWords.get(i)).append(" ");
|
||||
wordRXString.append("|");
|
||||
wordRXString.append("^" + excludeWords.get(i) + " ");
|
||||
wordRXString.append("^").append(excludeWords.get(i)).append(" ");
|
||||
wordRXString.append("|");
|
||||
wordRXString.append(" " + excludeWords.get(i) + "$");
|
||||
wordRXString.append(" ").append(excludeWords.get(i)).append("$");
|
||||
}
|
||||
wordRXString.append(")");
|
||||
wordRX = Pattern.compile(wordRXString.toString());
|
||||
@@ -956,8 +993,8 @@ public class LogAnalyser {
|
||||
// read in the config file and set up our instance variables
|
||||
while ((record = br.readLine()) != null) {
|
||||
// check to see what kind of line we have
|
||||
Matcher matchComment = comment.matcher(record);
|
||||
Matcher matchReal = real.matcher(record);
|
||||
Matcher matchComment = COMMENT.matcher(record);
|
||||
Matcher matchReal = REAL.matcher(record);
|
||||
|
||||
// if the line is not a comment and is real, read it in
|
||||
if (!matchComment.matches() && matchReal.matches()) {
|
||||
@@ -968,7 +1005,7 @@ public class LogAnalyser {
|
||||
// read the config values into our instance variables (see
|
||||
// documentation for more info on config params)
|
||||
if (key.equals("general.summary")) {
|
||||
actionAggregator.put(value, Integer.valueOf(0));
|
||||
actionAggregator.put(value, 0);
|
||||
generalSummary.add(value);
|
||||
}
|
||||
|
||||
@@ -1022,9 +1059,9 @@ public class LogAnalyser {
|
||||
Integer newValue = null;
|
||||
if (map.containsKey(key)) {
|
||||
// FIXME: this seems like a ridiculous way to add Integers
|
||||
newValue = Integer.valueOf((map.get(key)).intValue() + 1);
|
||||
newValue = (map.get(key)) + 1;
|
||||
} else {
|
||||
newValue = Integer.valueOf(1);
|
||||
newValue = 1;
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
@@ -27,6 +27,10 @@ import java.util.StringTokenizer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataSchemaEnum;
|
||||
import org.dspace.content.MetadataValue;
|
||||
@@ -162,7 +166,7 @@ public class ReportGenerator {
|
||||
/**
|
||||
* pattern that matches an unqualified aggregator property
|
||||
*/
|
||||
private static final Pattern real = Pattern.compile("^(.+)=(.+)");
|
||||
private static final Pattern REAL = Pattern.compile("^(.+)=(.+)");
|
||||
|
||||
//////////////////////////
|
||||
// Miscellaneous variables
|
||||
@@ -221,28 +225,46 @@ public class ReportGenerator {
|
||||
String myOutput = null;
|
||||
String myMap = null;
|
||||
|
||||
// read in our command line options
|
||||
for (int i = 0; i < argv.length; i++) {
|
||||
if (argv[i].equals("-format")) {
|
||||
myFormat = argv[i + 1].toLowerCase();
|
||||
}
|
||||
Options options = new Options();
|
||||
Option option;
|
||||
|
||||
if (argv[i].equals("-in")) {
|
||||
myInput = argv[i + 1];
|
||||
}
|
||||
option = Option.builder().longOpt("format").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-out")) {
|
||||
myOutput = argv[i + 1];
|
||||
}
|
||||
option = Option.builder().longOpt("in").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-map")) {
|
||||
myMap = argv[i + 1];
|
||||
}
|
||||
option = Option.builder().longOpt("out").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
if (argv[i].equals("-help")) {
|
||||
usage();
|
||||
System.exit(0);
|
||||
}
|
||||
option = Option.builder().longOpt("map").hasArg().build();
|
||||
options.addOption(option);
|
||||
|
||||
option = Option.builder().longOpt("help").build();
|
||||
options.addOption(option);
|
||||
|
||||
DefaultParser parser = new DefaultParser();
|
||||
CommandLine cmd = parser.parse(options, argv);
|
||||
|
||||
if (cmd.hasOption("help")) {
|
||||
usage();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
if (cmd.hasOption("format")) {
|
||||
myFormat = cmd.getOptionValue("format");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("in")) {
|
||||
myInput = cmd.getOptionValue("in");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("out")) {
|
||||
myOutput = cmd.getOptionValue("out");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("map")) {
|
||||
myMap = cmd.getOptionValue("map");
|
||||
}
|
||||
|
||||
processReport(context, myFormat, myInput, myOutput, myMap);
|
||||
@@ -576,7 +598,7 @@ public class ReportGenerator {
|
||||
|
||||
// loop through the map file and read in the values
|
||||
while ((record = br.readLine()) != null) {
|
||||
Matcher matchReal = real.matcher(record);
|
||||
Matcher matchReal = REAL.matcher(record);
|
||||
|
||||
// if the line is real then read it in
|
||||
if (matchReal.matches()) {
|
||||
@@ -650,7 +672,7 @@ public class ReportGenerator {
|
||||
// loop through the aggregator file and read in the values
|
||||
while ((record = br.readLine()) != null) {
|
||||
// match real lines
|
||||
Matcher matchReal = real.matcher(record);
|
||||
Matcher matchReal = REAL.matcher(record);
|
||||
|
||||
// pre-prepare our input strings
|
||||
String section = null;
|
||||
|
@@ -324,11 +324,7 @@ public class StatisticsLoader {
|
||||
ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
File reportDir = new File(configurationService.getProperty("log.report.dir"));
|
||||
if (reportDir != null) {
|
||||
return reportDir.listFiles(new AnalysisAndReportFilter());
|
||||
}
|
||||
|
||||
return null;
|
||||
return reportDir.listFiles(new AnalysisAndReportFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.app.util;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.servicemanager.DSpaceKernelImpl;
|
||||
import org.dspace.servicemanager.DSpaceKernelInit;
|
||||
import org.dspace.services.CachingService;
|
||||
|
||||
/**
|
||||
* List all EhCache CacheManager and Cache instances.
|
||||
*
|
||||
* <p>This is a debugging tool, not used in the daily operation of DSpace.
|
||||
* Just run it from the installed instance using
|
||||
* {@code bin/dspace dsrun org.dspace.app.util.CacheSnooper}
|
||||
* to check that the cache configuration is what you expect it to be,
|
||||
* given your configuration.
|
||||
*
|
||||
* <p>This was created to prove a specific cache configuration patch,
|
||||
* but I leave it here in the hope that it may be useful to others.
|
||||
*
|
||||
* @author Mark H. Wood <mwood@iupui.edu>
|
||||
*/
|
||||
public class CacheSnooper {
|
||||
private CacheSnooper() { }
|
||||
|
||||
public static void main(String[] argv) {
|
||||
// Ensure that the DSpace kernel is started.
|
||||
DSpaceKernelImpl kernel = DSpaceKernelInit.getKernel(null);
|
||||
|
||||
// Ensure that the services cache manager is started.
|
||||
CachingService serviceCaches = kernel.getServiceManager()
|
||||
.getServiceByName(null, CachingService.class);
|
||||
|
||||
// Ensure that the database layer is started.
|
||||
Context ctx = new Context();
|
||||
|
||||
// List those caches!
|
||||
for (CacheManager manager : CacheManager.ALL_CACHE_MANAGERS) {
|
||||
System.out.format("CacheManager: %s%n", manager);
|
||||
for (String cacheName : manager.getCacheNames()) {
|
||||
Cache cache = manager.getCache(cacheName);
|
||||
System.out.format(" Cache: '%s'; maxHeap: %d; maxDisk: %d%n",
|
||||
cacheName,
|
||||
cache.getCacheConfiguration().getMaxEntriesLocalHeap(),
|
||||
cache.getCacheConfiguration().getMaxEntriesLocalDisk());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -37,6 +37,7 @@ public class Configuration {
|
||||
* <li>{@code --property name} prints the value of the DSpace configuration
|
||||
* property {@code name} to the standard output.</li>
|
||||
* <li>{@code --raw} suppresses parameter substitution in the output.</li>
|
||||
* <li>{@code --first} print only the first of multiple values.</li>
|
||||
* <li>{@code --help} describes these options.</li>
|
||||
* </ul>
|
||||
* If the property does not exist, nothing is written.
|
||||
@@ -51,6 +52,8 @@ public class Configuration {
|
||||
"optional name of the module in which 'property' exists");
|
||||
options.addOption("r", "raw", false,
|
||||
"do not do property substitution on the value");
|
||||
options.addOption("f", "first", false,
|
||||
"display only the first value of an array property");
|
||||
options.addOption("?", "Get help");
|
||||
options.addOption("h", "help", false, "Get help");
|
||||
|
||||
@@ -90,19 +93,36 @@ public class Configuration {
|
||||
propNameBuilder.append(cmd.getOptionValue('p'));
|
||||
String propName = propNameBuilder.toString();
|
||||
|
||||
// Print the property's value, if it exists
|
||||
// Print the property's value(s), if it exists
|
||||
ConfigurationService cfg = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
if (!cfg.hasProperty(propName)) {
|
||||
System.out.println();
|
||||
} else {
|
||||
String val;
|
||||
if (cmd.hasOption('r')) {
|
||||
val = cfg.getPropertyValue(propName).toString();
|
||||
// Print "raw" values (without property substitutions)
|
||||
Object rawValue = cfg.getPropertyValue(propName);
|
||||
if (rawValue.getClass().isArray()) {
|
||||
for (Object value : (Object[]) rawValue) {
|
||||
System.out.println(value.toString());
|
||||
if (cmd.hasOption('f')) {
|
||||
break; // If --first print only one value
|
||||
}
|
||||
}
|
||||
} else { // Not an array
|
||||
System.out.println(rawValue.toString());
|
||||
}
|
||||
} else {
|
||||
val = cfg.getProperty(propName);
|
||||
// Print values with property substitutions
|
||||
String[] values = cfg.getArrayProperty(propName);
|
||||
for (String value : values) {
|
||||
System.out.println(value);
|
||||
if (cmd.hasOption('f')) {
|
||||
break; // If --first print only one value
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(val);
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
@@ -144,8 +144,8 @@ public class DCInput {
|
||||
private boolean isMetadataField = false;
|
||||
private String relationshipType = null;
|
||||
private String searchConfiguration = null;
|
||||
private String filter;
|
||||
private List<String> externalSources;
|
||||
private final String filter;
|
||||
private final List<String> externalSources;
|
||||
|
||||
/**
|
||||
* The scope of the input sets, this restricts hidden metadata fields from
|
||||
@@ -213,7 +213,7 @@ public class DCInput {
|
||||
|| "yes".equalsIgnoreCase(closedVocabularyStr);
|
||||
|
||||
// parsing of the <type-bind> element (using the colon as split separator)
|
||||
typeBind = new ArrayList<String>();
|
||||
typeBind = new ArrayList<>();
|
||||
String typeBindDef = fieldMap.get("type-bind");
|
||||
if (typeBindDef != null && typeBindDef.trim().length() > 0) {
|
||||
String[] types = typeBindDef.split(",");
|
||||
@@ -553,7 +553,7 @@ public class DCInput {
|
||||
}
|
||||
}
|
||||
} catch (PatternSyntaxException ex) {
|
||||
log.error("Regex validation failed!", ex.getMessage());
|
||||
log.error("Regex validation failed! {}", ex.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -562,18 +562,31 @@ public class DCInput {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify whether the current field contains an entity relationship
|
||||
* This also implies a relationship type is defined for this field
|
||||
* The field can contain both an entity relationship and a metadata field simultaneously
|
||||
* Get the type bind list for use in determining whether
|
||||
* to display this field in angular dynamic form building
|
||||
* @return list of bound types
|
||||
*/
|
||||
public List<String> getTypeBindList() {
|
||||
return typeBind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify whether the current field contains an entity relationship.
|
||||
* This also implies a relationship type is defined for this field.
|
||||
* The field can contain both an entity relationship and a metadata field
|
||||
* simultaneously.
|
||||
* @return true if the field contains a relationship.
|
||||
*/
|
||||
public boolean isRelationshipField() {
|
||||
return isRelationshipField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify whether the current field contains a metadata field
|
||||
* This also implies a field type is defined for this field
|
||||
* The field can contain both an entity relationship and a metadata field simultaneously
|
||||
* Verify whether the current field contains a metadata field.
|
||||
* This also implies a field type is defined for this field.
|
||||
* The field can contain both an entity relationship and a metadata field
|
||||
* simultaneously.
|
||||
* @return true if the field contains a metadata field.
|
||||
*/
|
||||
public boolean isMetadataField() {
|
||||
return isMetadataField;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -16,7 +17,6 @@ import org.dspace.core.Utils;
|
||||
* Class representing all DC inputs required for a submission, organized into pages
|
||||
*
|
||||
* @author Brian S. Hughes, based on work by Jenny Toves, OCLC
|
||||
* @version $Revision$
|
||||
*/
|
||||
|
||||
public class DCInputSet {
|
||||
@@ -33,7 +33,6 @@ public class DCInputSet {
|
||||
* constructor
|
||||
*
|
||||
* @param formName form name
|
||||
* @param mandatoryFlags
|
||||
* @param rows the rows
|
||||
* @param listMap map
|
||||
*/
|
||||
@@ -176,4 +175,50 @@ public class DCInputSet {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate DC input rows and populate a list of all allowed field names in this submission configuration.
|
||||
* This is important because an input can be configured repeatedly in a form (for example it could be required
|
||||
* for type Book, and allowed but not required for type Article).
|
||||
* If the field is allowed for this document type it'll never be stripped from metadata on validation.
|
||||
*
|
||||
* This can be more efficient than isFieldPresent to avoid looping the input set with each check.
|
||||
*
|
||||
* @param documentTypeValue Document type eg. Article, Book
|
||||
* @return ArrayList of field names to use in validation
|
||||
*/
|
||||
public List<String> populateAllowedFieldNames(String documentTypeValue) {
|
||||
List<String> allowedFieldNames = new ArrayList<>();
|
||||
// Before iterating each input for validation, run through all inputs + fields and populate a lookup
|
||||
// map with inputs for this type. Because an input can be configured repeatedly in a form (for example
|
||||
// it could be required for type Book, and allowed but not required for type Article), allowed=true will
|
||||
// always take precedence
|
||||
for (DCInput[] row : inputs) {
|
||||
for (DCInput input : row) {
|
||||
if (input.isQualdropValue()) {
|
||||
List<Object> inputPairs = input.getPairs();
|
||||
//starting from the second element of the list and skipping one every time because the display
|
||||
// values are also in the list and before the stored values.
|
||||
for (int i = 1; i < inputPairs.size(); i += 2) {
|
||||
String fullFieldname = input.getFieldName() + "." + inputPairs.get(i);
|
||||
if (input.isAllowedFor(documentTypeValue)) {
|
||||
if (!allowedFieldNames.contains(fullFieldname)) {
|
||||
allowedFieldNames.add(fullFieldname);
|
||||
}
|
||||
// For the purposes of qualdrop, we have to add the field name without the qualifier
|
||||
// too, or a required qualdrop will get confused and incorrectly reject a value
|
||||
if (!allowedFieldNames.contains(input.getFieldName())) {
|
||||
allowedFieldNames.add(input.getFieldName());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (input.isAllowedFor(documentTypeValue) && !allowedFieldNames.contains(input.getFieldName())) {
|
||||
allowedFieldNames.add(input.getFieldName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return allowedFieldNames;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -86,8 +86,10 @@ public class GoogleBitstreamComparator implements Comparator<Bitstream> {
|
||||
if (priority1 > priority2) {
|
||||
return 1;
|
||||
} else if (priority1 == priority2) {
|
||||
if (b1.getSizeBytes() <= b2.getSizeBytes()) {
|
||||
if (b1.getSizeBytes() < b2.getSizeBytes()) {
|
||||
return 1;
|
||||
} else if (b1.getSizeBytes() == b2.getSizeBytes()) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
@@ -42,7 +42,7 @@ import org.dspace.core.Context;
|
||||
import org.dspace.handle.factory.HandleServiceFactory;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.jdom.Element;
|
||||
import org.jdom2.Element;
|
||||
|
||||
/**
|
||||
* Configuration and mapping for Google Scholar output metadata
|
||||
@@ -470,11 +470,7 @@ public class GoogleMetadata {
|
||||
parsedOptions.add(parsedFields);
|
||||
}
|
||||
|
||||
if (null != parsedOptions) {
|
||||
return parsedOptions;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return parsedOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -16,10 +16,10 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.syndication.feed.module.opensearch.OpenSearchModule;
|
||||
import com.sun.syndication.feed.module.opensearch.entity.OSQuery;
|
||||
import com.sun.syndication.feed.module.opensearch.impl.OpenSearchModuleImpl;
|
||||
import com.sun.syndication.io.FeedException;
|
||||
import com.rometools.modules.opensearch.OpenSearchModule;
|
||||
import com.rometools.modules.opensearch.entity.OSQuery;
|
||||
import com.rometools.modules.opensearch.impl.OpenSearchModuleImpl;
|
||||
import com.rometools.rome.io.FeedException;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.service.OpenSearchService;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
@@ -29,11 +29,11 @@ import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.handle.service.HandleService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jdom.Namespace;
|
||||
import org.jdom.output.DOMOutputter;
|
||||
import org.jdom.output.XMLOutputter;
|
||||
import org.jdom2.Element;
|
||||
import org.jdom2.JDOMException;
|
||||
import org.jdom2.Namespace;
|
||||
import org.jdom2.output.DOMOutputter;
|
||||
import org.jdom2.output.XMLOutputter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
@@ -192,7 +192,7 @@ public class OpenSearchServiceImpl implements OpenSearchService {
|
||||
* @param scope - null for the entire repository, or a collection/community handle
|
||||
* @return Service Document
|
||||
*/
|
||||
protected org.jdom.Document getServiceDocument(String scope) {
|
||||
protected org.jdom2.Document getServiceDocument(String scope) {
|
||||
ConfigurationService config = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
|
||||
Namespace ns = Namespace.getNamespace(osNs);
|
||||
@@ -245,7 +245,7 @@ public class OpenSearchServiceImpl implements OpenSearchService {
|
||||
url.setAttribute("template", template.toString());
|
||||
root.addContent(url);
|
||||
}
|
||||
return new org.jdom.Document(root);
|
||||
return new org.jdom2.Document(root);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,7 +255,7 @@ public class OpenSearchServiceImpl implements OpenSearchService {
|
||||
* @return W3C Document object
|
||||
* @throws IOException if IO error
|
||||
*/
|
||||
protected Document jDomToW3(org.jdom.Document jdomDoc) throws IOException {
|
||||
protected Document jDomToW3(org.jdom2.Document jdomDoc) throws IOException {
|
||||
DOMOutputter domOut = new DOMOutputter();
|
||||
try {
|
||||
return domOut.output(jdomDoc);
|
||||
|
@@ -11,7 +11,6 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
@@ -23,12 +22,12 @@ import org.dspace.eperson.service.EPersonService;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
/**
|
||||
* A command line tool to verify/test the accuracy and speed gains of
|
||||
* {@link Collection.findAuthorizedOptimized}.
|
||||
* Invocation: {@code dsrun org.dspace.app.util.OptimizeSelectCollection}
|
||||
* @author peterdietz
|
||||
* A command line tool to verify/test the accuracy and speed gains of Collection.findAuthorizedOptimized()
|
||||
* Invocation: dsrun org.dspace.app.util.OptimizeSelectCollection
|
||||
*/
|
||||
public class OptimizeSelectCollection {
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(OptimizeSelectCollection.class);
|
||||
private static Context context;
|
||||
|
||||
private static ArrayList<EPerson> brokenPeople;
|
||||
@@ -49,7 +48,7 @@ public class OptimizeSelectCollection {
|
||||
"values as the legacy select-collection logic.");
|
||||
|
||||
context = new Context();
|
||||
brokenPeople = new ArrayList<EPerson>();
|
||||
brokenPeople = new ArrayList<>();
|
||||
int peopleChecked = 0;
|
||||
timeSavedMS = 0L;
|
||||
|
||||
@@ -68,7 +67,7 @@ public class OptimizeSelectCollection {
|
||||
}
|
||||
}
|
||||
|
||||
if (brokenPeople.size() > 0) {
|
||||
if (!brokenPeople.isEmpty()) {
|
||||
System.out.println("NOT DONE YET!!! Some people don't have all their collections.");
|
||||
for (EPerson person : brokenPeople) {
|
||||
System.out.println("-- " + person.getEmail());
|
||||
@@ -90,7 +89,7 @@ public class OptimizeSelectCollection {
|
||||
stopWatch.start("findAuthorized");
|
||||
List<Collection> collections = collectionService.findAuthorized(context, null, Constants.ADD);
|
||||
stopWatch.stop();
|
||||
Long defaultMS = stopWatch.getLastTaskTimeMillis();
|
||||
long defaultMS = stopWatch.getLastTaskTimeMillis();
|
||||
|
||||
stopWatch.start("ListingCollections");
|
||||
System.out.println("Legacy Find Authorized");
|
||||
@@ -100,7 +99,7 @@ public class OptimizeSelectCollection {
|
||||
stopWatch.start("findAuthorizedOptimized");
|
||||
List<Collection> collectionsOptimized = collectionService.findAuthorizedOptimized(context, Constants.ADD);
|
||||
stopWatch.stop();
|
||||
Long optimizedMS = stopWatch.getLastTaskTimeMillis();
|
||||
long optimizedMS = stopWatch.getLastTaskTimeMillis();
|
||||
timeSavedMS += defaultMS - optimizedMS;
|
||||
|
||||
|
||||
|
@@ -15,26 +15,26 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.sun.syndication.feed.module.DCModule;
|
||||
import com.sun.syndication.feed.module.DCModuleImpl;
|
||||
import com.sun.syndication.feed.module.Module;
|
||||
import com.sun.syndication.feed.module.itunes.EntryInformation;
|
||||
import com.sun.syndication.feed.module.itunes.EntryInformationImpl;
|
||||
import com.sun.syndication.feed.module.itunes.types.Duration;
|
||||
import com.sun.syndication.feed.synd.SyndContent;
|
||||
import com.sun.syndication.feed.synd.SyndContentImpl;
|
||||
import com.sun.syndication.feed.synd.SyndEnclosure;
|
||||
import com.sun.syndication.feed.synd.SyndEnclosureImpl;
|
||||
import com.sun.syndication.feed.synd.SyndEntry;
|
||||
import com.sun.syndication.feed.synd.SyndEntryImpl;
|
||||
import com.sun.syndication.feed.synd.SyndFeed;
|
||||
import com.sun.syndication.feed.synd.SyndFeedImpl;
|
||||
import com.sun.syndication.feed.synd.SyndImage;
|
||||
import com.sun.syndication.feed.synd.SyndImageImpl;
|
||||
import com.sun.syndication.feed.synd.SyndPerson;
|
||||
import com.sun.syndication.feed.synd.SyndPersonImpl;
|
||||
import com.sun.syndication.io.FeedException;
|
||||
import com.sun.syndication.io.SyndFeedOutput;
|
||||
import com.rometools.modules.itunes.EntryInformation;
|
||||
import com.rometools.modules.itunes.EntryInformationImpl;
|
||||
import com.rometools.modules.itunes.types.Duration;
|
||||
import com.rometools.rome.feed.module.DCModule;
|
||||
import com.rometools.rome.feed.module.DCModuleImpl;
|
||||
import com.rometools.rome.feed.module.Module;
|
||||
import com.rometools.rome.feed.synd.SyndContent;
|
||||
import com.rometools.rome.feed.synd.SyndContentImpl;
|
||||
import com.rometools.rome.feed.synd.SyndEnclosure;
|
||||
import com.rometools.rome.feed.synd.SyndEnclosureImpl;
|
||||
import com.rometools.rome.feed.synd.SyndEntry;
|
||||
import com.rometools.rome.feed.synd.SyndEntryImpl;
|
||||
import com.rometools.rome.feed.synd.SyndFeed;
|
||||
import com.rometools.rome.feed.synd.SyndFeedImpl;
|
||||
import com.rometools.rome.feed.synd.SyndImage;
|
||||
import com.rometools.rome.feed.synd.SyndImageImpl;
|
||||
import com.rometools.rome.feed.synd.SyndPerson;
|
||||
import com.rometools.rome.feed.synd.SyndPersonImpl;
|
||||
import com.rometools.rome.io.FeedException;
|
||||
import com.rometools.rome.io.SyndFeedOutput;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -193,13 +193,11 @@ public class SyndicationFeed {
|
||||
String defaultTitle = null;
|
||||
boolean podcastFeed = false;
|
||||
this.request = request;
|
||||
|
||||
// dso is null for the whole site, or a search without scope
|
||||
if (dso == null) {
|
||||
defaultTitle = configurationService.getProperty("dspace.name");
|
||||
feed.setDescription(localize(labels, MSG_FEED_DESCRIPTION));
|
||||
objectURL = resolveURL(request, null);
|
||||
logoURL = configurationService.getProperty("webui.feed.logo.url");
|
||||
} else {
|
||||
Bitstream logo = null;
|
||||
if (dso instanceof IndexableCollection) {
|
||||
@@ -329,7 +327,8 @@ public class SyndicationFeed {
|
||||
dcDescriptionField != null) {
|
||||
DCModule dc = new DCModuleImpl();
|
||||
if (dcCreatorField != null) {
|
||||
List<MetadataValue> dcAuthors = itemService.getMetadataByMetadataString(item, dcCreatorField);
|
||||
List<MetadataValue> dcAuthors = itemService
|
||||
.getMetadataByMetadataString(item, dcCreatorField);
|
||||
if (dcAuthors.size() > 0) {
|
||||
List<String> creators = new ArrayList<>();
|
||||
for (MetadataValue author : dcAuthors) {
|
||||
@@ -345,7 +344,8 @@ public class SyndicationFeed {
|
||||
}
|
||||
}
|
||||
if (dcDescriptionField != null) {
|
||||
List<MetadataValue> v = itemService.getMetadataByMetadataString(item, dcDescriptionField);
|
||||
List<MetadataValue> v = itemService
|
||||
.getMetadataByMetadataString(item, dcDescriptionField);
|
||||
if (v.size() > 0) {
|
||||
StringBuilder descs = new StringBuilder();
|
||||
for (MetadataValue d : v) {
|
||||
@@ -376,6 +376,7 @@ public class SyndicationFeed {
|
||||
enc.setLength(bit.getSizeBytes());
|
||||
enc.setUrl(urlOfBitstream(request, bit));
|
||||
enclosures.add(enc);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,7 +420,7 @@ public class SyndicationFeed {
|
||||
// with length of song in seconds
|
||||
if (extent != null && extent.length() > 0) {
|
||||
extent = extent.split(" ")[0];
|
||||
Integer duration = Integer.parseInt(extent);
|
||||
long duration = Long.parseLong(extent);
|
||||
itunes.setDuration(new Duration(duration)); // <itunes:duration>
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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.sql.SQLException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.authenticate.factory.AuthenticateServiceFactory;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.kernel.ServiceManager;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AuthenticationMethod} that delegate all the method
|
||||
* invocations to the bean of class {@link OrcidAuthenticationBean}.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class OrcidAuthentication implements AuthenticationMethod {
|
||||
|
||||
private final ServiceManager serviceManager = new DSpace().getServiceManager();
|
||||
|
||||
/**
|
||||
* Check if OrcidAuthentication plugin is enabled
|
||||
* @return true if enabled, false otherwise
|
||||
*/
|
||||
public static boolean isEnabled() {
|
||||
|
||||
String pluginName = new OrcidAuthentication().getName();
|
||||
|
||||
Iterator<AuthenticationMethod> authenticationMethodIterator = AuthenticateServiceFactory.getInstance()
|
||||
.getAuthenticationService().authenticationMethodIterator();
|
||||
|
||||
while (authenticationMethodIterator.hasNext()) {
|
||||
if (pluginName.equals(authenticationMethodIterator.next().getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSelfRegister(Context context, HttpServletRequest request, String username) throws SQLException {
|
||||
return getOrcidAuthentication().canSelfRegister(context, request, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initEPerson(Context context, HttpServletRequest request, EPerson eperson) throws SQLException {
|
||||
getOrcidAuthentication().initEPerson(context, request, eperson);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowSetPassword(Context context, HttpServletRequest request, String username) throws SQLException {
|
||||
return getOrcidAuthentication().allowSetPassword(context, request, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImplicit() {
|
||||
return getOrcidAuthentication().isImplicit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> getSpecialGroups(Context context, HttpServletRequest request) throws SQLException {
|
||||
return getOrcidAuthentication().getSpecialGroups(context, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int authenticate(Context context, String username, String password, String realm, HttpServletRequest request)
|
||||
throws SQLException {
|
||||
return getOrcidAuthentication().authenticate(context, username, password, realm, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loginPageURL(Context context, HttpServletRequest request, HttpServletResponse response) {
|
||||
return getOrcidAuthentication().loginPageURL(context, request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getOrcidAuthentication().getName();
|
||||
}
|
||||
|
||||
private OrcidAuthenticationBean getOrcidAuthentication() {
|
||||
return serviceManager.getServiceByName("orcidAuthentication", OrcidAuthenticationBean.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsed(Context context, HttpServletRequest request) {
|
||||
return getOrcidAuthentication().isUsed(context, request);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,330 @@
|
||||
/**
|
||||
* 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 static java.lang.String.format;
|
||||
import static java.net.URLEncoder.encode;
|
||||
import static org.apache.commons.lang.BooleanUtils.toBoolean;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.dspace.content.Item.ANY;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.orcid.OrcidToken;
|
||||
import org.dspace.orcid.client.OrcidClient;
|
||||
import org.dspace.orcid.client.OrcidConfiguration;
|
||||
import org.dspace.orcid.model.OrcidTokenResponseDTO;
|
||||
import org.dspace.orcid.service.OrcidSynchronizationService;
|
||||
import org.dspace.orcid.service.OrcidTokenService;
|
||||
import org.dspace.profile.ResearcherProfile;
|
||||
import org.dspace.profile.service.ResearcherProfileService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.orcid.jaxb.model.v3.release.record.Email;
|
||||
import org.orcid.jaxb.model.v3.release.record.Person;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* ORCID authentication for DSpace.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class OrcidAuthenticationBean implements AuthenticationMethod {
|
||||
|
||||
public static final String ORCID_AUTH_ATTRIBUTE = "orcid-authentication";
|
||||
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(OrcidAuthenticationBean.class);
|
||||
|
||||
private final static String LOGIN_PAGE_URL_FORMAT = "%s?client_id=%s&response_type=code&scope=%s&redirect_uri=%s";
|
||||
|
||||
@Autowired
|
||||
private OrcidClient orcidClient;
|
||||
|
||||
@Autowired
|
||||
private OrcidConfiguration orcidConfiguration;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Autowired
|
||||
private EPersonService ePersonService;
|
||||
|
||||
@Autowired
|
||||
private ResearcherProfileService researcherProfileService;
|
||||
|
||||
@Autowired
|
||||
private OrcidSynchronizationService orcidSynchronizationService;
|
||||
|
||||
@Autowired
|
||||
private OrcidTokenService orcidTokenService;
|
||||
|
||||
@Override
|
||||
public int authenticate(Context context, String username, String password, String realm, HttpServletRequest request)
|
||||
throws SQLException {
|
||||
|
||||
if (request == null) {
|
||||
LOGGER.warn("Unable to authenticate using ORCID because the request object is null.");
|
||||
return BAD_ARGS;
|
||||
}
|
||||
|
||||
String code = (String) request.getParameter("code");
|
||||
if (StringUtils.isEmpty(code)) {
|
||||
LOGGER.warn("The incoming request has not code parameter");
|
||||
return NO_SUCH_USER;
|
||||
}
|
||||
request.setAttribute(ORCID_AUTH_ATTRIBUTE, true);
|
||||
return authenticateWithOrcid(context, code, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loginPageURL(Context context, HttpServletRequest request, HttpServletResponse response) {
|
||||
|
||||
String authorizeUrl = orcidConfiguration.getAuthorizeEndpointUrl();
|
||||
String clientId = orcidConfiguration.getClientId();
|
||||
String redirectUri = orcidConfiguration.getRedirectUrl();
|
||||
String scopes = String.join("+", orcidConfiguration.getScopes());
|
||||
|
||||
if (StringUtils.isAnyBlank(authorizeUrl, clientId, redirectUri, scopes)) {
|
||||
LOGGER.error("Missing mandatory configuration properties for OrcidAuthentication");
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
return format(LOGIN_PAGE_URL_FORMAT, authorizeUrl, clientId, scopes, encode(redirectUri, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsed(Context context, HttpServletRequest request) {
|
||||
return request.getAttribute(ORCID_AUTH_ATTRIBUTE) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSelfRegister(Context context, HttpServletRequest request, String username) throws SQLException {
|
||||
return canSelfRegister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initEPerson(Context context, HttpServletRequest request, EPerson eperson) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowSetPassword(Context context, HttpServletRequest request, String username) throws SQLException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImplicit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> getSpecialGroups(Context context, HttpServletRequest request) throws SQLException {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "orcid";
|
||||
}
|
||||
|
||||
private int authenticateWithOrcid(Context context, String code, HttpServletRequest request) throws SQLException {
|
||||
OrcidTokenResponseDTO token = getOrcidAccessToken(code);
|
||||
if (token == null) {
|
||||
return NO_SUCH_USER;
|
||||
}
|
||||
|
||||
String orcid = token.getOrcid();
|
||||
|
||||
EPerson ePerson = ePersonService.findByNetid(context, orcid);
|
||||
if (ePerson != null) {
|
||||
return ePerson.canLogIn() ? logInEPerson(context, token, ePerson) : BAD_ARGS;
|
||||
}
|
||||
|
||||
Person person = getPersonFromOrcid(token);
|
||||
if (person == null) {
|
||||
return NO_SUCH_USER;
|
||||
}
|
||||
|
||||
String email = getEmail(person).orElse(null);
|
||||
|
||||
ePerson = ePersonService.findByEmail(context, email);
|
||||
if (ePerson != null) {
|
||||
return ePerson.canLogIn() ? logInEPerson(context, token, ePerson) : BAD_ARGS;
|
||||
}
|
||||
|
||||
return canSelfRegister() ? registerNewEPerson(context, person, token) : NO_SUCH_USER;
|
||||
|
||||
}
|
||||
|
||||
private int logInEPerson(Context context, OrcidTokenResponseDTO token, EPerson ePerson)
|
||||
throws SQLException {
|
||||
|
||||
context.setCurrentUser(ePerson);
|
||||
|
||||
setOrcidMetadataOnEPerson(context, ePerson, token);
|
||||
|
||||
ResearcherProfile profile = findProfile(context, ePerson);
|
||||
if (profile != null) {
|
||||
orcidSynchronizationService.linkProfile(context, profile.getItem(), token);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
private ResearcherProfile findProfile(Context context, EPerson ePerson) throws SQLException {
|
||||
try {
|
||||
return researcherProfileService.findById(context, ePerson.getID());
|
||||
} catch (AuthorizeException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private int registerNewEPerson(Context context, Person person, OrcidTokenResponseDTO token) throws SQLException {
|
||||
|
||||
try {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
String email = getEmail(person)
|
||||
.orElseThrow(() -> new IllegalStateException("The email is configured private on orcid"));
|
||||
|
||||
String orcid = token.getOrcid();
|
||||
|
||||
EPerson eperson = ePersonService.create(context);
|
||||
|
||||
eperson.setNetid(orcid);
|
||||
|
||||
eperson.setEmail(email);
|
||||
|
||||
Optional<String> firstName = getFirstName(person);
|
||||
if (firstName.isPresent()) {
|
||||
eperson.setFirstName(context, firstName.get());
|
||||
}
|
||||
|
||||
Optional<String> lastName = getLastName(person);
|
||||
if (lastName.isPresent()) {
|
||||
eperson.setLastName(context, lastName.get());
|
||||
}
|
||||
eperson.setCanLogIn(true);
|
||||
eperson.setSelfRegistered(true);
|
||||
|
||||
setOrcidMetadataOnEPerson(context, eperson, token);
|
||||
|
||||
ePersonService.update(context, eperson);
|
||||
context.setCurrentUser(eperson);
|
||||
context.dispatchEvents();
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("An error occurs registering a new EPerson from ORCID", ex);
|
||||
context.rollback();
|
||||
return NO_SUCH_USER;
|
||||
} finally {
|
||||
context.restoreAuthSystemState();
|
||||
}
|
||||
}
|
||||
|
||||
private void setOrcidMetadataOnEPerson(Context context, EPerson person, OrcidTokenResponseDTO token)
|
||||
throws SQLException {
|
||||
|
||||
String orcid = token.getOrcid();
|
||||
String accessToken = token.getAccessToken();
|
||||
String[] scopes = token.getScopeAsArray();
|
||||
|
||||
ePersonService.setMetadataSingleValue(context, person, "eperson", "orcid", null, null, orcid);
|
||||
ePersonService.clearMetadata(context, person, "eperson", "orcid", "scope", ANY);
|
||||
for (String scope : scopes) {
|
||||
ePersonService.addMetadata(context, person, "eperson", "orcid", "scope", null, scope);
|
||||
}
|
||||
|
||||
OrcidToken orcidToken = orcidTokenService.findByEPerson(context, person);
|
||||
if (orcidToken == null) {
|
||||
orcidTokenService.create(context, person, accessToken);
|
||||
} else {
|
||||
orcidToken.setAccessToken(accessToken);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Person getPersonFromOrcid(OrcidTokenResponseDTO token) {
|
||||
try {
|
||||
return orcidClient.getPerson(token.getAccessToken(), token.getOrcid());
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("An error occurs retriving the ORCID record with id " + token.getOrcid(), ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<String> getEmail(Person person) {
|
||||
List<Email> emails = person.getEmails() != null ? person.getEmails().getEmails() : Collections.emptyList();
|
||||
if (CollectionUtils.isEmpty(emails)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.ofNullable(emails.get(0).getEmail());
|
||||
}
|
||||
|
||||
private Optional<String> getFirstName(Person person) {
|
||||
return Optional.ofNullable(person.getName())
|
||||
.map(name -> name.getGivenNames())
|
||||
.map(givenNames -> givenNames.getContent());
|
||||
}
|
||||
|
||||
private Optional<String> getLastName(Person person) {
|
||||
return Optional.ofNullable(person.getName())
|
||||
.map(name -> name.getFamilyName())
|
||||
.map(givenNames -> givenNames.getContent());
|
||||
}
|
||||
|
||||
private boolean canSelfRegister() {
|
||||
String canSelfRegister = configurationService.getProperty("authentication-orcid.can-self-register", "true");
|
||||
if (isBlank(canSelfRegister)) {
|
||||
return true;
|
||||
}
|
||||
return toBoolean(canSelfRegister);
|
||||
}
|
||||
|
||||
private OrcidTokenResponseDTO getOrcidAccessToken(String code) {
|
||||
try {
|
||||
return orcidClient.getAccessToken(code);
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("An error occurs retriving the ORCID access_token", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public OrcidClient getOrcidClient() {
|
||||
return orcidClient;
|
||||
}
|
||||
|
||||
public void setOrcidClient(OrcidClient orcidClient) {
|
||||
this.orcidClient = orcidClient;
|
||||
}
|
||||
|
||||
}
|
@@ -20,7 +20,6 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -290,20 +289,13 @@ public class ShibAuthentication implements AuthenticationMethod {
|
||||
try {
|
||||
// User has not successfuly authenticated via shibboleth.
|
||||
if (request == null ||
|
||||
context.getCurrentUser() == null ||
|
||||
request.getSession().getAttribute("shib.authenticated") == null) {
|
||||
context.getCurrentUser() == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
// If we have already calculated the special groups then return them.
|
||||
if (request.getSession().getAttribute("shib.specialgroup") != null) {
|
||||
if (context.getSpecialGroups().size() > 0 ) {
|
||||
log.debug("Returning cached special groups.");
|
||||
List<UUID> sessionGroupIds = (List<UUID>) request.getSession().getAttribute("shib.specialgroup");
|
||||
List<Group> result = new ArrayList<>();
|
||||
for (UUID uuid : sessionGroupIds) {
|
||||
result.add(groupService.find(context, uuid));
|
||||
}
|
||||
return result;
|
||||
return context.getSpecialGroups();
|
||||
}
|
||||
|
||||
log.debug("Starting to determine special groups");
|
||||
@@ -396,16 +388,8 @@ public class ShibAuthentication implements AuthenticationMethod {
|
||||
|
||||
log.info("Added current EPerson to special groups: " + groups);
|
||||
|
||||
List<UUID> groupIds = new ArrayList<>();
|
||||
for (Group group : groups) {
|
||||
groupIds.add(group.getID());
|
||||
}
|
||||
|
||||
// Cache the special groups, so we don't have to recalculate them again
|
||||
// for this session.
|
||||
request.setAttribute("shib.specialgroup", groupIds);
|
||||
|
||||
return new ArrayList<>(groups);
|
||||
|
||||
} catch (Throwable t) {
|
||||
log.error("Unable to validate any sepcial groups this user may belong too because of an exception.", t);
|
||||
return Collections.EMPTY_LIST;
|
||||
|
@@ -50,7 +50,7 @@ public class AuthoritySolrServiceImpl implements AuthorityIndexingService, Autho
|
||||
*/
|
||||
protected SolrClient solr = null;
|
||||
|
||||
protected SolrClient getSolr()
|
||||
public SolrClient getSolr()
|
||||
throws MalformedURLException, SolrServerException, IOException {
|
||||
if (solr == null) {
|
||||
|
||||
@@ -67,7 +67,11 @@ public class AuthoritySolrServiceImpl implements AuthorityIndexingService, Autho
|
||||
|
||||
SolrQuery solrQuery = new SolrQuery().setQuery("*:*");
|
||||
|
||||
solrServer.query(solrQuery);
|
||||
try {
|
||||
solrServer.query(solrQuery);
|
||||
} catch (Exception ex) {
|
||||
log.error("An error occurs querying authority solr core", ex);
|
||||
}
|
||||
|
||||
solr = solrServer;
|
||||
}
|
||||
|
@@ -21,7 +21,8 @@ import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.authority.AuthorityValue;
|
||||
import org.dspace.authority.SolrAuthorityInterface;
|
||||
import org.dspace.external.OrcidRestConnector;
|
||||
@@ -40,7 +41,7 @@ import org.orcid.jaxb.model.v3.release.search.Result;
|
||||
*/
|
||||
public class Orcidv3SolrAuthorityImpl implements SolrAuthorityInterface {
|
||||
|
||||
private static Logger log = Logger.getLogger(Orcidv3SolrAuthorityImpl.class);
|
||||
private final static Logger log = LogManager.getLogger();
|
||||
|
||||
private OrcidRestConnector orcidRestConnector;
|
||||
private String OAUTHUrl;
|
||||
|
@@ -14,11 +14,12 @@ import java.util.Iterator;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.xpath.XPathAPI;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
@@ -62,36 +63,26 @@ public class XMLUtils {
|
||||
|
||||
/**
|
||||
* @param xml The starting context (a Node or a Document, for example).
|
||||
* @param NodeListXPath xpath
|
||||
* @param nodeListXPath xpath
|
||||
* @return A Node matches the NodeListXPath
|
||||
* null if nothing matches the NodeListXPath
|
||||
* @throws XPathExpressionException if xpath error
|
||||
*/
|
||||
public static Node getNode(Node xml, String NodeListXPath) throws XPathExpressionException {
|
||||
Node result = null;
|
||||
try {
|
||||
result = XPathAPI.selectSingleNode(xml, NodeListXPath);
|
||||
} catch (TransformerException e) {
|
||||
log.error("Error", e);
|
||||
}
|
||||
return result;
|
||||
public static Node getNode(Node xml, String nodeListXPath) throws XPathExpressionException {
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
return (Node) xPath.compile(nodeListXPath).evaluate(xml, XPathConstants.NODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param xml The starting context (a Node or a Document, for example).
|
||||
* @param NodeListXPath xpath
|
||||
* @param nodeListXPath xpath
|
||||
* @return A NodeList containing the nodes that match the NodeListXPath
|
||||
* null if nothing matches the NodeListXPath
|
||||
* @throws XPathExpressionException if xpath error
|
||||
*/
|
||||
public static NodeList getNodeList(Node xml, String NodeListXPath) throws XPathExpressionException {
|
||||
NodeList nodeList = null;
|
||||
try {
|
||||
nodeList = XPathAPI.selectNodeList(xml, NodeListXPath);
|
||||
} catch (TransformerException e) {
|
||||
log.error("Error", e);
|
||||
}
|
||||
return nodeList;
|
||||
public static NodeList getNodeList(Node xml, String nodeListXPath) throws XPathExpressionException {
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
return (NodeList) xPath.compile(nodeListXPath).evaluate(xml, XPathConstants.NODESET);
|
||||
}
|
||||
|
||||
public static Iterator<Node> getNodeListIterator(Node xml, String NodeListXPath) throws XPathExpressionException {
|
||||
|
@@ -7,6 +7,9 @@
|
||||
*/
|
||||
package org.dspace.authorize;
|
||||
|
||||
import static org.dspace.app.util.AuthorizeUtil.canCollectionAdminManageAccounts;
|
||||
import static org.dspace.app.util.AuthorizeUtil.canCommunityAdminManageAccounts;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -900,6 +903,16 @@ public class AuthorizeServiceImpl implements AuthorizeService {
|
||||
return discoverResult.getTotalSearchResults();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountManager(Context context) {
|
||||
try {
|
||||
return (canCommunityAdminManageAccounts() && isCommunityAdmin(context)
|
||||
|| canCollectionAdminManageAccounts() && isCollectionAdmin(context));
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean performCheck(Context context, String query) throws SQLException {
|
||||
if (context.getCurrentUser() == null) {
|
||||
return false;
|
||||
|
@@ -93,7 +93,7 @@ public class ResourcePolicy implements ReloadableEntity<Integer> {
|
||||
private String rptype;
|
||||
|
||||
@Lob
|
||||
@Type(type = "org.hibernate.type.MaterializedClobType")
|
||||
@Type(type = "org.dspace.storage.rdbms.hibernate.DatabaseAwareLobType")
|
||||
@Column(name = "rpdescription")
|
||||
private String rpdescription;
|
||||
|
||||
|
@@ -592,4 +592,12 @@ public interface AuthorizeService {
|
||||
*/
|
||||
long countAdminAuthorizedCollection(Context context, String query)
|
||||
throws SearchServiceException, SQLException;
|
||||
|
||||
/**
|
||||
* Returns true if the current user can manage accounts.
|
||||
*
|
||||
* @param context context with the current user
|
||||
* @return true if the current user can manage accounts
|
||||
*/
|
||||
boolean isAccountManager(Context context);
|
||||
}
|
||||
|
@@ -346,7 +346,7 @@ public interface BrowseDAO {
|
||||
public String getFilterValueField();
|
||||
|
||||
/**
|
||||
* Set he name of the field in which the value to constrain results is
|
||||
* Set the name of the field in which the value to constrain results is
|
||||
* contained
|
||||
*
|
||||
* @param valueField the name of the field
|
||||
|
@@ -11,6 +11,7 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
@@ -202,6 +203,13 @@ public class BrowseEngine {
|
||||
// get the table name that we are going to be getting our data from
|
||||
dao.setTable(browseIndex.getTableName());
|
||||
|
||||
if (scope.getBrowseIndex() != null && OrderFormat.TITLE.equals(scope.getBrowseIndex().getDataType())) {
|
||||
// For browsing by title, apply the same normalization applied to indexed titles
|
||||
dao.setStartsWith(normalizeJumpToValue(scope.getStartsWith()));
|
||||
} else {
|
||||
dao.setStartsWith(StringUtils.lowerCase(scope.getStartsWith()));
|
||||
}
|
||||
|
||||
// tell the browse query whether we are ascending or descending on the value
|
||||
dao.setAscending(scope.isAscending());
|
||||
|
||||
@@ -248,9 +256,6 @@ public class BrowseEngine {
|
||||
}
|
||||
}
|
||||
|
||||
// this is the total number of results in answer to the query
|
||||
int total = getTotalResults();
|
||||
|
||||
// assemble the ORDER BY clause
|
||||
String orderBy = browseIndex.getSortField(scope.isSecondLevel());
|
||||
if (scope.getSortBy() > 0) {
|
||||
@@ -258,6 +263,9 @@ public class BrowseEngine {
|
||||
}
|
||||
dao.setOrderField(orderBy);
|
||||
|
||||
// this is the total number of results in answer to the query
|
||||
int total = getTotalResults();
|
||||
|
||||
int offset = scope.getOffset();
|
||||
String rawFocusValue = null;
|
||||
if (offset < 1 && (scope.hasJumpToItem() || scope.hasJumpToValue() || scope.hasStartsWith())) {
|
||||
@@ -269,9 +277,6 @@ public class BrowseEngine {
|
||||
String focusValue = normalizeJumpToValue(rawFocusValue);
|
||||
|
||||
log.debug("browsing using focus: " + focusValue);
|
||||
|
||||
// Convert the focus value into an offset
|
||||
offset = getOffsetForValue(focusValue);
|
||||
}
|
||||
|
||||
dao.setOffset(offset);
|
||||
@@ -290,7 +295,7 @@ public class BrowseEngine {
|
||||
// now, if we don't have any results, we are at the end of the browse. This will
|
||||
// be because a starts_with value has been supplied for which we don't have
|
||||
// any items.
|
||||
if (results.size() == 0) {
|
||||
if (results.isEmpty()) {
|
||||
// In this case, we will calculate a new offset for the last page of results
|
||||
offset = total - scope.getResultsPerPage();
|
||||
if (offset < 0) {
|
||||
@@ -450,7 +455,7 @@ public class BrowseEngine {
|
||||
// now, if we don't have any results, we are at the end of the browse. This will
|
||||
// be because a starts_with value has been supplied for which we don't have
|
||||
// any items.
|
||||
if (results.size() == 0) {
|
||||
if (results.isEmpty()) {
|
||||
// In this case, we will calculate a new offset for the last page of results
|
||||
offset = total - scope.getResultsPerPage();
|
||||
if (offset < 0) {
|
||||
@@ -463,7 +468,7 @@ public class BrowseEngine {
|
||||
}
|
||||
} else {
|
||||
// No records, so make an empty list
|
||||
results = new ArrayList<String[]>();
|
||||
results = new ArrayList<>();
|
||||
}
|
||||
|
||||
// construct the BrowseInfo object to pass back
|
||||
@@ -554,7 +559,7 @@ public class BrowseEngine {
|
||||
}
|
||||
|
||||
String col = "sort_1";
|
||||
if (so.getNumber() > 0) {
|
||||
if (so != null && so.getNumber() > 0) {
|
||||
col = "sort_" + Integer.toString(so.getNumber());
|
||||
}
|
||||
|
||||
@@ -591,7 +596,7 @@ public class BrowseEngine {
|
||||
}
|
||||
|
||||
String col = "sort_1";
|
||||
if (so.getNumber() > 0) {
|
||||
if (so != null && so.getNumber() > 0) {
|
||||
col = "sort_" + Integer.toString(so.getNumber());
|
||||
}
|
||||
|
||||
@@ -684,13 +689,11 @@ public class BrowseEngine {
|
||||
// our count, storing them locally to reinstate later
|
||||
String focusField = dao.getJumpToField();
|
||||
String focusValue = dao.getJumpToValue();
|
||||
String orderField = dao.getOrderField();
|
||||
int limit = dao.getLimit();
|
||||
int offset = dao.getOffset();
|
||||
|
||||
dao.setJumpToField(null);
|
||||
dao.setJumpToValue(null);
|
||||
dao.setOrderField(null);
|
||||
dao.setLimit(-1);
|
||||
dao.setOffset(-1);
|
||||
|
||||
@@ -700,7 +703,6 @@ public class BrowseEngine {
|
||||
// now put back the values we removed for this method
|
||||
dao.setJumpToField(focusField);
|
||||
dao.setJumpToValue(focusValue);
|
||||
dao.setOrderField(orderField);
|
||||
dao.setLimit(limit);
|
||||
dao.setOffset(offset);
|
||||
dao.setCountValues(null);
|
||||
|
@@ -313,14 +313,6 @@ public final class BrowseIndex {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name The name to set.
|
||||
*/
|
||||
// public void setName(String name)
|
||||
// {
|
||||
// this.name = name;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get the SortOption associated with this index.
|
||||
*
|
||||
|
@@ -25,22 +25,7 @@ public class ItemListConfig {
|
||||
/**
|
||||
* a map of column number to metadata value
|
||||
*/
|
||||
private Map<Integer, String[]> metadata = new HashMap<Integer, String[]>();
|
||||
|
||||
/**
|
||||
* a map of column number to data type
|
||||
*/
|
||||
private Map<Integer, Integer> types = new HashMap<Integer, Integer>();
|
||||
|
||||
/**
|
||||
* constant for a DATE column
|
||||
*/
|
||||
private static final int DATE = 1;
|
||||
|
||||
/**
|
||||
* constant for a TEXT column
|
||||
*/
|
||||
private static final int TEXT = 2;
|
||||
private Map<Integer, String[]> metadata = new HashMap<>();
|
||||
|
||||
private final transient ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
@@ -63,14 +48,11 @@ public class ItemListConfig {
|
||||
// parse the config
|
||||
int i = 1;
|
||||
for (String token : browseFields) {
|
||||
Integer key = Integer.valueOf(i);
|
||||
Integer key = i;
|
||||
|
||||
// find out if the field is a date
|
||||
if (token.indexOf("(date)") > 0) {
|
||||
token = token.replaceAll("\\(date\\)", "");
|
||||
types.put(key, Integer.valueOf(ItemListConfig.DATE));
|
||||
} else {
|
||||
types.put(key, Integer.valueOf(ItemListConfig.TEXT));
|
||||
}
|
||||
|
||||
String[] mdBits = interpretField(token.trim(), null);
|
||||
@@ -100,7 +82,7 @@ public class ItemListConfig {
|
||||
* @return array of metadata
|
||||
*/
|
||||
public String[] getMetadata(int col) {
|
||||
return metadata.get(Integer.valueOf(col));
|
||||
return metadata.get(col);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -205,6 +205,9 @@ public class SolrBrowseDAO implements BrowseDAO {
|
||||
} else if (valuePartial) {
|
||||
query.addFilterQueries("{!field f=" + facetField + "_partial}" + value);
|
||||
}
|
||||
if (StringUtils.isNotBlank(startsWith) && orderField != null) {
|
||||
query.addFilterQueries("bi_" + orderField + "_sort:" + startsWith + "*");
|
||||
}
|
||||
// filter on item to be sure to don't include any other object
|
||||
// indexed in the Discovery Search core
|
||||
query.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE);
|
||||
|
@@ -158,6 +158,11 @@ public class BundleServiceImpl extends DSpaceObjectServiceImpl<Bundle> implement
|
||||
}
|
||||
|
||||
bundle.addBitstream(bitstream);
|
||||
// If a bitstream is moved from one bundle to another it may be temporarily flagged as deleted
|
||||
// (when removed from the original bundle)
|
||||
if (bitstream.isDeleted()) {
|
||||
bitstream.setDeleted(false);
|
||||
}
|
||||
bitstream.getBundles().add(bundle);
|
||||
|
||||
|
||||
|
@@ -243,67 +243,64 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
|
||||
|
||||
boolean authorityControlled = metadataAuthorityService.isAuthorityControlled(metadataField);
|
||||
boolean authorityRequired = metadataAuthorityService.isAuthorityRequired(metadataField);
|
||||
List<MetadataValue> newMetadata = new ArrayList<>(values.size());
|
||||
List<MetadataValue> newMetadata = new ArrayList<>();
|
||||
// We will not verify that they are valid entries in the registry
|
||||
// until update() is called.
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
|
||||
if (authorities != null && authorities.size() >= i) {
|
||||
if (StringUtils.startsWith(authorities.get(i), Constants.VIRTUAL_AUTHORITY_PREFIX)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
MetadataValue metadataValue = metadataValueService.create(context, dso, metadataField);
|
||||
newMetadata.add(metadataValue);
|
||||
|
||||
metadataValue.setPlace(placeSupplier.get());
|
||||
|
||||
metadataValue.setLanguage(lang == null ? null : lang.trim());
|
||||
|
||||
// Logic to set Authority and Confidence:
|
||||
// - normalize an empty string for authority to NULL.
|
||||
// - if authority key is present, use given confidence or NOVALUE if not given
|
||||
// - otherwise, preserve confidence if meaningful value was given since it may document a failed
|
||||
// authority lookup
|
||||
// - CF_UNSET signifies no authority nor meaningful confidence.
|
||||
// - it's possible to have empty authority & CF_ACCEPTED if e.g. user deletes authority key
|
||||
if (authorityControlled) {
|
||||
if (authorities != null && authorities.get(i) != null && authorities.get(i).length() > 0) {
|
||||
metadataValue.setAuthority(authorities.get(i));
|
||||
metadataValue.setConfidence(confidences == null ? Choices.CF_NOVALUE : confidences.get(i));
|
||||
} else {
|
||||
metadataValue.setAuthority(null);
|
||||
metadataValue.setConfidence(confidences == null ? Choices.CF_UNSET : confidences.get(i));
|
||||
}
|
||||
// authority sanity check: if authority is required, was it supplied?
|
||||
// XXX FIXME? can't throw a "real" exception here without changing all the callers to expect it, so
|
||||
// use a runtime exception
|
||||
if (authorityRequired && (metadataValue.getAuthority() == null || metadataValue.getAuthority()
|
||||
.length() == 0)) {
|
||||
throw new IllegalArgumentException("The metadata field \"" + metadataField
|
||||
.toString() + "\" requires an authority key but none was provided. Value=\"" + values
|
||||
.get(i) + "\"");
|
||||
}
|
||||
}
|
||||
if (values.get(i) != null) {
|
||||
if (authorities != null && authorities.size() >= i) {
|
||||
if (StringUtils.startsWith(authorities.get(i), Constants.VIRTUAL_AUTHORITY_PREFIX)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
MetadataValue metadataValue = metadataValueService.create(context, dso, metadataField);
|
||||
newMetadata.add(metadataValue);
|
||||
|
||||
metadataValue.setPlace(placeSupplier.get());
|
||||
|
||||
metadataValue.setLanguage(lang == null ? null : lang.trim());
|
||||
|
||||
// Logic to set Authority and Confidence:
|
||||
// - normalize an empty string for authority to NULL.
|
||||
// - if authority key is present, use given confidence or NOVALUE if not given
|
||||
// - otherwise, preserve confidence if meaningful value was given since it may document a failed
|
||||
// authority lookup
|
||||
// - CF_UNSET signifies no authority nor meaningful confidence.
|
||||
// - it's possible to have empty authority & CF_ACCEPTED if e.g. user deletes authority key
|
||||
if (authorityControlled) {
|
||||
if (authorities != null && authorities.get(i) != null && authorities.get(i).length() > 0) {
|
||||
metadataValue.setAuthority(authorities.get(i));
|
||||
metadataValue.setConfidence(confidences == null ? Choices.CF_NOVALUE : confidences.get(i));
|
||||
} else {
|
||||
metadataValue.setAuthority(null);
|
||||
metadataValue.setConfidence(confidences == null ? Choices.CF_UNSET : confidences.get(i));
|
||||
}
|
||||
// authority sanity check: if authority is required, was it supplied?
|
||||
// XXX FIXME? can't throw a "real" exception here without changing all the callers to expect it, so
|
||||
// use a runtime exception
|
||||
if (authorityRequired && (metadataValue.getAuthority() == null || metadataValue.getAuthority()
|
||||
.length() == 0)) {
|
||||
throw new IllegalArgumentException("The metadata field \"" + metadataField
|
||||
.toString() + "\" requires an authority key but none was provided. Value=\"" + values
|
||||
.get(i) + "\"");
|
||||
}
|
||||
}
|
||||
// remove control unicode char
|
||||
String temp = values.get(i).trim();
|
||||
char[] dcvalue = temp.toCharArray();
|
||||
for (int charPos = 0; charPos < dcvalue.length; charPos++) {
|
||||
if (Character.isISOControl(dcvalue[charPos]) &&
|
||||
!String.valueOf(dcvalue[charPos]).equals("\u0009") &&
|
||||
!String.valueOf(dcvalue[charPos]).equals("\n") &&
|
||||
!String.valueOf(dcvalue[charPos]).equals("\r")) {
|
||||
!String.valueOf(dcvalue[charPos]).equals("\u0009") &&
|
||||
!String.valueOf(dcvalue[charPos]).equals("\n") &&
|
||||
!String.valueOf(dcvalue[charPos]).equals("\r")) {
|
||||
dcvalue[charPos] = ' ';
|
||||
}
|
||||
}
|
||||
metadataValue.setValue(String.valueOf(dcvalue));
|
||||
} else {
|
||||
metadataValue.setValue(null);
|
||||
}
|
||||
//An update here isn't needed, this is persited upon the merge of the owning object
|
||||
//An update here isn't needed, this is persited upon the merge of the owning object
|
||||
// metadataValueService.update(context, metadataValue);
|
||||
dso.addDetails(metadataField.toString());
|
||||
dso.addDetails(metadataField.toString());
|
||||
}
|
||||
}
|
||||
setMetadataModified(dso);
|
||||
return newMetadata;
|
||||
@@ -624,8 +621,14 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
|
||||
});
|
||||
for (MetadataValue metadataValue : metadataValues) {
|
||||
//Retrieve & store the place for each metadata value
|
||||
if (StringUtils.startsWith(metadataValue.getAuthority(), Constants.VIRTUAL_AUTHORITY_PREFIX) &&
|
||||
((RelationshipMetadataValue) metadataValue).isUseForPlace()) {
|
||||
if (
|
||||
// For virtual MDVs with useForPlace=true,
|
||||
// update both the place of the metadatum and the place of the Relationship.
|
||||
// E.g. for an Author relationship,
|
||||
// the place should be updated using the same principle as dc.contributor.author.
|
||||
StringUtils.startsWith(metadataValue.getAuthority(), Constants.VIRTUAL_AUTHORITY_PREFIX)
|
||||
&& ((RelationshipMetadataValue) metadataValue).isUseForPlace()
|
||||
) {
|
||||
int mvPlace = getMetadataValuePlace(fieldToLastPlace, metadataValue);
|
||||
metadataValue.setPlace(mvPlace);
|
||||
String authority = metadataValue.getAuthority();
|
||||
@@ -638,8 +641,16 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
|
||||
}
|
||||
relationshipService.update(context, relationship);
|
||||
|
||||
} else if (!StringUtils.startsWith(metadataValue.getAuthority(),
|
||||
Constants.VIRTUAL_AUTHORITY_PREFIX)) {
|
||||
} else if (
|
||||
// Otherwise, just set the place of the metadatum
|
||||
// ...unless the metadatum in question is a relation.* metadatum.
|
||||
// This case is a leftover from when a Relationship is removed and copied to metadata.
|
||||
// If we let its place change the order of any remaining Relationships will be affected.
|
||||
// todo: this makes it so these leftover MDVs can't be reordered later on
|
||||
!StringUtils.equals(
|
||||
metadataValue.getMetadataField().getMetadataSchema().getName(), "relation"
|
||||
)
|
||||
) {
|
||||
int mvPlace = getMetadataValuePlace(fieldToLastPlace, metadataValue);
|
||||
metadataValue.setPlace(mvPlace);
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
@@ -40,6 +41,7 @@ import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.service.BundleService;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.content.service.EntityTypeService;
|
||||
import org.dspace.content.service.InstallItemService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.content.service.MetadataSchemaService;
|
||||
@@ -56,6 +58,15 @@ import org.dspace.harvest.HarvestedItem;
|
||||
import org.dspace.harvest.service.HarvestedItemService;
|
||||
import org.dspace.identifier.IdentifierException;
|
||||
import org.dspace.identifier.service.IdentifierService;
|
||||
import org.dspace.orcid.OrcidHistory;
|
||||
import org.dspace.orcid.OrcidQueue;
|
||||
import org.dspace.orcid.OrcidToken;
|
||||
import org.dspace.orcid.model.OrcidEntityType;
|
||||
import org.dspace.orcid.service.OrcidHistoryService;
|
||||
import org.dspace.orcid.service.OrcidQueueService;
|
||||
import org.dspace.orcid.service.OrcidSynchronizationService;
|
||||
import org.dspace.orcid.service.OrcidTokenService;
|
||||
import org.dspace.profile.service.ResearcherProfileService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.dspace.workflow.WorkflowItemService;
|
||||
@@ -120,6 +131,24 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
@Autowired(required = true)
|
||||
private RelationshipMetadataService relationshipMetadataService;
|
||||
|
||||
@Autowired(required = true)
|
||||
private EntityTypeService entityTypeService;
|
||||
|
||||
@Autowired
|
||||
private OrcidTokenService orcidTokenService;
|
||||
|
||||
@Autowired(required = true)
|
||||
private OrcidHistoryService orcidHistoryService;
|
||||
|
||||
@Autowired(required = true)
|
||||
private OrcidQueueService orcidQueueService;
|
||||
|
||||
@Autowired(required = true)
|
||||
private OrcidSynchronizationService orcidSynchronizationService;
|
||||
|
||||
@Autowired(required = true)
|
||||
private ResearcherProfileService researcherProfileService;
|
||||
|
||||
protected ItemServiceImpl() {
|
||||
super();
|
||||
}
|
||||
@@ -241,6 +270,10 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
return itemDAO.findAll(context, true, true);
|
||||
}
|
||||
|
||||
public Iterator<Item> findAllRegularItems(Context context) throws SQLException {
|
||||
return itemDAO.findAllRegularItems(context);
|
||||
};
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findBySubmitter(Context context, EPerson eperson) throws SQLException {
|
||||
return itemDAO.findBySubmitter(context, eperson);
|
||||
@@ -724,7 +757,7 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
+ item.getID()));
|
||||
|
||||
// Remove relationships
|
||||
for (Relationship relationship : relationshipService.findByItem(context, item)) {
|
||||
for (Relationship relationship : relationshipService.findByItem(context, item, -1, -1, false, false)) {
|
||||
relationshipService.forceDelete(context, relationship, false, false);
|
||||
}
|
||||
|
||||
@@ -737,6 +770,8 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
// remove version attached to the item
|
||||
removeVersion(context, item);
|
||||
|
||||
removeOrcidSynchronizationStuff(context, item);
|
||||
|
||||
// Also delete the item if it appears in a harvested collection.
|
||||
HarvestedItem hi = harvestedItemService.find(context, item);
|
||||
|
||||
@@ -744,6 +779,11 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
harvestedItemService.delete(context, hi);
|
||||
}
|
||||
|
||||
OrcidToken orcidToken = orcidTokenService.findByProfileItem(context, item);
|
||||
if (orcidToken != null) {
|
||||
orcidToken.setProfileItem(null);
|
||||
}
|
||||
|
||||
//Only clear collections after we have removed everything else from the item
|
||||
item.clearCollections();
|
||||
item.setOwningCollection(null);
|
||||
@@ -911,6 +951,12 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
||||
@Override
|
||||
public void move(Context context, Item item, Collection from, Collection to)
|
||||
throws SQLException, AuthorizeException, IOException {
|
||||
|
||||
// If the two collections are the same, do nothing.
|
||||
if (from.equals(to)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the normal move method, and default to not inherit permissions
|
||||
this.move(context, item, from, to, false);
|
||||
}
|
||||
@@ -1125,6 +1171,50 @@ prevent the generation of resource policy entry values with null dspace_object a
|
||||
return !(hasCustomPolicy && isAnonimousGroup && datesAreNull);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator of Items possessing the passed metadata field, or only
|
||||
* those matching the passed value, if value is not Item.ANY
|
||||
*
|
||||
* @param context DSpace context object
|
||||
* @param schema metadata field schema
|
||||
* @param element metadata field element
|
||||
* @param qualifier metadata field qualifier
|
||||
* @param value field value or Item.ANY to match any value
|
||||
* @return an iterator over the items matching that authority value
|
||||
* @throws SQLException if database error
|
||||
* An exception that provides information on a database access error or other errors.
|
||||
* @throws AuthorizeException if authorization error
|
||||
* Exception indicating the current user of the context does not have permission
|
||||
* to perform a particular action.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Item> findArchivedByMetadataField(Context context,
|
||||
String schema, String element, String qualifier, String value)
|
||||
throws SQLException, AuthorizeException {
|
||||
MetadataSchema mds = metadataSchemaService.find(context, schema);
|
||||
if (mds == null) {
|
||||
throw new IllegalArgumentException("No such metadata schema: " + schema);
|
||||
}
|
||||
MetadataField mdf = metadataFieldService.findByElement(context, mds, element, qualifier);
|
||||
if (mdf == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"No such metadata field: schema=" + schema + ", element=" + element + ", qualifier=" + qualifier);
|
||||
}
|
||||
|
||||
if (Item.ANY.equals(value)) {
|
||||
return itemDAO.findByMetadataField(context, mdf, null, true);
|
||||
} else {
|
||||
return itemDAO.findByMetadataField(context, mdf, value, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> findArchivedByMetadataField(Context context, String metadataField, String value)
|
||||
throws SQLException, AuthorizeException {
|
||||
String[] mdValueByField = getMDValueByField(metadataField);
|
||||
return findArchivedByMetadataField(context, mdValueByField[0], mdValueByField[1], mdValueByField[2], value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator of Items possessing the passed metadata field, or only
|
||||
* those matching the passed value, if value is not Item.ANY
|
||||
@@ -1529,5 +1619,100 @@ prevent the generation of resource policy entry values with null dspace_object a
|
||||
.stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEntityTypeLabel(Item item) {
|
||||
List<MetadataValue> mdvs = getMetadata(item, "dspace", "entity", "type", Item.ANY, false);
|
||||
if (mdvs.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mdvs.size() > 1) {
|
||||
log.warn(
|
||||
"Item with uuid {}, handle {} has {} entity types ({}), expected 1 entity type",
|
||||
item.getID(), item.getHandle(), mdvs.size(),
|
||||
mdvs.stream().map(MetadataValue::getValue).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
String entityType = mdvs.get(0).getValue();
|
||||
if (StringUtils.isBlank(entityType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType getEntityType(Context context, Item item) throws SQLException {
|
||||
String entityTypeString = getEntityTypeLabel(item);
|
||||
if (StringUtils.isBlank(entityTypeString)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return entityTypeService.findByEntityType(context, entityTypeString);
|
||||
}
|
||||
|
||||
private void removeOrcidSynchronizationStuff(Context context, Item item) throws SQLException, AuthorizeException {
|
||||
|
||||
if (isNotProfileOrOrcidEntity(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
try {
|
||||
|
||||
createOrcidQueueRecordsToDeleteOnOrcid(context, item);
|
||||
deleteOrcidHistoryRecords(context, item);
|
||||
deleteOrcidQueueRecords(context, item);
|
||||
|
||||
} finally {
|
||||
context.restoreAuthSystemState();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean isNotProfileOrOrcidEntity(Item item) {
|
||||
String entityType = getEntityTypeLabel(item);
|
||||
return !OrcidEntityType.isValidEntityType(entityType)
|
||||
&& !researcherProfileService.getProfileType().equals(entityType);
|
||||
}
|
||||
|
||||
private void createOrcidQueueRecordsToDeleteOnOrcid(Context context, Item entity) throws SQLException {
|
||||
|
||||
String entityType = getEntityTypeLabel(entity);
|
||||
if (entityType == null || researcherProfileService.getProfileType().equals(entityType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<Item, String> profileAndPutCodeMap = orcidHistoryService.findLastPutCodes(context, entity);
|
||||
for (Item profile : profileAndPutCodeMap.keySet()) {
|
||||
if (orcidSynchronizationService.isSynchronizationAllowed(profile, entity)) {
|
||||
String putCode = profileAndPutCodeMap.get(profile);
|
||||
String title = getMetadataFirstValue(entity, "dc", "title", null, Item.ANY);
|
||||
orcidQueueService.createEntityDeletionRecord(context, profile, title, entityType, putCode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void deleteOrcidHistoryRecords(Context context, Item item) throws SQLException {
|
||||
List<OrcidHistory> historyRecords = orcidHistoryService.findByProfileItemOrEntity(context, item);
|
||||
for (OrcidHistory historyRecord : historyRecords) {
|
||||
if (historyRecord.getProfileItem().equals(item)) {
|
||||
orcidHistoryService.delete(context, historyRecord);
|
||||
} else {
|
||||
historyRecord.setEntity(null);
|
||||
orcidHistoryService.update(context, historyRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteOrcidQueueRecords(Context context, Item item) throws SQLException {
|
||||
List<OrcidQueue> orcidQueueRecords = orcidQueueService.findByProfileItemOrEntity(context, item);
|
||||
for (OrcidQueue orcidQueueRecord : orcidQueueRecords) {
|
||||
orcidQueueService.delete(context, orcidQueueRecord);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user