mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-16 22:43:12 +00:00
Merge branch 'main' into 8882-localized-license-files
This commit is contained in:
2
.github/workflows/label_merge_conflicts.yml
vendored
2
.github/workflows/label_merge_conflicts.yml
vendored
@@ -25,6 +25,8 @@ jobs:
|
|||||||
# See: https://github.com/prince-chrismc/label-merge-conflicts-action
|
# See: https://github.com/prince-chrismc/label-merge-conflicts-action
|
||||||
- name: Auto-label PRs with merge conflicts
|
- name: Auto-label PRs with merge conflicts
|
||||||
uses: prince-chrismc/label-merge-conflicts-action@v3
|
uses: prince-chrismc/label-merge-conflicts-action@v3
|
||||||
|
# Ignore any failures -- may occur (randomly?) for older, outdated PRs.
|
||||||
|
continue-on-error: true
|
||||||
# Add "merge conflict" label if a merge conflict is detected. Remove it when resolved.
|
# Add "merge conflict" label if a merge conflict is detected. Remove it when resolved.
|
||||||
# Note, the authentication token is created automatically
|
# Note, the authentication token is created automatically
|
||||||
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
|
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
|
||||||
|
46
.github/workflows/port_merged_pull_request.yml
vendored
Normal file
46
.github/workflows/port_merged_pull_request.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# This workflow will attempt to port a merged pull request to
|
||||||
|
# the branch specified in a "port to" label (if exists)
|
||||||
|
name: Port merged Pull Request
|
||||||
|
|
||||||
|
# Only run for merged PRs against the "main" or maintenance branches
|
||||||
|
# We allow this to run for `pull_request_target` so that github secrets are available
|
||||||
|
# (This is required when the PR comes from a forked repo)
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [ closed ]
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- 'dspace-**'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write # so action can add comments
|
||||||
|
pull-requests: write # so action can create pull requests
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
port_pr:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Don't run on closed *unmerged* pull requests
|
||||||
|
if: github.event.pull_request.merged
|
||||||
|
steps:
|
||||||
|
# Checkout code
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
# Port PR to other branch (ONLY if labeled with "port to")
|
||||||
|
# See https://github.com/korthout/backport-action
|
||||||
|
- name: Create backport pull requests
|
||||||
|
uses: korthout/backport-action@v1
|
||||||
|
with:
|
||||||
|
# Trigger based on a "port to [branch]" label on PR
|
||||||
|
# (This label must specify the branch name to port to)
|
||||||
|
label_pattern: '^port to ([^ ]+)$'
|
||||||
|
# Title to add to the (newly created) port PR
|
||||||
|
pull_title: '[Port ${target_branch}] ${pull_title}'
|
||||||
|
# Description to add to the (newly created) port PR
|
||||||
|
pull_description: 'Port of #${pull_number} by @${pull_author} to `${target_branch}`.'
|
||||||
|
# Copy all labels from original PR to (newly created) port PR
|
||||||
|
# NOTE: The labels matching 'label_pattern' are automatically excluded
|
||||||
|
copy_labels_pattern: '.*'
|
||||||
|
# Skip any merge commits in the ported PR. This means only non-merge commits are cherry-picked to the new PR
|
||||||
|
merge_commits: 'skip'
|
||||||
|
# Use a personal access token (PAT) to create PR as 'dspace-bot' user.
|
||||||
|
# A PAT is required in order for the new PR to trigger its own actions (for CI checks)
|
||||||
|
github_token: ${{ secrets.PR_PORT_TOKEN }}
|
@@ -1,14 +1,15 @@
|
|||||||
# This image will be published as dspace/dspace
|
# This image will be published as dspace/dspace
|
||||||
# See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details
|
# See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details
|
||||||
#
|
#
|
||||||
# - note: default tag for branch: dspace/dspace: dspace/dspace:dspace-7_x
|
# - note: default tag for branch: dspace/dspace: dspace/dspace:latest
|
||||||
|
|
||||||
# This Dockerfile uses JDK11 by default, but has also been tested with JDK17.
|
# This Dockerfile uses JDK11 by default, but has also been tested with JDK17.
|
||||||
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
||||||
ARG JDK_VERSION=11
|
ARG JDK_VERSION=11
|
||||||
|
ARG DSPACE_VERSION=latest
|
||||||
|
|
||||||
# Step 1 - Run Maven Build
|
# Step 1 - Run Maven Build
|
||||||
FROM dspace/dspace-dependencies:dspace-7_x as build
|
FROM dspace/dspace-dependencies:${DSPACE_VERSION} as build
|
||||||
ARG TARGET_DIR=dspace-installer
|
ARG TARGET_DIR=dspace-installer
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
# The dspace-installer directory will be written to /install
|
# The dspace-installer directory will be written to /install
|
||||||
@@ -50,7 +51,7 @@ RUN ant init_installation update_configs update_code update_webapps
|
|||||||
FROM tomcat:9-jdk${JDK_VERSION}
|
FROM tomcat:9-jdk${JDK_VERSION}
|
||||||
# NOTE: DSPACE_INSTALL must align with the "dspace.dir" default configuration.
|
# NOTE: DSPACE_INSTALL must align with the "dspace.dir" default configuration.
|
||||||
ENV DSPACE_INSTALL=/dspace
|
ENV DSPACE_INSTALL=/dspace
|
||||||
# Copy the /dspace directory from 'ant_build' containger to /dspace in this container
|
# Copy the /dspace directory from 'ant_build' container to /dspace in this container
|
||||||
COPY --from=ant_build /dspace $DSPACE_INSTALL
|
COPY --from=ant_build /dspace $DSPACE_INSTALL
|
||||||
# Expose Tomcat port and AJP port
|
# Expose Tomcat port and AJP port
|
||||||
EXPOSE 8080 8009
|
EXPOSE 8080 8009
|
||||||
|
@@ -1,14 +1,15 @@
|
|||||||
# This image will be published as dspace/dspace-cli
|
# This image will be published as dspace/dspace-cli
|
||||||
# See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details
|
# See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details
|
||||||
#
|
#
|
||||||
# - note: default tag for branch: dspace/dspace-cli: dspace/dspace-cli:dspace-7_x
|
# - note: default tag for branch: dspace/dspace-cli: dspace/dspace-cli:latest
|
||||||
|
|
||||||
# This Dockerfile uses JDK11 by default, but has also been tested with JDK17.
|
# This Dockerfile uses JDK11 by default, but has also been tested with JDK17.
|
||||||
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
||||||
ARG JDK_VERSION=11
|
ARG JDK_VERSION=11
|
||||||
|
ARG DSPACE_VERSION=latest
|
||||||
|
|
||||||
# Step 1 - Run Maven Build
|
# Step 1 - Run Maven Build
|
||||||
FROM dspace/dspace-dependencies:dspace-7_x as build
|
FROM dspace/dspace-dependencies:${DSPACE_VERSION} as build
|
||||||
ARG TARGET_DIR=dspace-installer
|
ARG TARGET_DIR=dspace-installer
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
# The dspace-installer directory will be written to /install
|
# The dspace-installer directory will be written to /install
|
||||||
|
@@ -1,16 +1,17 @@
|
|||||||
# This image will be published as dspace/dspace
|
# This image will be published as dspace/dspace
|
||||||
# See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details
|
# See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details
|
||||||
#
|
#
|
||||||
# - note: default tag for branch: dspace/dspace: dspace/dspace:dspace-7_x-test
|
# - note: default tag for branch: dspace/dspace: dspace/dspace:latest-test
|
||||||
#
|
#
|
||||||
# This image is meant for TESTING/DEVELOPMENT ONLY as it deploys the old v6 REST API under HTTP (not HTTPS)
|
# This image is meant for TESTING/DEVELOPMENT ONLY as it deploys the old v6 REST API under HTTP (not HTTPS)
|
||||||
|
|
||||||
# This Dockerfile uses JDK11 by default, but has also been tested with JDK17.
|
# This Dockerfile uses JDK11 by default, but has also been tested with JDK17.
|
||||||
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
||||||
ARG JDK_VERSION=11
|
ARG JDK_VERSION=11
|
||||||
|
ARG DSPACE_VERSION=latest
|
||||||
|
|
||||||
# Step 1 - Run Maven Build
|
# Step 1 - Run Maven Build
|
||||||
FROM dspace/dspace-dependencies:dspace-7_x as build
|
FROM dspace/dspace-dependencies:${DSPACE_VERSION} as build
|
||||||
ARG TARGET_DIR=dspace-installer
|
ARG TARGET_DIR=dspace-installer
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
# The dspace-installer directory will be written to /install
|
# The dspace-installer directory will be written to /install
|
||||||
|
@@ -2,7 +2,7 @@ version: "3.7"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
dspace-cli:
|
dspace-cli:
|
||||||
image: "${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-dspace-7_x}"
|
image: "${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-latest}"
|
||||||
container_name: dspace-cli
|
container_name: dspace-cli
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
|
@@ -28,7 +28,7 @@ services:
|
|||||||
# proxies.trusted.ipranges: This setting is required for a REST API running in Docker to trust requests
|
# proxies.trusted.ipranges: This setting is required for a REST API running in Docker to trust requests
|
||||||
# from the host machine. This IP range MUST correspond to the 'dspacenet' subnet defined above.
|
# from the host machine. This IP range MUST correspond to the 'dspacenet' subnet defined above.
|
||||||
proxies__P__trusted__P__ipranges: '172.23.0'
|
proxies__P__trusted__P__ipranges: '172.23.0'
|
||||||
image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-dspace-7_x-test}"
|
image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-latest-test}"
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile.test
|
dockerfile: Dockerfile.test
|
||||||
@@ -66,7 +66,7 @@ services:
|
|||||||
dspacedb:
|
dspacedb:
|
||||||
container_name: dspacedb
|
container_name: dspacedb
|
||||||
# Uses a custom Postgres image with pgcrypto installed
|
# Uses a custom Postgres image with pgcrypto installed
|
||||||
image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-dspace-7_x}"
|
image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}"
|
||||||
build:
|
build:
|
||||||
# Must build out of subdirectory to have access to install script for pgcrypto
|
# Must build out of subdirectory to have access to install script for pgcrypto
|
||||||
context: ./dspace/src/main/docker/dspace-postgres-pgcrypto/
|
context: ./dspace/src/main/docker/dspace-postgres-pgcrypto/
|
||||||
@@ -86,7 +86,7 @@ services:
|
|||||||
# DSpace Solr container
|
# DSpace Solr container
|
||||||
dspacesolr:
|
dspacesolr:
|
||||||
container_name: dspacesolr
|
container_name: dspacesolr
|
||||||
image: "${DOCKER_OWNER:-dspace}/dspace-solr:${DSPACE_VER:-dspace-7_x}"
|
image: "${DOCKER_OWNER:-dspace}/dspace-solr:${DSPACE_VER:-latest}"
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: ./dspace/src/main/docker/dspace-solr/Dockerfile
|
dockerfile: ./dspace/src/main/docker/dspace-solr/Dockerfile
|
||||||
|
@@ -102,7 +102,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>build-helper-maven-plugin</artifactId>
|
<artifactId>build-helper-maven-plugin</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.4.0</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>validate</phase>
|
<phase>validate</phase>
|
||||||
@@ -116,7 +116,10 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>buildnumber-maven-plugin</artifactId>
|
<artifactId>buildnumber-maven-plugin</artifactId>
|
||||||
<version>1.4</version>
|
<version>3.2.0</version>
|
||||||
|
<configuration>
|
||||||
|
<revisionOnScmFailure>UNKNOWN_REVISION</revisionOnScmFailure>
|
||||||
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>validate</phase>
|
<phase>validate</phase>
|
||||||
|
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.scripts.DSpaceRunnable;
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable.StepResult;
|
||||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
import org.dspace.scripts.factory.ScriptServiceFactory;
|
import org.dspace.scripts.factory.ScriptServiceFactory;
|
||||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
@@ -145,8 +146,13 @@ public class ScriptLauncher {
|
|||||||
private static int executeScript(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
private static int executeScript(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||||
DSpaceRunnable script) {
|
DSpaceRunnable script) {
|
||||||
try {
|
try {
|
||||||
script.initialize(args, dSpaceRunnableHandler, null);
|
StepResult result = script.initialize(args, dSpaceRunnableHandler, null);
|
||||||
script.run();
|
// check the StepResult, only run the script if the result is Continue;
|
||||||
|
// otherwise - for example the script is started with the help as argument, nothing is to do
|
||||||
|
if (StepResult.Continue.equals(result)) {
|
||||||
|
// runs the script, the normal initialization is successful
|
||||||
|
script.run();
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
script.printHelp();
|
script.printHelp();
|
||||||
|
@@ -10,6 +10,7 @@ package org.dspace.app.mediafilter;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -40,6 +41,7 @@ import org.dspace.eperson.Group;
|
|||||||
import org.dspace.eperson.service.GroupService;
|
import org.dspace.eperson.service.GroupService;
|
||||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.util.ThrowableUtils;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
@@ -225,23 +227,9 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
|||||||
filtered = true;
|
filtered = true;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String handle = myItem.getHandle();
|
|
||||||
List<Bundle> bundles = myBitstream.getBundles();
|
|
||||||
long size = myBitstream.getSizeBytes();
|
|
||||||
String checksum = myBitstream.getChecksum() + " (" + myBitstream.getChecksumAlgorithm() + ")";
|
|
||||||
int assetstore = myBitstream.getStoreNumber();
|
|
||||||
|
|
||||||
// Printout helpful information to find the errored bitstream.
|
// Printout helpful information to find the errored bitstream.
|
||||||
StringBuilder sb = new StringBuilder("ERROR filtering, skipping bitstream:\n");
|
logError(formatBitstreamDetails(myItem.getHandle(), myBitstream));
|
||||||
sb.append("\tItem Handle: ").append(handle);
|
logError(ThrowableUtils.formatCauseChain(e));
|
||||||
for (Bundle bundle : bundles) {
|
|
||||||
sb.append("\tBundle Name: ").append(bundle.getName());
|
|
||||||
}
|
|
||||||
sb.append("\tFile Size: ").append(size);
|
|
||||||
sb.append("\tChecksum: ").append(checksum);
|
|
||||||
sb.append("\tAsset Store: ").append(assetstore);
|
|
||||||
logError(sb.toString());
|
|
||||||
logError(e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
} else if (filterClass instanceof SelfRegisterInputFormats) {
|
} else if (filterClass instanceof SelfRegisterInputFormats) {
|
||||||
// Filter implements self registration, so check to see if it should be applied
|
// Filter implements self registration, so check to see if it should be applied
|
||||||
@@ -319,10 +307,10 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
|||||||
|
|
||||||
// check if destination bitstream exists
|
// check if destination bitstream exists
|
||||||
Bundle existingBundle = null;
|
Bundle existingBundle = null;
|
||||||
List<Bitstream> existingBitstreams = new ArrayList<Bitstream>();
|
List<Bitstream> existingBitstreams = new ArrayList<>();
|
||||||
List<Bundle> bundles = itemService.getBundles(item, formatFilter.getBundleName());
|
List<Bundle> bundles = itemService.getBundles(item, formatFilter.getBundleName());
|
||||||
|
|
||||||
if (bundles.size() > 0) {
|
if (!bundles.isEmpty()) {
|
||||||
// only finds the last matching bundle and all matching bitstreams in the proper bundle(s)
|
// only finds the last matching bundle and all matching bitstreams in the proper bundle(s)
|
||||||
for (Bundle bundle : bundles) {
|
for (Bundle bundle : bundles) {
|
||||||
List<Bitstream> bitstreams = bundle.getBitstreams();
|
List<Bitstream> bitstreams = bundle.getBitstreams();
|
||||||
@@ -337,7 +325,7 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if exists and overwrite = false, exit
|
// if exists and overwrite = false, exit
|
||||||
if (!overWrite && (existingBitstreams.size() > 0)) {
|
if (!overWrite && (!existingBitstreams.isEmpty())) {
|
||||||
if (!isQuiet) {
|
if (!isQuiet) {
|
||||||
logInfo("SKIPPED: bitstream " + source.getID()
|
logInfo("SKIPPED: bitstream " + source.getID()
|
||||||
+ " (item: " + item.getHandle() + ") because '" + newName + "' already exists");
|
+ " (item: " + item.getHandle() + ") because '" + newName + "' already exists");
|
||||||
@@ -370,7 +358,7 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bundle targetBundle; // bundle we're modifying
|
Bundle targetBundle; // bundle we're modifying
|
||||||
if (bundles.size() < 1) {
|
if (bundles.isEmpty()) {
|
||||||
// create new bundle if needed
|
// create new bundle if needed
|
||||||
targetBundle = bundleService.create(context, item, formatFilter.getBundleName());
|
targetBundle = bundleService.create(context, item, formatFilter.getBundleName());
|
||||||
} else {
|
} else {
|
||||||
@@ -399,6 +387,7 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
|||||||
|
|
||||||
} catch (OutOfMemoryError oome) {
|
} catch (OutOfMemoryError oome) {
|
||||||
logError("!!! OutOfMemoryError !!!");
|
logError("!!! OutOfMemoryError !!!");
|
||||||
|
logError(formatBitstreamDetails(item.getHandle(), source));
|
||||||
}
|
}
|
||||||
|
|
||||||
// we are overwriting, so remove old bitstream
|
// we are overwriting, so remove old bitstream
|
||||||
@@ -496,6 +485,37 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describe a Bitstream in detail. Format a single line of text with
|
||||||
|
* information such as Bitstore index, backing file ID, size, checksum,
|
||||||
|
* enclosing Item and Bundles.
|
||||||
|
*
|
||||||
|
* @param itemHandle Handle of the Item by which we found the Bitstream.
|
||||||
|
* @param bitstream the Bitstream to be described.
|
||||||
|
* @return Bitstream details.
|
||||||
|
*/
|
||||||
|
private String formatBitstreamDetails(String itemHandle,
|
||||||
|
Bitstream bitstream) {
|
||||||
|
List<Bundle> bundles;
|
||||||
|
try {
|
||||||
|
bundles = bitstream.getBundles();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logError("Unexpected error fetching Bundles", ex);
|
||||||
|
bundles = Collections.EMPTY_LIST;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder("ERROR filtering, skipping bitstream:\n");
|
||||||
|
sb.append("\tItem Handle: ").append(itemHandle);
|
||||||
|
for (Bundle bundle : bundles) {
|
||||||
|
sb.append("\tBundle Name: ").append(bundle.getName());
|
||||||
|
}
|
||||||
|
sb.append("\tFile Size: ").append(bitstream.getSizeBytes());
|
||||||
|
sb.append("\tChecksum: ").append(bitstream.getChecksum())
|
||||||
|
.append(" (").append(bitstream.getChecksumAlgorithm()).append(')');
|
||||||
|
sb.append("\tAsset Store: ").append(bitstream.getStoreNumber());
|
||||||
|
sb.append("\tInternal ID: ").append(bitstream.getInternalId());
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private void logInfo(String message) {
|
private void logInfo(String message) {
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.logInfo(message);
|
handler.logInfo(message);
|
||||||
|
@@ -108,7 +108,7 @@ public class CrossLinks {
|
|||||||
} else {
|
} else {
|
||||||
// Exact match, if the key field has no .* wildcard
|
// Exact match, if the key field has no .* wildcard
|
||||||
if (links.containsKey(metadata)) {
|
if (links.containsKey(metadata)) {
|
||||||
return links.get(key);
|
return links.get(metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.cli;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
import org.apache.commons.cli.DefaultParser;
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.apache.commons.cli.ParseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended version of the DefaultParser. This parser skip/ignore unknown arguments.
|
||||||
|
*/
|
||||||
|
public class DSpaceSkipUnknownArgumentsParser extends DefaultParser {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandLine parse(Options options, String[] arguments) throws ParseException {
|
||||||
|
return super.parse(options, getOnlyKnownArguments(options, arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandLine parse(Options options, String[] arguments, Properties properties) throws ParseException {
|
||||||
|
return super.parse(options, getOnlyKnownArguments(options, arguments), properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the arguments according to the specified options and properties.
|
||||||
|
* @param options the specified Options
|
||||||
|
* @param arguments the command line arguments
|
||||||
|
* @param stopAtNonOption can be ignored - an unrecognized argument is ignored, an unrecognized argument doesn't
|
||||||
|
* stop the parsing and doesn't trigger a ParseException
|
||||||
|
*
|
||||||
|
* @return the list of atomic option and value tokens
|
||||||
|
* @throws ParseException if there are any problems encountered while parsing the command line tokens.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException {
|
||||||
|
return super.parse(options, getOnlyKnownArguments(options, arguments), stopAtNonOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the arguments according to the specified options and properties.
|
||||||
|
* @param options the specified Options
|
||||||
|
* @param arguments the command line arguments
|
||||||
|
* @param properties command line option name-value pairs
|
||||||
|
* @param stopAtNonOption can be ignored - an unrecognized argument is ignored, an unrecognized argument doesn't
|
||||||
|
* stop the parsing and doesn't trigger a ParseException
|
||||||
|
*
|
||||||
|
* @return the list of atomic option and value tokens
|
||||||
|
* @throws ParseException if there are any problems encountered while parsing the command line tokens.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CommandLine parse(Options options, String[] arguments, Properties properties, boolean stopAtNonOption)
|
||||||
|
throws ParseException {
|
||||||
|
return super.parse(options, getOnlyKnownArguments(options, arguments), properties, stopAtNonOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String[] getOnlyKnownArguments(Options options, String[] arguments) {
|
||||||
|
List<String> knownArguments = new ArrayList<>();
|
||||||
|
for (String arg : arguments) {
|
||||||
|
if (options.hasOption(arg)) {
|
||||||
|
knownArguments.add(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return knownArguments.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
}
|
@@ -194,7 +194,6 @@ public class BundleServiceImpl extends DSpaceObjectServiceImpl<Bundle> implement
|
|||||||
List<Group> defaultBitstreamReadGroups =
|
List<Group> defaultBitstreamReadGroups =
|
||||||
authorizeService.getAuthorizedGroups(context, owningCollection,
|
authorizeService.getAuthorizedGroups(context, owningCollection,
|
||||||
Constants.DEFAULT_BITSTREAM_READ);
|
Constants.DEFAULT_BITSTREAM_READ);
|
||||||
log.info(defaultBitstreamReadGroups.size());
|
|
||||||
// If this collection is configured with a DEFAULT_BITSTREAM_READ group, overwrite the READ policy
|
// If this collection is configured with a DEFAULT_BITSTREAM_READ group, overwrite the READ policy
|
||||||
// inherited from the bundle with this policy.
|
// inherited from the bundle with this policy.
|
||||||
if (!defaultBitstreamReadGroups.isEmpty()) {
|
if (!defaultBitstreamReadGroups.isEmpty()) {
|
||||||
|
@@ -21,7 +21,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import javax.activation.DataHandler;
|
import javax.activation.DataHandler;
|
||||||
@@ -41,7 +40,6 @@ import javax.mail.internet.MimeMessage;
|
|||||||
import javax.mail.internet.MimeMultipart;
|
import javax.mail.internet.MimeMultipart;
|
||||||
import javax.mail.internet.ParseException;
|
import javax.mail.internet.ParseException;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.velocity.Template;
|
import org.apache.velocity.Template;
|
||||||
@@ -57,26 +55,40 @@ import org.dspace.services.ConfigurationService;
|
|||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing an e-mail message, also used to send e-mails.
|
* Class representing an e-mail message. The {@link send} method causes the
|
||||||
|
* assembled message to be formatted and sent.
|
||||||
* <p>
|
* <p>
|
||||||
* Typical use:
|
* Typical use:
|
||||||
* </p>
|
* <pre>
|
||||||
|
* <code>Email email = Email.getEmail(path);</code>
|
||||||
|
* <code>email.addRecipient("foo@bar.com");</code>
|
||||||
|
* <code>email.addArgument("John");</code>
|
||||||
|
* <code>email.addArgument("On the Testing of DSpace");</code>
|
||||||
|
* <code>email.send();</code>
|
||||||
|
* </pre>
|
||||||
|
* {@code path} is the filesystem path of an email template, typically in
|
||||||
|
* {@code ${dspace.dir}/config/emails/} and can include the subject -- see
|
||||||
|
* below. Templates are processed by <a href='https://velocity.apache.org/'>
|
||||||
|
* Apache Velocity</a>. They may contain VTL directives and property
|
||||||
|
* placeholders.
|
||||||
* <p>
|
* <p>
|
||||||
* <code>Email email = new Email();</code><br>
|
* {@link addArgument(string)} adds a property to the {@code params} array
|
||||||
* <code>email.addRecipient("foo@bar.com");</code><br>
|
* in the Velocity context, which can be used to replace placeholder tokens
|
||||||
* <code>email.addArgument("John");</code><br>
|
* in the message. These arguments are indexed by number in the order they were
|
||||||
* <code>email.addArgument("On the Testing of DSpace");</code><br>
|
* added to the message.
|
||||||
* <code>email.send();</code><br>
|
|
||||||
* </p>
|
|
||||||
* <p>
|
* <p>
|
||||||
* <code>name</code> is the name of an email template in
|
* The DSpace configuration properties are also available to templates as the
|
||||||
* <code>dspace-dir/config/emails/</code> (which also includes the subject.)
|
* array {@code config}, indexed by name. Example: {@code ${config.get('dspace.name')}}
|
||||||
* <code>arg0</code> and <code>arg1</code> are arguments to fill out the
|
* <p>
|
||||||
* message with.
|
* Recipients and attachments may be added as needed. See {@link addRecipient},
|
||||||
* <P>
|
* {@link addAttachment(File, String)}, and
|
||||||
* Emails are formatted using Apache Velocity. Headers such as Subject may be
|
* {@link addAttachment(InputStream, String, String)}.
|
||||||
* supplied by the template, by defining them using #set(). Example:
|
* <p>
|
||||||
* </p>
|
* Headers such as Subject may be supplied by the template, by defining them
|
||||||
|
* using the VTL directive {@code #set()}. Only headers named in the DSpace
|
||||||
|
* configuration array property {@code mail.message.headers} will be added.
|
||||||
|
* <p>
|
||||||
|
* Example:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
@@ -91,12 +103,14 @@ import org.dspace.services.factory.DSpaceServicesFactory;
|
|||||||
*
|
*
|
||||||
* Thank you for sending us your submission "${params[1]}".
|
* Thank you for sending us your submission "${params[1]}".
|
||||||
*
|
*
|
||||||
|
* --
|
||||||
|
* The ${config.get('dspace.name')} Team
|
||||||
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If the example code above was used to send this mail, the resulting mail
|
* If the example code above was used to send this mail, the resulting mail
|
||||||
* would have the subject <code>Example e-mail</code> and the body would be:
|
* would have the subject <code>Example e-mail</code> and the body would be:
|
||||||
* </p>
|
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
@@ -105,7 +119,16 @@ import org.dspace.services.factory.DSpaceServicesFactory;
|
|||||||
*
|
*
|
||||||
* Thank you for sending us your submission "On the Testing of DSpace".
|
* Thank you for sending us your submission "On the Testing of DSpace".
|
||||||
*
|
*
|
||||||
|
* --
|
||||||
|
* The DSpace Team
|
||||||
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* There are two ways to load a message body. One can create an instance of
|
||||||
|
* {@link Email} and call {@link setContent} on it, passing the body as a String. Or
|
||||||
|
* one can use the static factory method {@link getEmail} to load a file by its
|
||||||
|
* complete filesystem path. In either case the text will be loaded into a
|
||||||
|
* Velocity template.
|
||||||
*
|
*
|
||||||
* @author Robert Tansley
|
* @author Robert Tansley
|
||||||
* @author Jim Downing - added attachment handling code
|
* @author Jim Downing - added attachment handling code
|
||||||
@@ -115,7 +138,6 @@ public class Email {
|
|||||||
/**
|
/**
|
||||||
* The content of the message
|
* The content of the message
|
||||||
*/
|
*/
|
||||||
private String content;
|
|
||||||
private String contentName;
|
private String contentName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,13 +198,12 @@ public class Email {
|
|||||||
moreAttachments = new ArrayList<>(10);
|
moreAttachments = new ArrayList<>(10);
|
||||||
subject = "";
|
subject = "";
|
||||||
template = null;
|
template = null;
|
||||||
content = "";
|
|
||||||
replyTo = null;
|
replyTo = null;
|
||||||
charset = null;
|
charset = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a recipient
|
* Add a recipient.
|
||||||
*
|
*
|
||||||
* @param email the recipient's email address
|
* @param email the recipient's email address
|
||||||
*/
|
*/
|
||||||
@@ -196,16 +217,24 @@ public class Email {
|
|||||||
* "Subject:" line must be stripped.
|
* "Subject:" line must be stripped.
|
||||||
*
|
*
|
||||||
* @param name a name for this message body
|
* @param name a name for this message body
|
||||||
* @param cnt the content of the message
|
* @param content the content of the message
|
||||||
*/
|
*/
|
||||||
public void setContent(String name, String cnt) {
|
public void setContent(String name, String content) {
|
||||||
content = cnt;
|
|
||||||
contentName = name;
|
contentName = name;
|
||||||
arguments.clear();
|
arguments.clear();
|
||||||
|
|
||||||
|
VelocityEngine templateEngine = new VelocityEngine();
|
||||||
|
templateEngine.init(VELOCITY_PROPERTIES);
|
||||||
|
|
||||||
|
StringResourceRepository repo = (StringResourceRepository)
|
||||||
|
templateEngine.getApplicationAttribute(RESOURCE_REPOSITORY_NAME);
|
||||||
|
repo.putStringResource(contentName, content);
|
||||||
|
// Turn content into a template.
|
||||||
|
template = templateEngine.getTemplate(contentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the subject of the message
|
* Set the subject of the message.
|
||||||
*
|
*
|
||||||
* @param s the subject of the message
|
* @param s the subject of the message
|
||||||
*/
|
*/
|
||||||
@@ -214,7 +243,7 @@ public class Email {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the reply-to email address
|
* Set the reply-to email address.
|
||||||
*
|
*
|
||||||
* @param email the reply-to email address
|
* @param email the reply-to email address
|
||||||
*/
|
*/
|
||||||
@@ -223,7 +252,7 @@ public class Email {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill out the next argument in the template
|
* Fill out the next argument in the template.
|
||||||
*
|
*
|
||||||
* @param arg the value for the next argument
|
* @param arg the value for the next argument
|
||||||
*/
|
*/
|
||||||
@@ -231,6 +260,13 @@ public class Email {
|
|||||||
arguments.add(arg);
|
arguments.add(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an attachment bodypart to the message from an external file.
|
||||||
|
*
|
||||||
|
* @param f reference to a file to be attached.
|
||||||
|
* @param name a name for the resulting bodypart in the message's MIME
|
||||||
|
* structure.
|
||||||
|
*/
|
||||||
public void addAttachment(File f, String name) {
|
public void addAttachment(File f, String name) {
|
||||||
attachments.add(new FileAttachment(f, name));
|
attachments.add(new FileAttachment(f, name));
|
||||||
}
|
}
|
||||||
@@ -238,6 +274,17 @@ public class Email {
|
|||||||
/** When given a bad MIME type for an attachment, use this instead. */
|
/** When given a bad MIME type for an attachment, use this instead. */
|
||||||
private static final String DEFAULT_ATTACHMENT_TYPE = "application/octet-stream";
|
private static final String DEFAULT_ATTACHMENT_TYPE = "application/octet-stream";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an attachment bodypart to the message from a byte stream.
|
||||||
|
*
|
||||||
|
* @param is the content of this stream will become the content of the
|
||||||
|
* bodypart.
|
||||||
|
* @param name a name for the resulting bodypart in the message's MIME
|
||||||
|
* structure.
|
||||||
|
* @param mimetype the MIME type of the resulting bodypart, such as
|
||||||
|
* "text/pdf". If {@code null} it will default to
|
||||||
|
* "application/octet-stream", which is MIME for "unknown format".
|
||||||
|
*/
|
||||||
public void addAttachment(InputStream is, String name, String mimetype) {
|
public void addAttachment(InputStream is, String name, String mimetype) {
|
||||||
if (null == mimetype) {
|
if (null == mimetype) {
|
||||||
LOG.error("Null MIME type replaced with '" + DEFAULT_ATTACHMENT_TYPE
|
LOG.error("Null MIME type replaced with '" + DEFAULT_ATTACHMENT_TYPE
|
||||||
@@ -257,6 +304,11 @@ public class Email {
|
|||||||
moreAttachments.add(new InputStreamAttachment(is, name, mimetype));
|
moreAttachments.add(new InputStreamAttachment(is, name, mimetype));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the character set of the message.
|
||||||
|
*
|
||||||
|
* @param cs the name of a character set, such as "UTF-8" or "EUC-JP".
|
||||||
|
*/
|
||||||
public void setCharset(String cs) {
|
public void setCharset(String cs) {
|
||||||
charset = cs;
|
charset = cs;
|
||||||
}
|
}
|
||||||
@@ -280,15 +332,20 @@ public class Email {
|
|||||||
* {@code mail.message.headers} then that name and its value will be added
|
* {@code mail.message.headers} then that name and its value will be added
|
||||||
* to the message's headers.
|
* to the message's headers.
|
||||||
*
|
*
|
||||||
* <p>"subject" is treated specially: if {@link setSubject()} has not been called,
|
* <p>"subject" is treated specially: if {@link setSubject()} has not been
|
||||||
* the value of any "subject" property will be used as if setSubject had
|
* called, the value of any "subject" property will be used as if setSubject
|
||||||
* been called with that value. Thus a template may define its subject, but
|
* had been called with that value. Thus a template may define its subject,
|
||||||
* the caller may override it.
|
* but the caller may override it.
|
||||||
*
|
*
|
||||||
* @throws MessagingException if there was a problem sending the mail.
|
* @throws MessagingException if there was a problem sending the mail.
|
||||||
* @throws IOException if IO error
|
* @throws IOException if IO error
|
||||||
*/
|
*/
|
||||||
public void send() throws MessagingException, IOException {
|
public void send() throws MessagingException, IOException {
|
||||||
|
if (null == template) {
|
||||||
|
// No template -- no content -- PANIC!!!
|
||||||
|
throw new MessagingException("Email has no body");
|
||||||
|
}
|
||||||
|
|
||||||
ConfigurationService config
|
ConfigurationService config
|
||||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
@@ -308,37 +365,18 @@ public class Email {
|
|||||||
MimeMessage message = new MimeMessage(session);
|
MimeMessage message = new MimeMessage(session);
|
||||||
|
|
||||||
// Set the recipients of the message
|
// Set the recipients of the message
|
||||||
Iterator<String> i = recipients.iterator();
|
for (String recipient : recipients) {
|
||||||
|
message.addRecipient(Message.RecipientType.TO,
|
||||||
while (i.hasNext()) {
|
new InternetAddress(recipient));
|
||||||
message.addRecipient(Message.RecipientType.TO, new InternetAddress(
|
|
||||||
i.next()));
|
|
||||||
}
|
}
|
||||||
// Get headers defined by the template.
|
// Get headers defined by the template.
|
||||||
String[] templateHeaders = config.getArrayProperty("mail.message.headers");
|
String[] templateHeaders = config.getArrayProperty("mail.message.headers");
|
||||||
|
|
||||||
// Format the mail message body
|
// Format the mail message body
|
||||||
VelocityEngine templateEngine = new VelocityEngine();
|
|
||||||
templateEngine.init(VELOCITY_PROPERTIES);
|
|
||||||
|
|
||||||
VelocityContext vctx = new VelocityContext();
|
VelocityContext vctx = new VelocityContext();
|
||||||
vctx.put("config", new UnmodifiableConfigurationService(config));
|
vctx.put("config", new UnmodifiableConfigurationService(config));
|
||||||
vctx.put("params", Collections.unmodifiableList(arguments));
|
vctx.put("params", Collections.unmodifiableList(arguments));
|
||||||
|
|
||||||
if (null == template) {
|
|
||||||
if (StringUtils.isBlank(content)) {
|
|
||||||
// No template and no content -- PANIC!!!
|
|
||||||
throw new MessagingException("Email has no body");
|
|
||||||
}
|
|
||||||
// No template, so use a String of content.
|
|
||||||
StringResourceRepository repo = (StringResourceRepository)
|
|
||||||
templateEngine.getApplicationAttribute(RESOURCE_REPOSITORY_NAME);
|
|
||||||
repo.putStringResource(contentName, content);
|
|
||||||
// Turn content into a template.
|
|
||||||
template = templateEngine.getTemplate(contentName);
|
|
||||||
templateHeaders = new String[] {};
|
|
||||||
}
|
|
||||||
|
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
try {
|
try {
|
||||||
template.merge(vctx, writer);
|
template.merge(vctx, writer);
|
||||||
@@ -405,7 +443,8 @@ public class Email {
|
|||||||
// add the stream
|
// add the stream
|
||||||
messageBodyPart = new MimeBodyPart();
|
messageBodyPart = new MimeBodyPart();
|
||||||
messageBodyPart.setDataHandler(new DataHandler(
|
messageBodyPart.setDataHandler(new DataHandler(
|
||||||
new InputStreamDataSource(attachment.name,attachment.mimetype,attachment.is)));
|
new InputStreamDataSource(attachment.name,
|
||||||
|
attachment.mimetype, attachment.is)));
|
||||||
messageBodyPart.setFileName(attachment.name);
|
messageBodyPart.setFileName(attachment.name);
|
||||||
multipart.addBodyPart(messageBodyPart);
|
multipart.addBodyPart(messageBodyPart);
|
||||||
}
|
}
|
||||||
@@ -447,6 +486,9 @@ public class Email {
|
|||||||
/**
|
/**
|
||||||
* Get the VTL template for an email message. The message is suitable
|
* Get the VTL template for an email message. The message is suitable
|
||||||
* for inserting values using Apache Velocity.
|
* for inserting values using Apache Velocity.
|
||||||
|
* <p>
|
||||||
|
* Note that everything is stored here, so that only send() throws a
|
||||||
|
* MessagingException.
|
||||||
*
|
*
|
||||||
* @param emailFile
|
* @param emailFile
|
||||||
* full name for the email template, for example "/dspace/config/emails/register".
|
* full name for the email template, for example "/dspace/config/emails/register".
|
||||||
@@ -484,15 +526,6 @@ public class Email {
|
|||||||
}
|
}
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Implementation note: It might be necessary to add a quick utility method
|
|
||||||
* like "send(to, subject, message)". We'll see how far we get without it -
|
|
||||||
* having all emails as templates in the config allows customisation and
|
|
||||||
* internationalisation.
|
|
||||||
*
|
|
||||||
* Note that everything is stored and the run in send() so that only send()
|
|
||||||
* throws a MessagingException.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test method to send an email to check email server settings
|
* Test method to send an email to check email server settings
|
||||||
@@ -547,7 +580,7 @@ public class Email {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility struct class for handling file attachments.
|
* Utility record class for handling file attachments.
|
||||||
*
|
*
|
||||||
* @author ojd20
|
* @author ojd20
|
||||||
*/
|
*/
|
||||||
@@ -563,7 +596,7 @@ public class Email {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility struct class for handling file attachments.
|
* Utility record class for handling file attachments.
|
||||||
*
|
*
|
||||||
* @author Adán Román Ruiz at arvo.es
|
* @author Adán Román Ruiz at arvo.es
|
||||||
*/
|
*/
|
||||||
@@ -580,6 +613,8 @@ public class Email {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Wrap an {@link InputStream} in a {@link DataSource}.
|
||||||
|
*
|
||||||
* @author arnaldo
|
* @author arnaldo
|
||||||
*/
|
*/
|
||||||
public static class InputStreamDataSource implements DataSource {
|
public static class InputStreamDataSource implements DataSource {
|
||||||
@@ -587,6 +622,14 @@ public class Email {
|
|||||||
private final String contentType;
|
private final String contentType;
|
||||||
private final ByteArrayOutputStream baos;
|
private final ByteArrayOutputStream baos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume the content of an InputStream and store it in a local buffer.
|
||||||
|
*
|
||||||
|
* @param name give the DataSource a name.
|
||||||
|
* @param contentType the DataSource contains this type of data.
|
||||||
|
* @param inputStream content to be buffered in the DataSource.
|
||||||
|
* @throws IOException if the stream cannot be read.
|
||||||
|
*/
|
||||||
InputStreamDataSource(String name, String contentType, InputStream inputStream) throws IOException {
|
InputStreamDataSource(String name, String contentType, InputStream inputStream) throws IOException {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.contentType = contentType;
|
this.contentType = contentType;
|
||||||
|
@@ -174,15 +174,22 @@ public class LicenseServiceImpl implements LicenseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtaining current request context
|
* Obtaining current request context.
|
||||||
|
* Return new context if getting one from current request failed.
|
||||||
|
*
|
||||||
|
* @return DSpace context object
|
||||||
*/
|
*/
|
||||||
private Context obtainContext() {
|
private Context obtainContext() {
|
||||||
Request currentRequest = DSpaceServicesFactory.getInstance().getRequestService().getCurrentRequest();
|
try {
|
||||||
if (currentRequest != null) {
|
Request currentRequest = DSpaceServicesFactory.getInstance().getRequestService().getCurrentRequest();
|
||||||
HttpServletRequest request = currentRequest.getHttpServletRequest();
|
if (currentRequest != null) {
|
||||||
return ContextUtil.obtainContext(request);
|
HttpServletRequest request = currentRequest.getHttpServletRequest();
|
||||||
} else {
|
return ContextUtil.obtainContext(request);
|
||||||
return new Context();
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Can't load current request context.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new Context();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -76,14 +76,19 @@ public class FullTextContentStreams extends ContentStreamBase {
|
|||||||
if (StringUtils.equals(FULLTEXT_BUNDLE, myBundle.getName())) {
|
if (StringUtils.equals(FULLTEXT_BUNDLE, myBundle.getName())) {
|
||||||
// a-ha! grab the text out of the bitstreams
|
// a-ha! grab the text out of the bitstreams
|
||||||
List<Bitstream> bitstreams = myBundle.getBitstreams();
|
List<Bitstream> bitstreams = myBundle.getBitstreams();
|
||||||
|
log.debug("Processing full-text bitstreams. Item handle: " + sourceInfo);
|
||||||
|
|
||||||
for (Bitstream fulltextBitstream : emptyIfNull(bitstreams)) {
|
for (Bitstream fulltextBitstream : emptyIfNull(bitstreams)) {
|
||||||
fullTextStreams.add(new FullTextBitstream(sourceInfo, fulltextBitstream));
|
fullTextStreams.add(new FullTextBitstream(sourceInfo, fulltextBitstream));
|
||||||
|
|
||||||
log.debug("Added BitStream: "
|
if (fulltextBitstream != null) {
|
||||||
+ fulltextBitstream.getStoreNumber() + " "
|
log.debug("Added BitStream: "
|
||||||
+ fulltextBitstream.getSequenceID() + " "
|
+ fulltextBitstream.getStoreNumber() + " "
|
||||||
+ fulltextBitstream.getName());
|
+ fulltextBitstream.getSequenceID() + " "
|
||||||
|
+ fulltextBitstream.getName());
|
||||||
|
} else {
|
||||||
|
log.error("Found a NULL bitstream when processing full-text files: item handle:" + sourceInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,16 +163,16 @@ public class FullTextContentStreams extends ContentStreamBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getContentType(final Context context) throws SQLException {
|
public String getContentType(final Context context) throws SQLException {
|
||||||
BitstreamFormat format = bitstream.getFormat(context);
|
BitstreamFormat format = bitstream != null ? bitstream.getFormat(context) : null;
|
||||||
return format == null ? null : StringUtils.trimToEmpty(format.getMIMEType());
|
return format == null ? null : StringUtils.trimToEmpty(format.getMIMEType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFileName() {
|
public String getFileName() {
|
||||||
return StringUtils.trimToEmpty(bitstream.getName());
|
return bitstream != null ? StringUtils.trimToEmpty(bitstream.getName()) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSize() {
|
public long getSize() {
|
||||||
return bitstream.getSizeBytes();
|
return bitstream != null ? bitstream.getSizeBytes() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() throws SQLException, IOException, AuthorizeException {
|
public InputStream getInputStream() throws SQLException, IOException, AuthorizeException {
|
||||||
|
@@ -172,13 +172,6 @@ public class ItemIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl<Indexable
|
|||||||
addNamedResourceTypeIndex(doc, acvalue);
|
addNamedResourceTypeIndex(doc, acvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the index and close the inputstreamreaders
|
|
||||||
try {
|
|
||||||
log.info("Wrote Item: " + item.getID() + " to Index");
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
log.error("Error while writing item to discovery index: " + item.getID() + " message:"
|
|
||||||
+ e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -141,20 +141,10 @@ public class Groomer {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
if (delete) {
|
if (delete) {
|
||||||
List<String> whyNot = ePersonService.getDeleteConstraints(myContext, account);
|
try {
|
||||||
if (!whyNot.isEmpty()) {
|
ePersonService.delete(myContext, account);
|
||||||
System.out.print("\tCannot be deleted; referenced in");
|
} catch (AuthorizeException | IOException ex) {
|
||||||
for (String table : whyNot) {
|
System.err.println(ex.getMessage());
|
||||||
System.out.print(' ');
|
|
||||||
System.out.print(table);
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
ePersonService.delete(myContext, account);
|
|
||||||
} catch (AuthorizeException | IOException ex) {
|
|
||||||
System.err.println(ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@ import org.apache.commons.cli.Option;
|
|||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.cli.DSpaceSkipUnknownArgumentsParser;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
@@ -36,6 +37,11 @@ public abstract class DSpaceRunnable<T extends ScriptConfiguration> implements R
|
|||||||
*/
|
*/
|
||||||
protected CommandLine commandLine;
|
protected CommandLine commandLine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimal CommandLine object for the script that'll hold help information
|
||||||
|
*/
|
||||||
|
protected CommandLine helpCommandLine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This EPerson identifier variable is the UUID of the EPerson that's running the script
|
* This EPerson identifier variable is the UUID of the EPerson that's running the script
|
||||||
*/
|
*/
|
||||||
@@ -64,26 +70,66 @@ public abstract class DSpaceRunnable<T extends ScriptConfiguration> implements R
|
|||||||
* @param args The arguments given to the script
|
* @param args The arguments given to the script
|
||||||
* @param dSpaceRunnableHandler The DSpaceRunnableHandler object that defines from where the script was ran
|
* @param dSpaceRunnableHandler The DSpaceRunnableHandler object that defines from where the script was ran
|
||||||
* @param currentUser
|
* @param currentUser
|
||||||
|
* @return the result of this step; StepResult.Continue: continue the normal process,
|
||||||
|
* initialize is successful; otherwise exit the process (the help or version is shown)
|
||||||
* @throws ParseException If something goes wrong
|
* @throws ParseException If something goes wrong
|
||||||
*/
|
*/
|
||||||
public void initialize(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
public StepResult initialize(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||||
EPerson currentUser) throws ParseException {
|
EPerson currentUser) throws ParseException {
|
||||||
if (currentUser != null) {
|
if (currentUser != null) {
|
||||||
this.setEpersonIdentifier(currentUser.getID());
|
this.setEpersonIdentifier(currentUser.getID());
|
||||||
}
|
}
|
||||||
this.setHandler(dSpaceRunnableHandler);
|
this.setHandler(dSpaceRunnableHandler);
|
||||||
this.parse(args);
|
|
||||||
|
// parse the command line in a first step for the help options
|
||||||
|
// --> no other option is required
|
||||||
|
StepResult result = this.parseForHelp(args);
|
||||||
|
switch (result) {
|
||||||
|
case Exit:
|
||||||
|
// arguments of the command line matches the help options, handle this
|
||||||
|
handleHelpCommandLine();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Continue:
|
||||||
|
// arguments of the command line matches NOT the help options, parse the args for the normal options
|
||||||
|
result = this.parse(args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method handle the help command line. In this easy implementation only the help is printed. For more
|
||||||
|
* complexity override this method.
|
||||||
|
*/
|
||||||
|
private void handleHelpCommandLine() {
|
||||||
|
printHelp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will take the primitive array of String objects that represent the parameters given to the String
|
* This method will take the primitive array of String objects that represent the parameters given to the String
|
||||||
* and it'll parse these into a CommandLine object that can be used by the script to retrieve the data
|
* and it'll parse these into a CommandLine object that can be used by the script to retrieve the data
|
||||||
* @param args The primitive array of Strings representing the parameters
|
* @param args The primitive array of Strings representing the parameters
|
||||||
* @throws ParseException If something goes wrong
|
* @throws ParseException If something goes wrong
|
||||||
*/
|
*/
|
||||||
private void parse(String[] args) throws ParseException {
|
private StepResult parse(String[] args) throws ParseException {
|
||||||
commandLine = new DefaultParser().parse(getScriptConfiguration().getOptions(), args);
|
commandLine = new DefaultParser().parse(getScriptConfiguration().getOptions(), args);
|
||||||
setup();
|
setup();
|
||||||
|
return StepResult.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StepResult parseForHelp(String[] args) throws ParseException {
|
||||||
|
helpCommandLine = new DSpaceSkipUnknownArgumentsParser().parse(getScriptConfiguration().getHelpOptions(), args);
|
||||||
|
if (helpCommandLine.getOptions() != null && helpCommandLine.getOptions().length > 0) {
|
||||||
|
return StepResult.Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StepResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,4 +204,8 @@ public abstract class DSpaceRunnable<T extends ScriptConfiguration> implements R
|
|||||||
public void setEpersonIdentifier(UUID epersonIdentifier) {
|
public void setEpersonIdentifier(UUID epersonIdentifier) {
|
||||||
this.epersonIdentifier = epersonIdentifier;
|
this.epersonIdentifier = epersonIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum StepResult {
|
||||||
|
Continue, Exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@ package org.dspace.scripts.configuration;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.dspace.authorize.service.AuthorizeService;
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
@@ -105,6 +106,19 @@ public abstract class ScriptConfiguration<T extends DSpaceRunnable> implements B
|
|||||||
*/
|
*/
|
||||||
public abstract Options getOptions();
|
public abstract Options getOptions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The getter for the options of the Script (help informations)
|
||||||
|
*
|
||||||
|
* @return the options value of this ScriptConfiguration for help
|
||||||
|
*/
|
||||||
|
public Options getHelpOptions() {
|
||||||
|
Options options = new Options();
|
||||||
|
|
||||||
|
options.addOption(Option.builder("h").longOpt("help").desc("help").hasArg(false).required(false).build());
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBeanName(String beanName) {
|
public void setBeanName(String beanName) {
|
||||||
this.name = beanName;
|
this.name = beanName;
|
||||||
|
@@ -37,7 +37,7 @@ public class GeoIpService {
|
|||||||
public DatabaseReader getDatabaseReader() throws IllegalStateException {
|
public DatabaseReader getDatabaseReader() throws IllegalStateException {
|
||||||
String dbPath = configurationService.getProperty("usage-statistics.dbfile");
|
String dbPath = configurationService.getProperty("usage-statistics.dbfile");
|
||||||
if (StringUtils.isBlank(dbPath)) {
|
if (StringUtils.isBlank(dbPath)) {
|
||||||
throw new IllegalStateException("The required 'dbfile' configuration is missing in solr-statistics.cfg!");
|
throw new IllegalStateException("The required 'dbfile' configuration is missing in usage-statistics.cfg!");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@@ -1203,22 +1203,6 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void optimizeSOLR() {
|
|
||||||
try {
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
System.out.println("SOLR Optimize -- Process Started:" + start);
|
|
||||||
solr.optimize();
|
|
||||||
long finish = System.currentTimeMillis();
|
|
||||||
System.out.println("SOLR Optimize -- Process Finished:" + finish);
|
|
||||||
System.out.println("SOLR Optimize -- Total time taken:" + (finish - start) + " (ms).");
|
|
||||||
} catch (SolrServerException sse) {
|
|
||||||
System.err.println(sse.getMessage());
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
System.err.println(ioe.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shardSolrIndex() throws IOException, SolrServerException {
|
public void shardSolrIndex() throws IOException, SolrServerException {
|
||||||
if (!(solr instanceof HttpSolrClient)) {
|
if (!(solr instanceof HttpSolrClient)) {
|
||||||
@@ -1691,11 +1675,14 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
|||||||
statisticYearCores
|
statisticYearCores
|
||||||
.add(baseSolrUrl.replace("http://", "").replace("https://", "") + statCoreName);
|
.add(baseSolrUrl.replace("http://", "").replace("https://", "") + statCoreName);
|
||||||
}
|
}
|
||||||
//Also add the core containing the current year !
|
var baseCore = ((HttpSolrClient) solr)
|
||||||
statisticYearCores.add(((HttpSolrClient) solr)
|
|
||||||
.getBaseURL()
|
.getBaseURL()
|
||||||
.replace("http://", "")
|
.replace("http://", "")
|
||||||
.replace("https://", ""));
|
.replace("https://", "");
|
||||||
|
if (!statisticYearCores.contains(baseCore)) {
|
||||||
|
//Also add the core containing the current year, if it hasn't been added already
|
||||||
|
statisticYearCores.add(baseCore);
|
||||||
|
}
|
||||||
} catch (IOException | SolrServerException e) {
|
} catch (IOException | SolrServerException e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
@@ -266,12 +266,6 @@ public interface SolrLoggerService {
|
|||||||
*/
|
*/
|
||||||
public String getIgnoreSpiderIPs();
|
public String getIgnoreSpiderIPs();
|
||||||
|
|
||||||
/**
|
|
||||||
* Maintenance to keep a SOLR index efficient.
|
|
||||||
* Note: This might take a long time.
|
|
||||||
*/
|
|
||||||
public void optimizeSOLR();
|
|
||||||
|
|
||||||
public void shardSolrIndex() throws IOException, SolrServerException;
|
public void shardSolrIndex() throws IOException, SolrServerException;
|
||||||
|
|
||||||
public void reindexBitstreamHits(boolean removeDeletedBitstreams) throws Exception;
|
public void reindexBitstreamHits(boolean removeDeletedBitstreams) throws Exception;
|
||||||
|
@@ -67,7 +67,6 @@ public class StatisticsClient {
|
|||||||
options.addOption("m", "mark-spiders", false, "Update isBot Flag in Solr");
|
options.addOption("m", "mark-spiders", false, "Update isBot Flag in Solr");
|
||||||
options.addOption("f", "delete-spiders-by-flag", false, "Delete Spiders in Solr By isBot Flag");
|
options.addOption("f", "delete-spiders-by-flag", false, "Delete Spiders in Solr By isBot Flag");
|
||||||
options.addOption("i", "delete-spiders-by-ip", false, "Delete Spiders in Solr By IP Address");
|
options.addOption("i", "delete-spiders-by-ip", false, "Delete Spiders in Solr By IP Address");
|
||||||
options.addOption("o", "optimize", false, "Run maintenance on the SOLR index");
|
|
||||||
options.addOption("b", "reindex-bitstreams", false, "Reindex the bitstreams to ensure we have the bundle name");
|
options.addOption("b", "reindex-bitstreams", false, "Reindex the bitstreams to ensure we have the bundle name");
|
||||||
options.addOption("e", "export", false,
|
options.addOption("e", "export", false,
|
||||||
"Export SOLR view statistics data to usage-statistics-intermediate-format");
|
"Export SOLR view statistics data to usage-statistics-intermediate-format");
|
||||||
@@ -93,8 +92,6 @@ public class StatisticsClient {
|
|||||||
solrLoggerService.deleteRobotsByIsBotFlag();
|
solrLoggerService.deleteRobotsByIsBotFlag();
|
||||||
} else if (line.hasOption('i')) {
|
} else if (line.hasOption('i')) {
|
||||||
solrLoggerService.deleteRobotsByIP();
|
solrLoggerService.deleteRobotsByIP();
|
||||||
} else if (line.hasOption('o')) {
|
|
||||||
solrLoggerService.optimizeSOLR();
|
|
||||||
} else if (line.hasOption('b')) {
|
} else if (line.hasOption('b')) {
|
||||||
solrLoggerService.reindexBitstreamHits(line.hasOption('r'));
|
solrLoggerService.reindexBitstreamHits(line.hasOption('r'));
|
||||||
} else if (line.hasOption('e')) {
|
} else if (line.hasOption('e')) {
|
||||||
|
43
dspace-api/src/main/java/org/dspace/util/ThrowableUtils.java
Normal file
43
dspace-api/src/main/java/org/dspace/util/ThrowableUtils.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Things you wish {@link Throwable} or some logging package would do for you.
|
||||||
|
*
|
||||||
|
* @author mwood
|
||||||
|
*/
|
||||||
|
public class ThrowableUtils {
|
||||||
|
/**
|
||||||
|
* Utility class: do not instantiate.
|
||||||
|
*/
|
||||||
|
private ThrowableUtils() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace a chain of {@code Throwable}s showing only causes.
|
||||||
|
* Less voluminous than a stack trace. Useful if you just want to know
|
||||||
|
* what caused third-party code to return an uninformative exception
|
||||||
|
* message.
|
||||||
|
*
|
||||||
|
* @param throwable the exception or whatever.
|
||||||
|
* @return list of messages from each {@code Throwable} in the chain,
|
||||||
|
* separated by '\n'.
|
||||||
|
*/
|
||||||
|
static public String formatCauseChain(Throwable throwable) {
|
||||||
|
StringBuilder trace = new StringBuilder();
|
||||||
|
trace.append(throwable.getMessage());
|
||||||
|
Throwable cause = throwable.getCause();
|
||||||
|
while (null != cause) {
|
||||||
|
trace.append("\nCaused by: ")
|
||||||
|
.append(cause.getClass().getCanonicalName()).append(' ')
|
||||||
|
.append(cause.getMessage());
|
||||||
|
cause = cause.getCause();
|
||||||
|
}
|
||||||
|
return trace.toString();
|
||||||
|
}
|
||||||
|
}
|
@@ -99,8 +99,9 @@ public class MetadataExportIT
|
|||||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||||
}
|
}
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||||
script.run();
|
script.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,8 +207,9 @@ public class MetadataExportIT
|
|||||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||||
}
|
}
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||||
script.run();
|
script.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Exception exceptionDuringTestRun = testDSpaceRunnableHandler.getException();
|
Exception exceptionDuringTestRun = testDSpaceRunnableHandler.getException();
|
||||||
@@ -235,8 +237,9 @@ public class MetadataExportIT
|
|||||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||||
}
|
}
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||||
script.run();
|
script.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Exception exceptionDuringTestRun = testDSpaceRunnableHandler.getException();
|
Exception exceptionDuringTestRun = testDSpaceRunnableHandler.getException();
|
||||||
|
@@ -144,8 +144,9 @@ public class MetadataImportIT extends AbstractIntegrationTestWithDatabase {
|
|||||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||||
}
|
}
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||||
script.run();
|
script.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -702,8 +702,10 @@ public class CSVMetadataImportReferenceIT extends AbstractIntegrationTestWithDat
|
|||||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||||
}
|
}
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
if (DSpaceRunnable.StepResult.Continue
|
||||||
script.run();
|
.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||||
|
script.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (testDSpaceRunnableHandler.getException() != null) {
|
if (testDSpaceRunnableHandler.getException() != null) {
|
||||||
throw testDSpaceRunnableHandler.getException();
|
throw testDSpaceRunnableHandler.getException();
|
||||||
|
103
dspace-api/src/test/java/org/dspace/browse/CrossLinksTest.java
Normal file
103
dspace-api/src/test/java/org/dspace/browse/CrossLinksTest.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* 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.browse;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
import org.dspace.AbstractDSpaceTest;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for {@link CrossLinks}
|
||||||
|
*/
|
||||||
|
public class CrossLinksTest extends AbstractDSpaceTest {
|
||||||
|
protected ConfigurationService configurationService;
|
||||||
|
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
configurationService = new DSpace().getConfigurationService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindLinkType_Null() throws Exception {
|
||||||
|
CrossLinks crossLinks = new CrossLinks();
|
||||||
|
assertNull(crossLinks.findLinkType(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindLinkType_NoMatch() throws Exception {
|
||||||
|
CrossLinks crossLinks = new CrossLinks();
|
||||||
|
String metadataField = "foo.bar.baz.does.not.exist";
|
||||||
|
assertNull(crossLinks.findLinkType(metadataField));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindLinkType_WildcardMatch() throws Exception {
|
||||||
|
configurationService.setProperty("webui.browse.link.1", "author:dc.contributor.*");
|
||||||
|
CrossLinks crossLinks = new CrossLinks();
|
||||||
|
|
||||||
|
String metadataField = "dc.contributor.author";
|
||||||
|
assertEquals("author",crossLinks.findLinkType(metadataField));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindLinkType_SingleExactMatch_Author() throws Exception {
|
||||||
|
configurationService.setProperty("webui.browse.link.1", "author:dc.contributor.author");
|
||||||
|
CrossLinks crossLinks = new CrossLinks();
|
||||||
|
|
||||||
|
assertEquals("type",crossLinks.findLinkType("dc.genre"));
|
||||||
|
assertEquals("author",crossLinks.findLinkType("dc.contributor.author"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindLinkType_SingleExactMatch_Type() throws Exception {
|
||||||
|
configurationService.setProperty("webui.browse.link.1", "type:dc.genre");
|
||||||
|
CrossLinks crossLinks = new CrossLinks();
|
||||||
|
|
||||||
|
assertEquals("type",crossLinks.findLinkType("dc.genre"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindLinkType_MultipleExactMatches_DifferentIndexes() throws Exception {
|
||||||
|
configurationService.setProperty("webui.browse.link.1", "author:dc.contributor.author");
|
||||||
|
configurationService.setProperty("webui.browse.link.2", "type:dc.genre");
|
||||||
|
CrossLinks crossLinks = new CrossLinks();
|
||||||
|
|
||||||
|
assertEquals("author",crossLinks.findLinkType("dc.contributor.author"));
|
||||||
|
assertEquals("type",crossLinks.findLinkType("dc.genre"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindLinkType_MultipleWildcardMatches_DifferentIndexes() throws Exception {
|
||||||
|
configurationService.setProperty("webui.browse.link.1", "author:dc.contributor.*");
|
||||||
|
configurationService.setProperty("webui.browse.link.2", "subject:dc.subject.*");
|
||||||
|
CrossLinks crossLinks = new CrossLinks();
|
||||||
|
|
||||||
|
assertEquals("author",crossLinks.findLinkType("dc.contributor.author"));
|
||||||
|
assertEquals("subject",crossLinks.findLinkType("dc.subject.lcsh"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindLinkType_MultiplExactAndWildcardMatches_DifferentIndexes() throws Exception {
|
||||||
|
configurationService.setProperty("webui.browse.link.1", "author:dc.contributor.*");
|
||||||
|
configurationService.setProperty("webui.browse.link.2", "subject:dc.subject.*");
|
||||||
|
configurationService.setProperty("webui.browse.link.3", "type:dc.genre");
|
||||||
|
configurationService.setProperty("webui.browse.link.4", "dateissued:dc.date.issued");
|
||||||
|
CrossLinks crossLinks = new CrossLinks();
|
||||||
|
|
||||||
|
assertEquals("author",crossLinks.findLinkType("dc.contributor.author"));
|
||||||
|
assertEquals("subject",crossLinks.findLinkType("dc.subject.lcsh"));
|
||||||
|
assertEquals("type",crossLinks.findLinkType("dc.genre"));
|
||||||
|
assertEquals("dateissued",crossLinks.findLinkType("dc.date.issued"));
|
||||||
|
}
|
||||||
|
}
|
@@ -43,8 +43,9 @@ public class CurationIT extends AbstractIntegrationTestWithDatabase {
|
|||||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||||
}
|
}
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||||
script.run();
|
script.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,8 +70,9 @@ public class CurationIT extends AbstractIntegrationTestWithDatabase {
|
|||||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||||
}
|
}
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||||
script.run();
|
script.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -103,6 +103,11 @@ public class ItemUtils {
|
|||||||
bundle.getElement().add(bitstreams);
|
bundle.getElement().add(bitstreams);
|
||||||
List<Bitstream> bits = b.getBitstreams();
|
List<Bitstream> bits = b.getBitstreams();
|
||||||
for (Bitstream bit : bits) {
|
for (Bitstream bit : bits) {
|
||||||
|
// Check if bitstream is null and log the error
|
||||||
|
if (bit == null) {
|
||||||
|
log.error("Null bitstream found, check item uuid: " + item.getID());
|
||||||
|
break;
|
||||||
|
}
|
||||||
Element bitstream = create("bitstream");
|
Element bitstream = create("bitstream");
|
||||||
bitstreams.getElement().add(bitstream);
|
bitstreams.getElement().add(bitstream);
|
||||||
String url = "";
|
String url = "";
|
||||||
|
@@ -10,7 +10,7 @@ This webapp uses the following technologies:
|
|||||||
We don't use Spring Data REST as we haven't a spring data layer and we want to provide clear separation between the persistence representation and the REST representation
|
We don't use Spring Data REST as we haven't a spring data layer and we want to provide clear separation between the persistence representation and the REST representation
|
||||||
|
|
||||||
## How to contribute
|
## How to contribute
|
||||||
Check the infomation available on the DSpace Official Wiki page for the [DSpace 7 Working Group](https://wiki.duraspace.org/display/DSPACE/DSpace+7+UI+Working+Group)
|
Check the information available on the DSpace Official Wiki page for the [DSpace 7 Working Group](https://wiki.duraspace.org/display/DSPACE/DSpace+7+UI+Working+Group)
|
||||||
|
|
||||||
[DSpace 7 REST: Coding DSpace Objects](https://wiki.duraspace.org/display/DSPACE/DSpace+7+REST%3A+Coding+DSpace+Objects)
|
[DSpace 7 REST: Coding DSpace Objects](https://wiki.duraspace.org/display/DSPACE/DSpace+7+REST%3A+Coding+DSpace+Objects)
|
||||||
|
|
||||||
|
@@ -132,7 +132,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
|||||||
Exception ex) throws IOException {
|
Exception ex) throws IOException {
|
||||||
//422 is not defined in HttpServletResponse. Its meaning is "Unprocessable Entity".
|
//422 is not defined in HttpServletResponse. Its meaning is "Unprocessable Entity".
|
||||||
//Using the value from HttpStatus.
|
//Using the value from HttpStatus.
|
||||||
sendErrorResponse(request, response, null,
|
sendErrorResponse(request, response, ex,
|
||||||
"Unprocessable or invalid entity",
|
"Unprocessable or invalid entity",
|
||||||
HttpStatus.UNPROCESSABLE_ENTITY.value());
|
HttpStatus.UNPROCESSABLE_ENTITY.value());
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
|||||||
@ExceptionHandler( {InvalidSearchRequestException.class})
|
@ExceptionHandler( {InvalidSearchRequestException.class})
|
||||||
protected void handleInvalidSearchRequestException(HttpServletRequest request, HttpServletResponse response,
|
protected void handleInvalidSearchRequestException(HttpServletRequest request, HttpServletResponse response,
|
||||||
Exception ex) throws IOException {
|
Exception ex) throws IOException {
|
||||||
sendErrorResponse(request, response, null,
|
sendErrorResponse(request, response, ex,
|
||||||
"Invalid search request",
|
"Invalid search request",
|
||||||
HttpStatus.UNPROCESSABLE_ENTITY.value());
|
HttpStatus.UNPROCESSABLE_ENTITY.value());
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
|||||||
TranslatableException ex) throws IOException {
|
TranslatableException ex) throws IOException {
|
||||||
Context context = ContextUtil.obtainContext(request);
|
Context context = ContextUtil.obtainContext(request);
|
||||||
sendErrorResponse(
|
sendErrorResponse(
|
||||||
request, response, null, ex.getLocalizedMessage(context), HttpStatus.UNPROCESSABLE_ENTITY.value()
|
request, response, (Exception) ex, ex.getLocalizedMessage(context), HttpStatus.UNPROCESSABLE_ENTITY.value()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
|||||||
protected void ParameterConversionException(HttpServletRequest request, HttpServletResponse response, Exception ex)
|
protected void ParameterConversionException(HttpServletRequest request, HttpServletResponse response, Exception ex)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
// we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428
|
// we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428
|
||||||
sendErrorResponse(request, response, null,
|
sendErrorResponse(request, response, ex,
|
||||||
"A required parameter is invalid",
|
"A required parameter is invalid",
|
||||||
HttpStatus.BAD_REQUEST.value());
|
HttpStatus.BAD_REQUEST.value());
|
||||||
}
|
}
|
||||||
@@ -197,7 +197,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
|||||||
protected void MissingParameterException(HttpServletRequest request, HttpServletResponse response, Exception ex)
|
protected void MissingParameterException(HttpServletRequest request, HttpServletResponse response, Exception ex)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
// we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428
|
// we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428
|
||||||
sendErrorResponse(request, response, null,
|
sendErrorResponse(request, response, ex,
|
||||||
"A required parameter is missing",
|
"A required parameter is missing",
|
||||||
HttpStatus.BAD_REQUEST.value());
|
HttpStatus.BAD_REQUEST.value());
|
||||||
}
|
}
|
||||||
|
@@ -67,7 +67,7 @@ public class HealthIndicatorsIT extends AbstractControllerIntegrationTest {
|
|||||||
match("solrSearchCore", Status.UP, Map.of("status", 0, "detectedPathType", "root")),
|
match("solrSearchCore", Status.UP, Map.of("status", 0, "detectedPathType", "root")),
|
||||||
match("solrStatisticsCore", Status.UP, Map.of("status", 0, "detectedPathType", "root")),
|
match("solrStatisticsCore", Status.UP, Map.of("status", 0, "detectedPathType", "root")),
|
||||||
match("geoIp", UP_WITH_ISSUES_STATUS,
|
match("geoIp", UP_WITH_ISSUES_STATUS,
|
||||||
Map.of("reason", "The required 'dbfile' configuration is missing in solr-statistics.cfg!"))
|
Map.of("reason", "The required 'dbfile' configuration is missing in usage-statistics.cfg!"))
|
||||||
)));
|
)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1460,9 +1460,6 @@ log.report.dir = ${dspace.dir}/log
|
|||||||
# fields at least the date and title fields as specified by the
|
# fields at least the date and title fields as specified by the
|
||||||
# webui.browse.index.* configuration options below.
|
# webui.browse.index.* configuration options below.
|
||||||
#
|
#
|
||||||
# If you have enabled thumbnails (webui.browse.thumbnail.show), you must also
|
|
||||||
# include a 'thumbnail' entry in your columns - this is where the thumbnail will be displayed
|
|
||||||
#
|
|
||||||
# If you want to mark each item include a 'mark_[value]' (without the brackets - replace the word 'value' with anything that
|
# If you want to mark each item include a 'mark_[value]' (without the brackets - replace the word 'value' with anything that
|
||||||
# has a meaning for your mark) entry in your columns - this is where the icon will be displayed.
|
# has a meaning for your mark) entry in your columns - this is where the icon will be displayed.
|
||||||
# Do not forget to add a Spring bean with id = "org.dspace.app.itemmarking.ItemMarkingExtractor.[value]"
|
# Do not forget to add a Spring bean with id = "org.dspace.app.itemmarking.ItemMarkingExtractor.[value]"
|
||||||
@@ -1470,13 +1467,8 @@ log.report.dir = ${dspace.dir}/log
|
|||||||
# You can add more than one 'mark_[value]' options (with different value) in case you need to mark items more than one time for
|
# You can add more than one 'mark_[value]' options (with different value) in case you need to mark items more than one time for
|
||||||
# different purposes. Remember to add the respective beans in file 'config/spring/api/item-marking.xml'.
|
# different purposes. Remember to add the respective beans in file 'config/spring/api/item-marking.xml'.
|
||||||
#
|
#
|
||||||
# webui.itemlist.columns = thumbnail, dc.date.issued(date), dc.title, dc.contributor.*
|
# webui.itemlist.columns = dc.date.issued(date), dc.title, dc.contributor.*
|
||||||
#
|
#
|
||||||
# You can customise the width of each column with the following line - you can have numbers (pixels)
|
|
||||||
# or percentages. For the 'thumbnail' column, a setting of '*' will use the max width specified
|
|
||||||
# for browse thumbnails (webui.browse.thumbnail.maxwidth, thumbnail.maxwidth)
|
|
||||||
# webui.itemlist.widths = *, 130, 60%, 40%
|
|
||||||
|
|
||||||
# Additionally, you can override the DC fields used on the listing page for
|
# Additionally, you can override the DC fields used on the listing page for
|
||||||
# a given browse index and/or sort option. As a sort option or index may be defined
|
# a given browse index and/or sort option. As a sort option or index may be defined
|
||||||
# on a field that isn't normally included in the list, this allows you to display
|
# on a field that isn't normally included in the list, this allows you to display
|
||||||
@@ -1486,30 +1478,8 @@ log.report.dir = ${dspace.dir}/log
|
|||||||
# they are listed below is the priority in which they will be used (so a combination
|
# they are listed below is the priority in which they will be used (so a combination
|
||||||
# of an index name and sort name will take precedence over just the browse name).
|
# of an index name and sort name will take precedence over just the browse name).
|
||||||
#
|
#
|
||||||
# webui.itemlist.browse.<index name>.sort.<sort name>.columns
|
|
||||||
# webui.itemlist.sort.<sort name>.columns
|
# webui.itemlist.sort.<sort name>.columns
|
||||||
# webui.itemlist.browse.<browse name>.columns
|
|
||||||
# webui.itemlist.<sort or index name>.columns
|
# webui.itemlist.<sort or index name>.columns
|
||||||
#
|
|
||||||
# In the last case, a sort option name will always take precedence over a browse
|
|
||||||
# index name. Note also, that for any additional columns you list, you will need to
|
|
||||||
# ensure there is an itemlist.<field name> entry in the messages file.
|
|
||||||
#
|
|
||||||
# The following example would display the date of accession in place of the issue date
|
|
||||||
# whenever the dateaccessioned browse index or sort option is selected.
|
|
||||||
#
|
|
||||||
# Just like webui.itemlist.columns, you will need to include a 'thumbnail' entry to display
|
|
||||||
# and thumbnails in the item list
|
|
||||||
#
|
|
||||||
# webui.itemlist.dateaccessioned.columns = thumbnail, dc.date.accessioned(date), dc.title, dc.contributor.*
|
|
||||||
#
|
|
||||||
# As above, you can customise the width of the columns for each configured column list, substituting '.widths' for
|
|
||||||
# '.columns' in the property name. See the setting for webui.itemlist.widths for more details
|
|
||||||
# webui.itemlist.dateaccessioned.widths = *, 130, 60%, 40%
|
|
||||||
|
|
||||||
# You can also set the overall size of the item list table with the following setting. It can lead to faster
|
|
||||||
# table rendering when used with the column widths above, but not generally recommended.
|
|
||||||
# webui.itemlist.tablewidth = 100%
|
|
||||||
|
|
||||||
##### SFX Server (OpenURL) #####
|
##### SFX Server (OpenURL) #####
|
||||||
|
|
||||||
|
@@ -55,9 +55,7 @@
|
|||||||
- - - - - -
|
- - - - - -
|
||||||
PLEASE NOTICE THAT YOU WILL HAVE TO RESTART DSPACE
|
PLEASE NOTICE THAT YOU WILL HAVE TO RESTART DSPACE
|
||||||
- - - - - -
|
- - - - - -
|
||||||
Uncomment if you intend to use them
|
-->
|
||||||
-->
|
|
||||||
<!--
|
|
||||||
<name-map collection-entity-type="Publication" submission-name="Publication"/>
|
<name-map collection-entity-type="Publication" submission-name="Publication"/>
|
||||||
<name-map collection-entity-type="Person" submission-name="Person"/>
|
<name-map collection-entity-type="Person" submission-name="Person"/>
|
||||||
<name-map collection-entity-type="Project" submission-name="Project"/>
|
<name-map collection-entity-type="Project" submission-name="Project"/>
|
||||||
@@ -65,8 +63,6 @@
|
|||||||
<name-map collection-entity-type="Journal" submission-name="Journal"/>
|
<name-map collection-entity-type="Journal" submission-name="Journal"/>
|
||||||
<name-map collection-entity-type="JournalVolume" submission-name="JournalVolume"/>
|
<name-map collection-entity-type="JournalVolume" submission-name="JournalVolume"/>
|
||||||
<name-map collection-entity-type="JournalIssue" submission-name="JournalIssue"/>
|
<name-map collection-entity-type="JournalIssue" submission-name="JournalIssue"/>
|
||||||
-->
|
|
||||||
|
|
||||||
</submission-map>
|
</submission-map>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -268,8 +268,8 @@ Here's how to fix those issues by migrating your old Postgres data to the new ve
|
|||||||
* Pull down an older version of the image from Dockerhub (using a tag)
|
* Pull down an older version of the image from Dockerhub (using a tag)
|
||||||
* Or, temporarily rebuild your local image with the old version of Postgres. For example:
|
* Or, temporarily rebuild your local image with the old version of Postgres. For example:
|
||||||
```
|
```
|
||||||
# This command will rebuild using PostgreSQL v11 & tag it locally as "dspace-7_x"
|
# This command will rebuild using PostgreSQL v11 & tag it locally as "latest"
|
||||||
docker build --build-arg POSTGRES_VERSION=11 -t dspace/dspace-postgres-pgcrypto:dspace-7_x ./dspace/src/main/docker/dspace-postgres-pgcrypto/
|
docker build --build-arg POSTGRES_VERSION=11 -t dspace/dspace-postgres-pgcrypto:latest ./dspace/src/main/docker/dspace-postgres-pgcrypto/
|
||||||
# Then restart container with that image
|
# Then restart container with that image
|
||||||
docker-compose -p d7 up -d
|
docker-compose -p d7 up -d
|
||||||
```
|
```
|
||||||
|
@@ -10,7 +10,7 @@ version: "3.7"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
dspacedb:
|
dspacedb:
|
||||||
image: dspace/dspace-postgres-pgcrypto:dspace-7_x-loadsql
|
image: dspace/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}-loadsql
|
||||||
environment:
|
environment:
|
||||||
# This SQL is available from https://github.com/DSpace-Labs/AIP-Files/releases/tag/demo-entities-data
|
# This SQL is available from https://github.com/DSpace-Labs/AIP-Files/releases/tag/demo-entities-data
|
||||||
- LOADSQL=https://github.com/DSpace-Labs/AIP-Files/releases/download/demo-entities-data/dspace7-entities-data.sql
|
- LOADSQL=https://github.com/DSpace-Labs/AIP-Files/releases/download/demo-entities-data/dspace7-entities-data.sql
|
||||||
|
@@ -14,7 +14,7 @@ version: "3.7"
|
|||||||
# This can be used to restore a "dspacedb" container from a pg_dump, or during upgrade to a new version of PostgreSQL.
|
# This can be used to restore a "dspacedb" container from a pg_dump, or during upgrade to a new version of PostgreSQL.
|
||||||
services:
|
services:
|
||||||
dspacedb:
|
dspacedb:
|
||||||
image: dspace/dspace-postgres-pgcrypto:dspace-7_x-loadsql
|
image: dspace/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}-loadsql
|
||||||
environment:
|
environment:
|
||||||
# Location where the dump SQL file will be available on the running container
|
# Location where the dump SQL file will be available on the running container
|
||||||
- LOCALSQL=/tmp/pgdump.sql
|
- LOCALSQL=/tmp/pgdump.sql
|
||||||
|
@@ -23,7 +23,7 @@ services:
|
|||||||
DSPACE_REST_HOST: localhost
|
DSPACE_REST_HOST: localhost
|
||||||
DSPACE_REST_PORT: 8080
|
DSPACE_REST_PORT: 8080
|
||||||
DSPACE_REST_NAMESPACE: /server
|
DSPACE_REST_NAMESPACE: /server
|
||||||
image: dspace/dspace-angular:dspace-7_x
|
image: dspace/dspace-angular:${DSPACE_VER:-latest}
|
||||||
networks:
|
networks:
|
||||||
dspacenet:
|
dspacenet:
|
||||||
ports:
|
ports:
|
||||||
|
@@ -16,7 +16,7 @@ Caching these Maven dependencies provides a speed increase to all later builds b
|
|||||||
are only downloaded once.
|
are only downloaded once.
|
||||||
|
|
||||||
```
|
```
|
||||||
docker build -t dspace/dspace-dependencies:dspace-7_x -f Dockerfile.dependencies .
|
docker build -t dspace/dspace-dependencies:latest -f Dockerfile.dependencies .
|
||||||
```
|
```
|
||||||
|
|
||||||
This image is built *automatically* after each commit is made to the `main` branch.
|
This image is built *automatically* after each commit is made to the `main` branch.
|
||||||
@@ -25,7 +25,7 @@ A corresponding image exists for DSpace 4-6.
|
|||||||
|
|
||||||
Admins to our DockerHub repo can manually publish with the following command.
|
Admins to our DockerHub repo can manually publish with the following command.
|
||||||
```
|
```
|
||||||
docker push dspace/dspace-dependencies:dspace-7_x
|
docker push dspace/dspace-dependencies:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dockerfile.test (in root folder)
|
## Dockerfile.test (in root folder)
|
||||||
@@ -37,7 +37,7 @@ This image deploys two DSpace webapps to Tomcat running in Docker:
|
|||||||
This image also sets up debugging in Tomcat for development.
|
This image also sets up debugging in Tomcat for development.
|
||||||
|
|
||||||
```
|
```
|
||||||
docker build -t dspace/dspace:dspace-7_x-test -f Dockerfile.test .
|
docker build -t dspace/dspace:latest-test -f Dockerfile.test .
|
||||||
```
|
```
|
||||||
|
|
||||||
This image is built *automatically* after each commit is made to the `main` branch.
|
This image is built *automatically* after each commit is made to the `main` branch.
|
||||||
@@ -46,7 +46,7 @@ A corresponding image exists for DSpace 4-6.
|
|||||||
|
|
||||||
Admins to our DockerHub repo can manually publish with the following command.
|
Admins to our DockerHub repo can manually publish with the following command.
|
||||||
```
|
```
|
||||||
docker push dspace/dspace:dspace-7_x-test
|
docker push dspace/dspace:latest-test
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dockerfile (in root folder)
|
## Dockerfile (in root folder)
|
||||||
@@ -56,7 +56,7 @@ This image deploys one DSpace webapp to Tomcat running in Docker:
|
|||||||
1. The DSpace 7 REST API (at `http://localhost:8080/server`)
|
1. The DSpace 7 REST API (at `http://localhost:8080/server`)
|
||||||
|
|
||||||
```
|
```
|
||||||
docker build -t dspace/dspace:dspace-7_x -f Dockerfile .
|
docker build -t dspace/dspace:latest -f Dockerfile .
|
||||||
```
|
```
|
||||||
|
|
||||||
This image is built *automatically* after each commit is made to the `main` branch.
|
This image is built *automatically* after each commit is made to the `main` branch.
|
||||||
@@ -65,14 +65,14 @@ A corresponding image exists for DSpace 4-6.
|
|||||||
|
|
||||||
Admins to our DockerHub repo can publish with the following command.
|
Admins to our DockerHub repo can publish with the following command.
|
||||||
```
|
```
|
||||||
docker push dspace/dspace:dspace-7_x
|
docker push dspace/dspace:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dockerfile.cli (in root folder)
|
## Dockerfile.cli (in root folder)
|
||||||
|
|
||||||
This Dockerfile builds a DSpace 7 CLI (command line interface) image, which can be used to run DSpace's commandline tools via Docker.
|
This Dockerfile builds a DSpace 7 CLI (command line interface) image, which can be used to run DSpace's commandline tools via Docker.
|
||||||
```
|
```
|
||||||
docker build -t dspace/dspace-cli:dspace-7_x -f Dockerfile.cli .
|
docker build -t dspace/dspace-cli:latest -f Dockerfile.cli .
|
||||||
```
|
```
|
||||||
|
|
||||||
This image is built *automatically* after each commit is made to the `main` branch.
|
This image is built *automatically* after each commit is made to the `main` branch.
|
||||||
@@ -81,7 +81,7 @@ A corresponding image exists for DSpace 6.
|
|||||||
|
|
||||||
Admins to our DockerHub repo can publish with the following command.
|
Admins to our DockerHub repo can publish with the following command.
|
||||||
```
|
```
|
||||||
docker push dspace/dspace-cli:dspace-7_x
|
docker push dspace/dspace-cli:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## ./dspace-postgres-pgcrypto/Dockerfile
|
## ./dspace-postgres-pgcrypto/Dockerfile
|
||||||
@@ -92,20 +92,20 @@ This image is built *automatically* after each commit is made to the `main` bran
|
|||||||
How to build manually:
|
How to build manually:
|
||||||
```
|
```
|
||||||
cd dspace/src/main/docker/dspace-postgres-pgcrypto
|
cd dspace/src/main/docker/dspace-postgres-pgcrypto
|
||||||
docker build -t dspace/dspace-postgres-pgcrypto:dspace-7_x .
|
docker build -t dspace/dspace-postgres-pgcrypto:latest .
|
||||||
```
|
```
|
||||||
|
|
||||||
It is also possible to change the version of PostgreSQL or the PostgreSQL user's password during the build:
|
It is also possible to change the version of PostgreSQL or the PostgreSQL user's password during the build:
|
||||||
```
|
```
|
||||||
cd dspace/src/main/docker/dspace-postgres-pgcrypto
|
cd dspace/src/main/docker/dspace-postgres-pgcrypto
|
||||||
docker build -t dspace/dspace-postgres-pgcrypto:dspace-7_x --build-arg POSTGRES_VERSION=11 --build-arg POSTGRES_PASSWORD=mypass .
|
docker build -t dspace/dspace-postgres-pgcrypto:latest --build-arg POSTGRES_VERSION=11 --build-arg POSTGRES_PASSWORD=mypass .
|
||||||
```
|
```
|
||||||
|
|
||||||
A copy of this file exists in the DSpace 6 branch. A specialized version of this file exists for DSpace 4 in DSpace-Docker-Images.
|
A copy of this file exists in the DSpace 6 branch. A specialized version of this file exists for DSpace 4 in DSpace-Docker-Images.
|
||||||
|
|
||||||
Admins to our DockerHub repo can (manually) publish with the following command.
|
Admins to our DockerHub repo can (manually) publish with the following command.
|
||||||
```
|
```
|
||||||
docker push dspace/dspace-postgres-pgcrypto:dspace-7_x
|
docker push dspace/dspace-postgres-pgcrypto:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## ./dspace-postgres-pgcrypto-curl/Dockerfile
|
## ./dspace-postgres-pgcrypto-curl/Dockerfile
|
||||||
@@ -118,7 +118,7 @@ This image is built *automatically* after each commit is made to the `main` bran
|
|||||||
How to build manually:
|
How to build manually:
|
||||||
```
|
```
|
||||||
cd dspace/src/main/docker/dspace-postgres-pgcrypto-curl
|
cd dspace/src/main/docker/dspace-postgres-pgcrypto-curl
|
||||||
docker build -t dspace/dspace-postgres-pgcrypto:dspace-7_x-loadsql .
|
docker build -t dspace/dspace-postgres-pgcrypto:latest-loadsql .
|
||||||
```
|
```
|
||||||
|
|
||||||
Similar to `dspace-postgres-pgcrypto` above, you can also modify the version of PostgreSQL or the PostgreSQL user's password.
|
Similar to `dspace-postgres-pgcrypto` above, you can also modify the version of PostgreSQL or the PostgreSQL user's password.
|
||||||
@@ -128,7 +128,7 @@ A copy of this file exists in the DSpace 6 branch.
|
|||||||
|
|
||||||
Admins to our DockerHub repo can (manually) publish with the following command.
|
Admins to our DockerHub repo can (manually) publish with the following command.
|
||||||
```
|
```
|
||||||
docker push dspace/dspace-postgres-pgcrypto:dspace-7_x-loadsql
|
docker push dspace/dspace-postgres-pgcrypto:latest-loadsql
|
||||||
```
|
```
|
||||||
|
|
||||||
## ./dspace-shibboleth/Dockerfile
|
## ./dspace-shibboleth/Dockerfile
|
||||||
|
2
pom.xml
2
pom.xml
@@ -1688,7 +1688,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>2.1.214</version>
|
<version>2.2.220</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Google Analytics -->
|
<!-- Google Analytics -->
|
||||||
|
Reference in New Issue
Block a user