Merge branch 'main' into 8882-localized-license-files

This commit is contained in:
damian
2023-09-06 12:52:44 +02:00
42 changed files with 607 additions and 246 deletions

View File

@@ -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

View 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 }}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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: .

View File

@@ -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

View File

@@ -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>

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);
} }
} }
} }

View File

@@ -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]);
}
}

View File

@@ -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()) {

View File

@@ -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 &quot;${params[1]}&quot;. * Thank you for sending us your submission &quot;${params[1]}&quot;.
* *
* --
* 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 &quot;On the Testing of DSpace&quot;. * Thank you for sending us your submission &quot;On the Testing of DSpace&quot;.
* *
* --
* 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;

View File

@@ -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();
} }
} }

View File

@@ -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 {

View File

@@ -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;
} }

View File

@@ -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());
}
} }
} }
} }

View File

@@ -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;
}
} }

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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);
} }

View File

@@ -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;

View File

@@ -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')) {

View 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();
}
}

View File

@@ -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();

View File

@@ -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();
}
} }
} }

View File

@@ -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();

View 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"));
}
}

View File

@@ -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();
}
} }
} }
} }

View File

@@ -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 = "";

View File

@@ -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)

View File

@@ -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());
} }

View File

@@ -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!"))
))); )));
} }

View File

@@ -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) #####

View File

@@ -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>

View File

@@ -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
``` ```

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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 -->