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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

@@ -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 &quot;${params[1]}&quot;.
*
* --
* 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 &quot;On the Testing of DSpace&quot;.
*
* --
* 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;

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

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)
* 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
```

View File

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

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

View File

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

View File

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

View File

@@ -1688,7 +1688,7 @@
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
<version>2.2.220</version>
<scope>test</scope>
</dependency>
<!-- Google Analytics -->