mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +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
|
||||
- name: Auto-label PRs with merge conflicts
|
||||
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.
|
||||
# Note, the authentication token is created automatically
|
||||
# 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
|
||||
# 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.
|
||||
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
||||
ARG JDK_VERSION=11
|
||||
ARG DSPACE_VERSION=latest
|
||||
|
||||
# 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
|
||||
WORKDIR /app
|
||||
# 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}
|
||||
# NOTE: DSPACE_INSTALL must align with the "dspace.dir" default configuration.
|
||||
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
|
||||
# Expose Tomcat port and AJP port
|
||||
EXPOSE 8080 8009
|
||||
|
@@ -1,14 +1,15 @@
|
||||
# This image will be published as dspace/dspace-cli
|
||||
# See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details
|
||||
#
|
||||
# - note: default tag for branch: dspace/dspace-cli: dspace/dspace-cli: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.
|
||||
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
||||
ARG JDK_VERSION=11
|
||||
ARG DSPACE_VERSION=latest
|
||||
|
||||
# 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
|
||||
WORKDIR /app
|
||||
# The dspace-installer directory will be written to /install
|
||||
|
@@ -1,16 +1,17 @@
|
||||
# This image will be published as dspace/dspace
|
||||
# See https://github.com/DSpace/DSpace/tree/main/dspace/src/main/docker for usage details
|
||||
#
|
||||
# - note: default tag for branch: dspace/dspace: dspace/dspace: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 Dockerfile uses JDK11 by default, but has also been tested with JDK17.
|
||||
# To build with JDK17, use "--build-arg JDK_VERSION=17"
|
||||
ARG JDK_VERSION=11
|
||||
ARG DSPACE_VERSION=latest
|
||||
|
||||
# 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
|
||||
WORKDIR /app
|
||||
# The dspace-installer directory will be written to /install
|
||||
|
@@ -2,7 +2,7 @@ version: "3.7"
|
||||
|
||||
services:
|
||||
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
|
||||
build:
|
||||
context: .
|
||||
|
@@ -28,7 +28,7 @@ services:
|
||||
# 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.
|
||||
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:
|
||||
context: .
|
||||
dockerfile: Dockerfile.test
|
||||
@@ -66,7 +66,7 @@ services:
|
||||
dspacedb:
|
||||
container_name: dspacedb
|
||||
# Uses a custom Postgres image with pgcrypto installed
|
||||
image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-dspace-7_x}"
|
||||
image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}"
|
||||
build:
|
||||
# Must build out of subdirectory to have access to install script for pgcrypto
|
||||
context: ./dspace/src/main/docker/dspace-postgres-pgcrypto/
|
||||
@@ -86,7 +86,7 @@ services:
|
||||
# DSpace Solr container
|
||||
dspacesolr:
|
||||
container_name: dspacesolr
|
||||
image: "${DOCKER_OWNER:-dspace}/dspace-solr:${DSPACE_VER:-dspace-7_x}"
|
||||
image: "${DOCKER_OWNER:-dspace}/dspace-solr:${DSPACE_VER:-latest}"
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./dspace/src/main/docker/dspace-solr/Dockerfile
|
||||
|
@@ -102,7 +102,7 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.4.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
@@ -116,7 +116,10 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>buildnumber-maven-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<version>3.2.0</version>
|
||||
<configuration>
|
||||
<revisionOnScmFailure>UNKNOWN_REVISION</revisionOnScmFailure>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
|
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.DSpaceRunnable.StepResult;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
import org.dspace.scripts.factory.ScriptServiceFactory;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
@@ -145,8 +146,13 @@ public class ScriptLauncher {
|
||||
private static int executeScript(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||
DSpaceRunnable script) {
|
||||
try {
|
||||
script.initialize(args, dSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
StepResult result = script.initialize(args, dSpaceRunnableHandler, null);
|
||||
// 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;
|
||||
} catch (ParseException e) {
|
||||
script.printHelp();
|
||||
|
@@ -10,6 +10,7 @@ package org.dspace.app.mediafilter;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -40,6 +41,7 @@ import org.dspace.eperson.Group;
|
||||
import org.dspace.eperson.service.GroupService;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.util.ThrowableUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -225,23 +227,9 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
||||
filtered = true;
|
||||
}
|
||||
} 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.
|
||||
StringBuilder sb = new StringBuilder("ERROR filtering, skipping bitstream:\n");
|
||||
sb.append("\tItem Handle: ").append(handle);
|
||||
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);
|
||||
logError(formatBitstreamDetails(myItem.getHandle(), myBitstream));
|
||||
logError(ThrowableUtils.formatCauseChain(e));
|
||||
}
|
||||
} else if (filterClass instanceof SelfRegisterInputFormats) {
|
||||
// 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
|
||||
Bundle existingBundle = null;
|
||||
List<Bitstream> existingBitstreams = new ArrayList<Bitstream>();
|
||||
List<Bitstream> existingBitstreams = new ArrayList<>();
|
||||
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)
|
||||
for (Bundle bundle : bundles) {
|
||||
List<Bitstream> bitstreams = bundle.getBitstreams();
|
||||
@@ -337,7 +325,7 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
||||
}
|
||||
|
||||
// if exists and overwrite = false, exit
|
||||
if (!overWrite && (existingBitstreams.size() > 0)) {
|
||||
if (!overWrite && (!existingBitstreams.isEmpty())) {
|
||||
if (!isQuiet) {
|
||||
logInfo("SKIPPED: bitstream " + source.getID()
|
||||
+ " (item: " + item.getHandle() + ") because '" + newName + "' already exists");
|
||||
@@ -370,7 +358,7 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
||||
}
|
||||
|
||||
Bundle targetBundle; // bundle we're modifying
|
||||
if (bundles.size() < 1) {
|
||||
if (bundles.isEmpty()) {
|
||||
// create new bundle if needed
|
||||
targetBundle = bundleService.create(context, item, formatFilter.getBundleName());
|
||||
} else {
|
||||
@@ -399,6 +387,7 @@ public class MediaFilterServiceImpl implements MediaFilterService, InitializingB
|
||||
|
||||
} catch (OutOfMemoryError oome) {
|
||||
logError("!!! OutOfMemoryError !!!");
|
||||
logError(formatBitstreamDetails(item.getHandle(), source));
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (handler != null) {
|
||||
handler.logInfo(message);
|
||||
|
@@ -108,7 +108,7 @@ public class CrossLinks {
|
||||
} else {
|
||||
// Exact match, if the key field has no .* wildcard
|
||||
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 =
|
||||
authorizeService.getAuthorizedGroups(context, owningCollection,
|
||||
Constants.DEFAULT_BITSTREAM_READ);
|
||||
log.info(defaultBitstreamReadGroups.size());
|
||||
// If this collection is configured with a DEFAULT_BITSTREAM_READ group, overwrite the READ policy
|
||||
// inherited from the bundle with this policy.
|
||||
if (!defaultBitstreamReadGroups.isEmpty()) {
|
||||
|
@@ -21,7 +21,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import javax.activation.DataHandler;
|
||||
@@ -41,7 +40,6 @@ import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import javax.mail.internet.ParseException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.velocity.Template;
|
||||
@@ -57,26 +55,40 @@ import org.dspace.services.ConfigurationService;
|
||||
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>
|
||||
* 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>
|
||||
* <code>Email email = new Email();</code><br>
|
||||
* <code>email.addRecipient("foo@bar.com");</code><br>
|
||||
* <code>email.addArgument("John");</code><br>
|
||||
* <code>email.addArgument("On the Testing of DSpace");</code><br>
|
||||
* <code>email.send();</code><br>
|
||||
* </p>
|
||||
* {@link addArgument(string)} adds a property to the {@code params} array
|
||||
* in the Velocity context, which can be used to replace placeholder tokens
|
||||
* in the message. These arguments are indexed by number in the order they were
|
||||
* added to the message.
|
||||
* <p>
|
||||
* <code>name</code> is the name of an email template in
|
||||
* <code>dspace-dir/config/emails/</code> (which also includes the subject.)
|
||||
* <code>arg0</code> and <code>arg1</code> are arguments to fill out the
|
||||
* message with.
|
||||
* <P>
|
||||
* Emails are formatted using Apache Velocity. Headers such as Subject may be
|
||||
* supplied by the template, by defining them using #set(). Example:
|
||||
* </p>
|
||||
* The DSpace configuration properties are also available to templates as the
|
||||
* array {@code config}, indexed by name. Example: {@code ${config.get('dspace.name')}}
|
||||
* <p>
|
||||
* Recipients and attachments may be added as needed. See {@link addRecipient},
|
||||
* {@link addAttachment(File, String)}, and
|
||||
* {@link addAttachment(InputStream, String, String)}.
|
||||
* <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>
|
||||
*
|
||||
@@ -91,12 +103,14 @@ import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
*
|
||||
* Thank you for sending us your submission "${params[1]}".
|
||||
*
|
||||
* --
|
||||
* The ${config.get('dspace.name')} Team
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* 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:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
@@ -105,7 +119,16 @@ import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
*
|
||||
* Thank you for sending us your submission "On the Testing of DSpace".
|
||||
*
|
||||
* --
|
||||
* The DSpace Team
|
||||
*
|
||||
* </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 Jim Downing - added attachment handling code
|
||||
@@ -115,7 +138,6 @@ public class Email {
|
||||
/**
|
||||
* The content of the message
|
||||
*/
|
||||
private String content;
|
||||
private String contentName;
|
||||
|
||||
/**
|
||||
@@ -176,13 +198,12 @@ public class Email {
|
||||
moreAttachments = new ArrayList<>(10);
|
||||
subject = "";
|
||||
template = null;
|
||||
content = "";
|
||||
replyTo = null;
|
||||
charset = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a recipient
|
||||
* Add a recipient.
|
||||
*
|
||||
* @param email the recipient's email address
|
||||
*/
|
||||
@@ -196,16 +217,24 @@ public class Email {
|
||||
* "Subject:" line must be stripped.
|
||||
*
|
||||
* @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) {
|
||||
content = cnt;
|
||||
public void setContent(String name, String content) {
|
||||
contentName = name;
|
||||
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
|
||||
*/
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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
|
||||
*/
|
||||
@@ -231,6 +260,13 @@ public class Email {
|
||||
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) {
|
||||
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. */
|
||||
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) {
|
||||
if (null == mimetype) {
|
||||
LOG.error("Null MIME type replaced with '" + DEFAULT_ATTACHMENT_TYPE
|
||||
@@ -257,6 +304,11 @@ public class Email {
|
||||
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) {
|
||||
charset = cs;
|
||||
}
|
||||
@@ -280,15 +332,20 @@ public class Email {
|
||||
* {@code mail.message.headers} then that name and its value will be added
|
||||
* to the message's headers.
|
||||
*
|
||||
* <p>"subject" is treated specially: if {@link setSubject()} has not been called,
|
||||
* the value of any "subject" property will be used as if setSubject had
|
||||
* been called with that value. Thus a template may define its subject, but
|
||||
* the caller may override it.
|
||||
* <p>"subject" is treated specially: if {@link setSubject()} has not been
|
||||
* called, the value of any "subject" property will be used as if setSubject
|
||||
* had been called with that value. Thus a template may define its subject,
|
||||
* but the caller may override it.
|
||||
*
|
||||
* @throws MessagingException if there was a problem sending the mail.
|
||||
* @throws IOException if IO error
|
||||
*/
|
||||
public void send() throws MessagingException, IOException {
|
||||
if (null == template) {
|
||||
// No template -- no content -- PANIC!!!
|
||||
throw new MessagingException("Email has no body");
|
||||
}
|
||||
|
||||
ConfigurationService config
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
|
||||
@@ -308,37 +365,18 @@ public class Email {
|
||||
MimeMessage message = new MimeMessage(session);
|
||||
|
||||
// Set the recipients of the message
|
||||
Iterator<String> i = recipients.iterator();
|
||||
|
||||
while (i.hasNext()) {
|
||||
message.addRecipient(Message.RecipientType.TO, new InternetAddress(
|
||||
i.next()));
|
||||
for (String recipient : recipients) {
|
||||
message.addRecipient(Message.RecipientType.TO,
|
||||
new InternetAddress(recipient));
|
||||
}
|
||||
// Get headers defined by the template.
|
||||
String[] templateHeaders = config.getArrayProperty("mail.message.headers");
|
||||
|
||||
// Format the mail message body
|
||||
VelocityEngine templateEngine = new VelocityEngine();
|
||||
templateEngine.init(VELOCITY_PROPERTIES);
|
||||
|
||||
VelocityContext vctx = new VelocityContext();
|
||||
vctx.put("config", new UnmodifiableConfigurationService(config));
|
||||
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();
|
||||
try {
|
||||
template.merge(vctx, writer);
|
||||
@@ -405,7 +443,8 @@ public class Email {
|
||||
// add the stream
|
||||
messageBodyPart = new MimeBodyPart();
|
||||
messageBodyPart.setDataHandler(new DataHandler(
|
||||
new InputStreamDataSource(attachment.name,attachment.mimetype,attachment.is)));
|
||||
new InputStreamDataSource(attachment.name,
|
||||
attachment.mimetype, attachment.is)));
|
||||
messageBodyPart.setFileName(attachment.name);
|
||||
multipart.addBodyPart(messageBodyPart);
|
||||
}
|
||||
@@ -447,6 +486,9 @@ public class Email {
|
||||
/**
|
||||
* Get the VTL template for an email message. The message is suitable
|
||||
* for inserting values using Apache Velocity.
|
||||
* <p>
|
||||
* Note that everything is stored here, so that only send() throws a
|
||||
* MessagingException.
|
||||
*
|
||||
* @param emailFile
|
||||
* full name for the email template, for example "/dspace/config/emails/register".
|
||||
@@ -484,15 +526,6 @@ public class 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
|
||||
@@ -547,7 +580,7 @@ public class Email {
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility struct class for handling file attachments.
|
||||
* Utility record class for handling file attachments.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
@@ -580,6 +613,8 @@ public class Email {
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap an {@link InputStream} in a {@link DataSource}.
|
||||
*
|
||||
* @author arnaldo
|
||||
*/
|
||||
public static class InputStreamDataSource implements DataSource {
|
||||
@@ -587,6 +622,14 @@ public class Email {
|
||||
private final String contentType;
|
||||
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 {
|
||||
this.name = name;
|
||||
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() {
|
||||
Request currentRequest = DSpaceServicesFactory.getInstance().getRequestService().getCurrentRequest();
|
||||
if (currentRequest != null) {
|
||||
HttpServletRequest request = currentRequest.getHttpServletRequest();
|
||||
return ContextUtil.obtainContext(request);
|
||||
} else {
|
||||
return new Context();
|
||||
try {
|
||||
Request currentRequest = DSpaceServicesFactory.getInstance().getRequestService().getCurrentRequest();
|
||||
if (currentRequest != null) {
|
||||
HttpServletRequest request = currentRequest.getHttpServletRequest();
|
||||
return ContextUtil.obtainContext(request);
|
||||
}
|
||||
} 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())) {
|
||||
// a-ha! grab the text out of the bitstreams
|
||||
List<Bitstream> bitstreams = myBundle.getBitstreams();
|
||||
log.debug("Processing full-text bitstreams. Item handle: " + sourceInfo);
|
||||
|
||||
for (Bitstream fulltextBitstream : emptyIfNull(bitstreams)) {
|
||||
fullTextStreams.add(new FullTextBitstream(sourceInfo, fulltextBitstream));
|
||||
|
||||
log.debug("Added BitStream: "
|
||||
+ fulltextBitstream.getStoreNumber() + " "
|
||||
+ fulltextBitstream.getSequenceID() + " "
|
||||
+ fulltextBitstream.getName());
|
||||
if (fulltextBitstream != null) {
|
||||
log.debug("Added BitStream: "
|
||||
+ fulltextBitstream.getStoreNumber() + " "
|
||||
+ 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 {
|
||||
BitstreamFormat format = bitstream.getFormat(context);
|
||||
BitstreamFormat format = bitstream != null ? bitstream.getFormat(context) : null;
|
||||
return format == null ? null : StringUtils.trimToEmpty(format.getMIMEType());
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return StringUtils.trimToEmpty(bitstream.getName());
|
||||
return bitstream != null ? StringUtils.trimToEmpty(bitstream.getName()) : null;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return bitstream.getSizeBytes();
|
||||
return bitstream != null ? bitstream.getSizeBytes() : -1;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws SQLException, IOException, AuthorizeException {
|
||||
|
@@ -172,13 +172,6 @@ public class ItemIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl<Indexable
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -141,20 +141,10 @@ public class Groomer {
|
||||
System.out.println();
|
||||
|
||||
if (delete) {
|
||||
List<String> whyNot = ePersonService.getDeleteConstraints(myContext, account);
|
||||
if (!whyNot.isEmpty()) {
|
||||
System.out.print("\tCannot be deleted; referenced in");
|
||||
for (String table : whyNot) {
|
||||
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());
|
||||
}
|
||||
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.ParseException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.cli.DSpaceSkipUnknownArgumentsParser;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
@@ -36,6 +37,11 @@ public abstract class DSpaceRunnable<T extends ScriptConfiguration> implements R
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@@ -64,26 +70,66 @@ public abstract class DSpaceRunnable<T extends ScriptConfiguration> implements R
|
||||
* @param args The arguments given to the script
|
||||
* @param dSpaceRunnableHandler The DSpaceRunnableHandler object that defines from where the script was ran
|
||||
* @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
|
||||
*/
|
||||
public void initialize(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||
public StepResult initialize(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||
EPerson currentUser) throws ParseException {
|
||||
if (currentUser != null) {
|
||||
this.setEpersonIdentifier(currentUser.getID());
|
||||
}
|
||||
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
|
||||
* 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
|
||||
* @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);
|
||||
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) {
|
||||
this.epersonIdentifier = epersonIdentifier;
|
||||
}
|
||||
|
||||
public enum StepResult {
|
||||
Continue, Exit;
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ package org.dspace.scripts.configuration;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.core.Context;
|
||||
@@ -105,6 +106,19 @@ public abstract class ScriptConfiguration<T extends DSpaceRunnable> implements B
|
||||
*/
|
||||
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
|
||||
public void setBeanName(String beanName) {
|
||||
this.name = beanName;
|
||||
|
@@ -37,7 +37,7 @@ public class GeoIpService {
|
||||
public DatabaseReader getDatabaseReader() throws IllegalStateException {
|
||||
String dbPath = configurationService.getProperty("usage-statistics.dbfile");
|
||||
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 {
|
||||
|
@@ -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
|
||||
public void shardSolrIndex() throws IOException, SolrServerException {
|
||||
if (!(solr instanceof HttpSolrClient)) {
|
||||
@@ -1691,11 +1675,14 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
statisticYearCores
|
||||
.add(baseSolrUrl.replace("http://", "").replace("https://", "") + statCoreName);
|
||||
}
|
||||
//Also add the core containing the current year !
|
||||
statisticYearCores.add(((HttpSolrClient) solr)
|
||||
var baseCore = ((HttpSolrClient) solr)
|
||||
.getBaseURL()
|
||||
.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) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
|
@@ -266,12 +266,6 @@ public interface SolrLoggerService {
|
||||
*/
|
||||
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 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("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("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("e", "export", false,
|
||||
"Export SOLR view statistics data to usage-statistics-intermediate-format");
|
||||
@@ -93,8 +92,6 @@ public class StatisticsClient {
|
||||
solrLoggerService.deleteRobotsByIsBotFlag();
|
||||
} else if (line.hasOption('i')) {
|
||||
solrLoggerService.deleteRobotsByIP();
|
||||
} else if (line.hasOption('o')) {
|
||||
solrLoggerService.optimizeSOLR();
|
||||
} else if (line.hasOption('b')) {
|
||||
solrLoggerService.reindexBitstreamHits(line.hasOption('r'));
|
||||
} 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);
|
||||
}
|
||||
if (script != null) {
|
||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||
script.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,8 +207,9 @@ public class MetadataExportIT
|
||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||
}
|
||||
if (script != null) {
|
||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||
script.run();
|
||||
}
|
||||
}
|
||||
|
||||
Exception exceptionDuringTestRun = testDSpaceRunnableHandler.getException();
|
||||
@@ -235,8 +237,9 @@ public class MetadataExportIT
|
||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||
}
|
||||
if (script != null) {
|
||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||
script.run();
|
||||
}
|
||||
}
|
||||
|
||||
Exception exceptionDuringTestRun = testDSpaceRunnableHandler.getException();
|
||||
|
@@ -144,8 +144,9 @@ public class MetadataImportIT extends AbstractIntegrationTestWithDatabase {
|
||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||
}
|
||||
if (script != null) {
|
||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||
script.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -702,8 +702,10 @@ public class CSVMetadataImportReferenceIT extends AbstractIntegrationTestWithDat
|
||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||
}
|
||||
if (script != null) {
|
||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
if (DSpaceRunnable.StepResult.Continue
|
||||
.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||
script.run();
|
||||
}
|
||||
}
|
||||
if (testDSpaceRunnableHandler.getException() != null) {
|
||||
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);
|
||||
}
|
||||
if (script != null) {
|
||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||
script.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +70,9 @@ public class CurationIT extends AbstractIntegrationTestWithDatabase {
|
||||
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||
}
|
||||
if (script != null) {
|
||||
script.initialize(args, testDSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
if (DSpaceRunnable.StepResult.Continue.equals(script.initialize(args, testDSpaceRunnableHandler, null))) {
|
||||
script.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -103,6 +103,11 @@ public class ItemUtils {
|
||||
bundle.getElement().add(bitstreams);
|
||||
List<Bitstream> bits = b.getBitstreams();
|
||||
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");
|
||||
bitstreams.getElement().add(bitstream);
|
||||
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
|
||||
|
||||
## 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)
|
||||
|
||||
|
@@ -132,7 +132,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
||||
Exception ex) throws IOException {
|
||||
//422 is not defined in HttpServletResponse. Its meaning is "Unprocessable Entity".
|
||||
//Using the value from HttpStatus.
|
||||
sendErrorResponse(request, response, null,
|
||||
sendErrorResponse(request, response, ex,
|
||||
"Unprocessable or invalid entity",
|
||||
HttpStatus.UNPROCESSABLE_ENTITY.value());
|
||||
}
|
||||
@@ -140,7 +140,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
||||
@ExceptionHandler( {InvalidSearchRequestException.class})
|
||||
protected void handleInvalidSearchRequestException(HttpServletRequest request, HttpServletResponse response,
|
||||
Exception ex) throws IOException {
|
||||
sendErrorResponse(request, response, null,
|
||||
sendErrorResponse(request, response, ex,
|
||||
"Invalid search request",
|
||||
HttpStatus.UNPROCESSABLE_ENTITY.value());
|
||||
}
|
||||
@@ -180,7 +180,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
||||
TranslatableException ex) throws IOException {
|
||||
Context context = ContextUtil.obtainContext(request);
|
||||
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)
|
||||
throws IOException {
|
||||
// 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",
|
||||
HttpStatus.BAD_REQUEST.value());
|
||||
}
|
||||
@@ -197,7 +197,7 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
||||
protected void MissingParameterException(HttpServletRequest request, HttpServletResponse response, Exception ex)
|
||||
throws IOException {
|
||||
// we want the 400 status for missing parameters, see https://jira.lyrasis.org/browse/DS-4428
|
||||
sendErrorResponse(request, response, null,
|
||||
sendErrorResponse(request, response, ex,
|
||||
"A required parameter is missing",
|
||||
HttpStatus.BAD_REQUEST.value());
|
||||
}
|
||||
|
@@ -67,7 +67,7 @@ public class HealthIndicatorsIT extends AbstractControllerIntegrationTest {
|
||||
match("solrSearchCore", Status.UP, Map.of("status", 0, "detectedPathType", "root")),
|
||||
match("solrStatisticsCore", Status.UP, Map.of("status", 0, "detectedPathType", "root")),
|
||||
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
|
||||
# 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
|
||||
# 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]"
|
||||
@@ -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
|
||||
# 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
|
||||
# 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
|
||||
@@ -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
|
||||
# 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.browse.<browse 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) #####
|
||||
|
||||
|
@@ -55,9 +55,7 @@
|
||||
- - - - - -
|
||||
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="Person" submission-name="Person"/>
|
||||
<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="JournalVolume" submission-name="JournalVolume"/>
|
||||
<name-map collection-entity-type="JournalIssue" submission-name="JournalIssue"/>
|
||||
-->
|
||||
|
||||
</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)
|
||||
* 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"
|
||||
docker build --build-arg POSTGRES_VERSION=11 -t dspace/dspace-postgres-pgcrypto:dspace-7_x ./dspace/src/main/docker/dspace-postgres-pgcrypto/
|
||||
# This command will rebuild using PostgreSQL v11 & tag it locally as "latest"
|
||||
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
|
||||
docker-compose -p d7 up -d
|
||||
```
|
||||
|
@@ -10,7 +10,7 @@ version: "3.7"
|
||||
|
||||
services:
|
||||
dspacedb:
|
||||
image: dspace/dspace-postgres-pgcrypto:dspace-7_x-loadsql
|
||||
image: dspace/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}-loadsql
|
||||
environment:
|
||||
# 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
|
||||
|
@@ -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.
|
||||
services:
|
||||
dspacedb:
|
||||
image: dspace/dspace-postgres-pgcrypto:dspace-7_x-loadsql
|
||||
image: dspace/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}-loadsql
|
||||
environment:
|
||||
# Location where the dump SQL file will be available on the running container
|
||||
- LOCALSQL=/tmp/pgdump.sql
|
||||
|
@@ -23,7 +23,7 @@ services:
|
||||
DSPACE_REST_HOST: localhost
|
||||
DSPACE_REST_PORT: 8080
|
||||
DSPACE_REST_NAMESPACE: /server
|
||||
image: dspace/dspace-angular:dspace-7_x
|
||||
image: dspace/dspace-angular:${DSPACE_VER:-latest}
|
||||
networks:
|
||||
dspacenet:
|
||||
ports:
|
||||
|
@@ -16,7 +16,7 @@ Caching these Maven dependencies provides a speed increase to all later builds b
|
||||
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.
|
||||
@@ -25,7 +25,7 @@ A corresponding image exists for DSpace 4-6.
|
||||
|
||||
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)
|
||||
@@ -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.
|
||||
|
||||
```
|
||||
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.
|
||||
@@ -46,7 +46,7 @@ A corresponding image exists for DSpace 4-6.
|
||||
|
||||
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)
|
||||
@@ -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`)
|
||||
|
||||
```
|
||||
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.
|
||||
@@ -65,14 +65,14 @@ A corresponding image exists for DSpace 4-6.
|
||||
|
||||
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)
|
||||
|
||||
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.
|
||||
@@ -81,7 +81,7 @@ A corresponding image exists for DSpace 6.
|
||||
|
||||
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
|
||||
@@ -92,20 +92,20 @@ This image is built *automatically* after each commit is made to the `main` bran
|
||||
How to build manually:
|
||||
```
|
||||
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:
|
||||
```
|
||||
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.
|
||||
|
||||
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
|
||||
@@ -118,7 +118,7 @@ This image is built *automatically* after each commit is made to the `main` bran
|
||||
How to build manually:
|
||||
```
|
||||
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.
|
||||
@@ -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.
|
||||
```
|
||||
docker push dspace/dspace-postgres-pgcrypto:dspace-7_x-loadsql
|
||||
docker push dspace/dspace-postgres-pgcrypto:latest-loadsql
|
||||
```
|
||||
|
||||
## ./dspace-shibboleth/Dockerfile
|
||||
|
Reference in New Issue
Block a user