mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-17 15:03:18 +00:00
Merge remote-tracking branch 'upstream/main' into w2p-72472_Delete-eperson
This commit is contained in:
29
.codecov.yml
Normal file
29
.codecov.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# DSpace configuration for Codecov.io coverage reports
|
||||||
|
# These override the default YAML settings at
|
||||||
|
# https://docs.codecov.io/docs/codecov-yaml#section-default-yaml
|
||||||
|
# Can be validated via instructions at:
|
||||||
|
# https://docs.codecov.io/docs/codecov-yaml#validate-your-repository-yaml
|
||||||
|
|
||||||
|
# Settings related to code coverage analysis
|
||||||
|
coverage:
|
||||||
|
status:
|
||||||
|
# Configuration for project-level checks. This checks how the PR changes overall coverage.
|
||||||
|
project:
|
||||||
|
default:
|
||||||
|
# For each PR, auto compare coverage to previous commit.
|
||||||
|
# Require that overall (project) coverage does NOT drop more than 0.5%
|
||||||
|
target: auto
|
||||||
|
threshold: 0.5%
|
||||||
|
# Configuration for patch-level checks. This checks the relative coverage of the new PR code ONLY.
|
||||||
|
patch:
|
||||||
|
default:
|
||||||
|
# For each PR, make sure the coverage of the new code is within 1% of current overall coverage.
|
||||||
|
# We let 'patch' be more lenient as we only require *project* coverage to not drop significantly.
|
||||||
|
target: auto
|
||||||
|
threshold: 1%
|
||||||
|
|
||||||
|
# Turn PR comments "off". This feature adds the code coverage summary as a
|
||||||
|
# comment on each PR. See https://docs.codecov.io/docs/pull-request-comments
|
||||||
|
# However, this same info is available from the Codecov checks in the PR's
|
||||||
|
# "Checks" tab in GitHub. So, the comment is unnecessary.
|
||||||
|
comment: false
|
77
.travis.yml
77
.travis.yml
@@ -1,46 +1,55 @@
|
|||||||
|
# DSpace's Travis CI Configuration
|
||||||
|
# Builds: https://travis-ci.com/github/DSpace/DSpace
|
||||||
|
# Travis configuration guide/validation: https://config.travis-ci.com/explore
|
||||||
language: java
|
language: java
|
||||||
sudo: false
|
# TODO: Upgrade to Bionic
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
os: linux
|
||||||
env:
|
|
||||||
# Give Maven 1GB of memory to work with
|
|
||||||
- MAVEN_OPTS=-Xmx1024M
|
|
||||||
|
|
||||||
jdk:
|
jdk:
|
||||||
# DS-3384 Oracle JDK has DocLint enabled by default.
|
# DS-3384 Oracle JDK has DocLint enabled by default.
|
||||||
# Let's use this to catch any newly introduced DocLint issues.
|
# Let's use this to catch any newly introduced DocLint issues.
|
||||||
- oraclejdk11
|
- oraclejdk11
|
||||||
|
|
||||||
## Should we run into any problems with oraclejdk8 on Travis, we may try the following workaround.
|
# Define global environment variables (shared across all jobs)
|
||||||
## https://docs.travis-ci.com/user/languages/java#Testing-Against-Multiple-JDKs
|
env:
|
||||||
## https://github.com/travis-ci/travis-ci/issues/3259#issuecomment-130860338
|
global:
|
||||||
#addons:
|
# Suppress all Maven "downloading" messages in Travis logs (see https://stackoverflow.com/a/35653426)
|
||||||
# apt:
|
# This also slightly speeds builds in Travis, as there is less logging
|
||||||
# packages:
|
- HIDE_MAVEN_DOWNLOADS="-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn"
|
||||||
# - oracle-java8-installer
|
# Give Maven 1GB of memory to work with
|
||||||
|
- MAVEN_OPTS="-Xmx1024M $HIDE_MAVEN_DOWNLOADS"
|
||||||
|
# Maven options which will skip ALL code validation checks. Includes skipping:
|
||||||
|
# - enforcer.skip => Skip maven-enforcer-plugin rules
|
||||||
|
# - checkstyle.skip => Skip all checkstyle checks by maven-checkstyle-plugin
|
||||||
|
# - license.skip => Skip all license header checks by license-maven-plugin
|
||||||
|
# - xml.skip => Skip all XML/XSLT validation by xml-maven-plugin
|
||||||
|
# (Useful for builds which don't need to repeat code checks)
|
||||||
|
- SKIP_CODE_CHECKS="-Denforcer.skip=true -Dcheckstyle.skip=true -Dlicense.skip=true -Dxml.skip=true"
|
||||||
|
|
||||||
before_install:
|
# Create two jobs to run Unit & Integration tests in parallel.
|
||||||
# Remove outdated settings.xml from Travis builds. Workaround for https://github.com/travis-ci/travis-ci/issues/4629
|
# These jobs only differ in the TEST_FLAGS defined below,
|
||||||
- rm ~/.m2/settings.xml
|
# and otherwise share all the other configs in this file
|
||||||
|
jobs:
|
||||||
|
include:
|
||||||
|
- name: "Run Unit Tests & Check Code"
|
||||||
|
# NOTE: unit tests include deprecated REST API v6 (as it has unit tests)
|
||||||
|
env: TEST_FLAGS="-DskipUnitTests=false -Pdspace-rest"
|
||||||
|
- name: "Run Integration Tests"
|
||||||
|
# NOTE: skips code checks, as they are already done by Unit Test job
|
||||||
|
env: TEST_FLAGS="-DskipIntegrationTests=false $SKIP_CODE_CHECKS"
|
||||||
|
|
||||||
# Skip install stage, as we'll do it below
|
# Skip 'install' process to save time. We build/install/test all at once in "script" below.
|
||||||
install: "echo 'Skipping install stage, dependencies will be downloaded during build and test stages.'"
|
install: skip
|
||||||
|
|
||||||
# Build DSpace and run both Unit and Integration Tests
|
# Build DSpace and run configured tests (see 'jobs' above)
|
||||||
script:
|
# Notes on flags used:
|
||||||
# Summary of flags used (below):
|
# -B => Maven batch/non-interactive mode (recommended for CI)
|
||||||
# license:check => Validate all source code license headers
|
# -V => Display Maven version info before build
|
||||||
# -DskipTests=false => Enable DSpace Unit Tests
|
# -P-assembly => Disable build of dspace-installer in [src]/dspace/, as it can be memory intensive
|
||||||
# -DskipITs=false => Enable DSpace Integration Tests
|
# -Pcoverage-report => Enable aggregate code coverage report (across all modules) via JaCoCo
|
||||||
# -Pdspace-rest => Enable optional dspace-rest module as part of build
|
script: mvn install -B -V -P-assembly -Pcoverage-report $TEST_FLAGS
|
||||||
# -P !assembly => Skip assembly of "dspace-installer" directory (as it can be memory intensive)
|
|
||||||
# -B => Maven batch/non-interactive mode (recommended for CI)
|
|
||||||
# -V => Display Maven version info before build
|
|
||||||
# -Dsurefire.rerunFailingTestsCount=2 => try again for flakey tests, and keep track of/report on number of retries
|
|
||||||
- "mvn clean install license:check -DskipTests=false -DskipITs=false -Pdspace-rest -P !assembly -B -V -Dsurefire.rerunFailingTestsCount=2"
|
|
||||||
|
|
||||||
# After a successful build and test (see 'script'), send code coverage reports to coveralls.io
|
# After a successful build and test (see 'script'), send aggregate code coverage reports
|
||||||
# These code coverage reports are generated by jacoco-maven-plugin (during test process above).
|
# (generated by -Pcoverage-report above) to CodeCov.io
|
||||||
after_success:
|
after_success: bash <(curl -s https://codecov.io/bash)
|
||||||
# Run "verify", enabling the "coveralls" profile. This sends our reports to coveralls.io (see coveralls-maven-plugin)
|
|
||||||
- "cd dspace && mvn verify -P coveralls"
|
|
||||||
|
20
README.md
20
README.md
@@ -90,33 +90,33 @@ run automatically by [Travis CI](https://travis-ci.com/DSpace/DSpace/) for all P
|
|||||||
|
|
||||||
* How to run both Unit Tests (via `maven-surefire-plugin`) and Integration Tests (via `maven-failsafe-plugin`):
|
* How to run both Unit Tests (via `maven-surefire-plugin`) and Integration Tests (via `maven-failsafe-plugin`):
|
||||||
```
|
```
|
||||||
mvn clean test -DskipTests=false -DskipITs=false
|
mvn install -DskipUnitTests=false -DskipIntegrationTests=false
|
||||||
```
|
```
|
||||||
* How to run just Unit Tests:
|
* How to run _only_ Unit Tests:
|
||||||
```
|
```
|
||||||
mvn test -DskipTests=false
|
mvn test -DskipUnitTests=false
|
||||||
```
|
```
|
||||||
* How to run a *single* Unit Test
|
* How to run a *single* Unit Test
|
||||||
```
|
```
|
||||||
# Run all tests in a specific test class
|
# Run all tests in a specific test class
|
||||||
# NOTE: failIfNoTests=false is required to skip tests in other modules
|
# NOTE: failIfNoTests=false is required to skip tests in other modules
|
||||||
mvn test -DskipTests=false -Dtest=[full.package.testClassName] -DfailIfNoTests=false
|
mvn test -DskipUnitTests=false -Dtest=[full.package.testClassName] -DfailIfNoTests=false
|
||||||
|
|
||||||
# Run one test method in a specific test class
|
# Run one test method in a specific test class
|
||||||
mvn test -DskipTests=false -Dtest=[full.package.testClassName]#[testMethodName] -DfailIfNoTests=false
|
mvn test -DskipUnitTests=false -Dtest=[full.package.testClassName]#[testMethodName] -DfailIfNoTests=false
|
||||||
```
|
```
|
||||||
* How to run Integration Tests (requires enabling Unit tests too)
|
* How to run _only_ Integration Tests
|
||||||
```
|
```
|
||||||
mvn verify -DskipTests=false -DskipITs=false
|
mvn install -DskipIntegrationTests=false
|
||||||
```
|
```
|
||||||
* How to run a *single* Integration Test (requires enabling Unit tests too)
|
* How to run a *single* Integration Test
|
||||||
```
|
```
|
||||||
# Run all integration tests in a specific test class
|
# Run all integration tests in a specific test class
|
||||||
# NOTE: failIfNoTests=false is required to skip tests in other modules
|
# NOTE: failIfNoTests=false is required to skip tests in other modules
|
||||||
mvn test -DskipTests=false -DskipITs=false -Dtest=[full.package.testClassName] -DfailIfNoTests=false
|
mvn install -DskipIntegrationTests=false -Dit.test=[full.package.testClassName] -DfailIfNoTests=false
|
||||||
|
|
||||||
# Run one test method in a specific test class
|
# Run one test method in a specific test class
|
||||||
mvn test -DskipTests=false -DskipITs=false -Dtest=[full.package.testClassName]#[testMethodName] -DfailIfNoTests=false
|
mvn install -DskipIntegrationTests=false -Dit.test=[full.package.testClassName]#[testMethodName] -DfailIfNoTests=false
|
||||||
```
|
```
|
||||||
* How to run only tests of a specific DSpace module
|
* How to run only tests of a specific DSpace module
|
||||||
```
|
```
|
||||||
|
@@ -127,44 +127,69 @@
|
|||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
||||||
|
(see: https://groovy.github.io/gmaven/groovy-maven-plugin/execute.html )
|
||||||
|
We are generating a OS-agnostic version (agnostic.build.dir) of
|
||||||
|
the ${project.build.directory} property (full path of target dir).
|
||||||
|
This is needed by the Surefire & Failsafe plugins (see below)
|
||||||
|
to initialize the Unit Test environment's dspace.cfg file.
|
||||||
|
Otherwise, the Unit Test Framework will not work on Windows OS.
|
||||||
|
This Groovy code was mostly borrowed from:
|
||||||
|
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
||||||
|
-->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.gmaven</groupId>
|
||||||
|
<artifactId>groovy-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setproperty</id>
|
||||||
|
<phase>initialize</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>execute</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<source>
|
||||||
|
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
||||||
|
log.info("Initializing Maven property 'agnostic.build.dir' to: {}", project.properties['agnostic.build.dir']);
|
||||||
|
</source>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>findbugs</id>
|
<id>spotbugs</id>
|
||||||
<activation>
|
<activation>
|
||||||
<activeByDefault>false</activeByDefault>
|
<activeByDefault>false</activeByDefault>
|
||||||
<!-- property>
|
|
||||||
<name>skipTests</name>
|
|
||||||
<value>false</value>
|
|
||||||
</property -->
|
|
||||||
</activation>
|
</activation>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>com.github.spotbugs</groupId>
|
||||||
<artifactId>findbugs-maven-plugin</artifactId>
|
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<!-- If Unit Testing is enabled, then setup the Unit Test Environment.
|
<!-- Setup the Unit Test Environment (when -DskipUnitTests=false) -->
|
||||||
See also the 'skiptests' profile in Parent POM. -->
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>test-environment</id>
|
<id>unit-test-environment</id>
|
||||||
<activation>
|
<activation>
|
||||||
<activeByDefault>false</activeByDefault>
|
<activeByDefault>false</activeByDefault>
|
||||||
<property>
|
<property>
|
||||||
<name>skipTests</name>
|
<name>skipUnitTests</name>
|
||||||
<value>false</value>
|
<value>false</value>
|
||||||
</property>
|
</property>
|
||||||
</activation>
|
</activation>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- Unit/Integration Testing setup: This plugin unzips the
|
<!-- Unit Testing setup: This plugin unzips the
|
||||||
'testEnvironment.zip' file (created by dspace-parent POM), into
|
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||||
the 'target/testing/' folder, to essentially create a test
|
the 'target/testing/' folder, to essentially create a test
|
||||||
install of DSpace, against which Tests can be run. -->
|
install of DSpace, against which Tests can be run. -->
|
||||||
@@ -184,53 +209,16 @@
|
|||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>setupTestEnvironment</id>
|
<id>setupUnitTestEnvironment</id>
|
||||||
<phase>generate-test-resources</phase>
|
<phase>generate-test-resources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>unpack</goal>
|
<goal>unpack</goal>
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
|
||||||
<id>setupIntegrationTestEnvironment</id>
|
|
||||||
<phase>pre-integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>unpack</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
<!-- Run Unit Testing! This plugin just kicks off the tests. -->
|
||||||
(see: http://gmaven.codehaus.org/Executing+Groovy+Code )
|
|
||||||
We are generating a OS-agnostic version (agnostic.build.dir) of
|
|
||||||
the ${project.build.directory} property (full path of target dir).
|
|
||||||
This is needed by the Surefire & Failsafe plugins (see below)
|
|
||||||
to initialize the Unit Test environment's dspace.cfg file.
|
|
||||||
Otherwise, the Unit Test Framework will not work on Windows OS.
|
|
||||||
This Groovy code was mostly borrowed from:
|
|
||||||
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
|
||||||
-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.gmaven</groupId>
|
|
||||||
<artifactId>groovy-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>setproperty</id>
|
|
||||||
<phase>initialize</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>execute</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<source>
|
|
||||||
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
|
||||||
log.info("Initializing Maven property 'agnostic.build.dir' to: {}", project.properties['agnostic.build.dir']);
|
|
||||||
</source>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<!-- Run Unit Testing! This plugin just kicks off the tests (when enabled). -->
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
@@ -245,8 +233,52 @@
|
|||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
<!-- Setup the Integration Test Environment (when -DskipIntegrationTests=false) -->
|
||||||
|
<profile>
|
||||||
|
<id>integration-test-environment</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
<property>
|
||||||
|
<name>skipIntegrationTests</name>
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Integration Testing setup: This plugin unzips the
|
||||||
|
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||||
|
the 'target/testing/' folder, to essentially create a test
|
||||||
|
install of DSpace, against which Tests can be run. -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/testing</outputDirectory>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.dspace</groupId>
|
||||||
|
<artifactId>dspace-parent</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<classifier>testEnvironment</classifier>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setupIntegrationTestEnvironment</id>
|
||||||
|
<phase>pre-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>unpack</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Run Integration Testing! This plugin just kicks off the tests. -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
@@ -262,7 +294,6 @@
|
|||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
@@ -732,6 +763,7 @@
|
|||||||
<groupId>com.google.oauth-client</groupId>
|
<groupId>com.google.oauth-client</groupId>
|
||||||
<artifactId>google-oauth-client</artifactId>
|
<artifactId>google-oauth-client</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- FindBugs -->
|
<!-- FindBugs -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
@@ -741,6 +773,7 @@
|
|||||||
<groupId>com.google.code.findbugs</groupId>
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
<artifactId>annotations</artifactId>
|
<artifactId>annotations</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>joda-time</groupId>
|
<groupId>joda-time</groupId>
|
||||||
<artifactId>joda-time</artifactId>
|
<artifactId>joda-time</artifactId>
|
||||||
|
@@ -629,6 +629,10 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl<Community> imp
|
|||||||
case Constants.DELETE:
|
case Constants.DELETE:
|
||||||
if (AuthorizeConfiguration.canCommunityAdminPerformSubelementDeletion()) {
|
if (AuthorizeConfiguration.canCommunityAdminPerformSubelementDeletion()) {
|
||||||
adminObject = getParentObject(context, community);
|
adminObject = getParentObject(context, community);
|
||||||
|
if (adminObject == null) {
|
||||||
|
//top-level community, has to be admin of the current community
|
||||||
|
adminObject = community;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Constants.ADD:
|
case Constants.ADD:
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.content;
|
package org.dspace.content;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
@@ -15,6 +16,8 @@ import javax.persistence.Id;
|
|||||||
import javax.persistence.SequenceGenerator;
|
import javax.persistence.SequenceGenerator;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.dspace.core.ReloadableEntity;
|
import org.dspace.core.ReloadableEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,7 +48,8 @@ public class EntityType implements ReloadableEntity<Integer> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The standard setter for the ID of this EntityType
|
* The standard setter for the ID of this EntityType
|
||||||
* @param id The ID that this EntityType's ID will be set to
|
*
|
||||||
|
* @param id The ID that this EntityType's ID will be set to
|
||||||
*/
|
*/
|
||||||
public void setId(Integer id) {
|
public void setId(Integer id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@@ -53,7 +57,8 @@ public class EntityType implements ReloadableEntity<Integer> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The standard getter for the label of this EntityType
|
* The standard getter for the label of this EntityType
|
||||||
* @return The label for this EntityType
|
*
|
||||||
|
* @return The label for this EntityType
|
||||||
*/
|
*/
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return label;
|
return label;
|
||||||
@@ -61,6 +66,7 @@ public class EntityType implements ReloadableEntity<Integer> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The standard setter for the label of this EntityType
|
* The standard setter for the label of this EntityType
|
||||||
|
*
|
||||||
* @param label The label that this EntityType's label will be set to
|
* @param label The label that this EntityType's label will be set to
|
||||||
*/
|
*/
|
||||||
public void setLabel(String label) {
|
public void setLabel(String label) {
|
||||||
@@ -69,9 +75,40 @@ public class EntityType implements ReloadableEntity<Integer> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The standard getter for the ID of this EntityType
|
* The standard getter for the ID of this EntityType
|
||||||
* @return The ID for this EntityType
|
*
|
||||||
|
* @return The ID for this EntityType
|
||||||
*/
|
*/
|
||||||
public Integer getID() {
|
public Integer getID() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether two entity types are equal based on the id and the label
|
||||||
|
* @param obj object to be compared
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof EntityType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EntityType entityType = (EntityType) obj;
|
||||||
|
|
||||||
|
if (!Objects.equals(this.getID(), entityType.getID())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.equals(this.getLabel(), entityType.getLabel())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hash code value for the object.
|
||||||
|
* @return hash code value
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return new HashCodeBuilder().append(getID()).toHashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1106,19 +1106,7 @@ prevent the generation of resource policy entry values with null dspace_object a
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Constants.DELETE:
|
case Constants.DELETE:
|
||||||
if (item.getOwningCollection() != null) {
|
adminObject = item;
|
||||||
if (AuthorizeConfiguration.canCollectionAdminPerformItemDeletion()) {
|
|
||||||
adminObject = collection;
|
|
||||||
} else if (AuthorizeConfiguration.canCommunityAdminPerformItemDeletion()) {
|
|
||||||
adminObject = community;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (AuthorizeConfiguration.canCollectionAdminManageTemplateItem()) {
|
|
||||||
adminObject = collection;
|
|
||||||
} else if (AuthorizeConfiguration.canCommunityAdminManageCollectionTemplateItem()) {
|
|
||||||
adminObject = community;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Constants.WRITE:
|
case Constants.WRITE:
|
||||||
// if it is a template item we need to check the
|
// if it is a template item we need to check the
|
||||||
|
@@ -13,6 +13,7 @@ import java.util.List;
|
|||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.GenericDAO;
|
import org.dspace.core.GenericDAO;
|
||||||
import org.dspace.scripts.Process;
|
import org.dspace.scripts.Process;
|
||||||
|
import org.dspace.scripts.ProcessQueryParameterContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the Data Access Object for the {@link Process} object
|
* This is the Data Access Object for the {@link Process} object
|
||||||
@@ -54,4 +55,30 @@ public interface ProcessDAO extends GenericDAO<Process> {
|
|||||||
*/
|
*/
|
||||||
int countRows(Context context) throws SQLException;
|
int countRows(Context context) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all Processes in the database which match the given field requirements. If the
|
||||||
|
* requirements are not null, they will be combined with an AND operation.
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param processQueryParameterContainer The {@link ProcessQueryParameterContainer} containing all the values
|
||||||
|
* that the returned {@link Process} objects must adhere to
|
||||||
|
* @param limit The limit for the amount of Processes returned
|
||||||
|
* @param offset The offset for the Processes to be returned
|
||||||
|
* @return The list of all Processes which match the metadata requirements
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
List<Process> search(Context context, ProcessQueryParameterContainer processQueryParameterContainer, int limit,
|
||||||
|
int offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count all the processes which match the requirements. The requirements are evaluated like the search
|
||||||
|
* method.
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param processQueryParameterContainer The {@link ProcessQueryParameterContainer} containing all the values
|
||||||
|
* that the returned {@link Process} objects must adhere to
|
||||||
|
* @return The number of results matching the query
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
|
||||||
|
int countTotalWithParameters(Context context, ProcessQueryParameterContainer processQueryParameterContainer)
|
||||||
|
throws SQLException;
|
||||||
}
|
}
|
||||||
|
@@ -8,15 +8,20 @@
|
|||||||
package org.dspace.content.dao.impl;
|
package org.dspace.content.dao.impl;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Predicate;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.content.dao.ProcessDAO;
|
import org.dspace.content.dao.ProcessDAO;
|
||||||
import org.dspace.core.AbstractHibernateDAO;
|
import org.dspace.core.AbstractHibernateDAO;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.scripts.Process;
|
import org.dspace.scripts.Process;
|
||||||
|
import org.dspace.scripts.ProcessQueryParameterContainer;
|
||||||
import org.dspace.scripts.Process_;
|
import org.dspace.scripts.Process_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,6 +61,7 @@ public class ProcessDAOImpl extends AbstractHibernateDAO<Process> implements Pro
|
|||||||
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
|
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
|
||||||
Root<Process> processRoot = criteriaQuery.from(Process.class);
|
Root<Process> processRoot = criteriaQuery.from(Process.class);
|
||||||
criteriaQuery.select(processRoot);
|
criteriaQuery.select(processRoot);
|
||||||
|
criteriaQuery.orderBy(criteriaBuilder.desc(processRoot.get(Process_.processId)));
|
||||||
|
|
||||||
return list(context, criteriaQuery, false, Process.class, limit, offset);
|
return list(context, criteriaQuery, false, Process.class, limit, offset);
|
||||||
}
|
}
|
||||||
@@ -71,6 +77,76 @@ public class ProcessDAOImpl extends AbstractHibernateDAO<Process> implements Pro
|
|||||||
return count(context, criteriaQuery, criteriaBuilder, processRoot);
|
return count(context, criteriaQuery, criteriaBuilder, processRoot);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Process> search(Context context, ProcessQueryParameterContainer processQueryParameterContainer,
|
||||||
|
int limit, int offset) throws SQLException {
|
||||||
|
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||||
|
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
|
||||||
|
Root<Process> processRoot = criteriaQuery.from(Process.class);
|
||||||
|
criteriaQuery.select(processRoot);
|
||||||
|
|
||||||
|
handleProcessQueryParameters(processQueryParameterContainer, criteriaBuilder, criteriaQuery, processRoot);
|
||||||
|
return list(context, criteriaQuery, false, Process.class, limit, offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will ensure that the params contained in the {@link ProcessQueryParameterContainer} are transferred
|
||||||
|
* to the ProcessRoot and that the correct conditions apply to the query
|
||||||
|
* @param processQueryParameterContainer The object containing the conditions that need to be met
|
||||||
|
* @param criteriaBuilder The criteriaBuilder to be used
|
||||||
|
* @param criteriaQuery The criteriaQuery to be used
|
||||||
|
* @param processRoot The processRoot to be used
|
||||||
|
*/
|
||||||
|
private void handleProcessQueryParameters(ProcessQueryParameterContainer processQueryParameterContainer,
|
||||||
|
CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery,
|
||||||
|
Root<Process> processRoot) {
|
||||||
|
addProcessQueryParameters(processQueryParameterContainer, criteriaBuilder, criteriaQuery, processRoot);
|
||||||
|
if (StringUtils.equalsIgnoreCase(processQueryParameterContainer.getSortOrder(), "asc")) {
|
||||||
|
criteriaQuery
|
||||||
|
.orderBy(criteriaBuilder.asc(processRoot.get(processQueryParameterContainer.getSortProperty())));
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(processQueryParameterContainer.getSortOrder(), "desc")) {
|
||||||
|
criteriaQuery
|
||||||
|
.orderBy(criteriaBuilder.desc(processRoot.get(processQueryParameterContainer.getSortProperty())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will apply the variables in the {@link ProcessQueryParameterContainer} as criteria for the
|
||||||
|
* {@link Process} objects to the given CriteriaQuery.
|
||||||
|
* They'll need to adhere to these variables in order to be eligible for return
|
||||||
|
* @param processQueryParameterContainer The object containing the variables for the {@link Process}
|
||||||
|
* to adhere to
|
||||||
|
* @param criteriaBuilder The current CriteriaBuilder
|
||||||
|
* @param criteriaQuery The current CriteriaQuery
|
||||||
|
* @param processRoot The processRoot
|
||||||
|
*/
|
||||||
|
private void addProcessQueryParameters(ProcessQueryParameterContainer processQueryParameterContainer,
|
||||||
|
CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery,
|
||||||
|
Root<Process> processRoot) {
|
||||||
|
List<Predicate> andPredicates = new LinkedList<>();
|
||||||
|
|
||||||
|
for (Map.Entry<String, Object> entry : processQueryParameterContainer.getQueryParameterMap().entrySet()) {
|
||||||
|
andPredicates.add(criteriaBuilder.equal(processRoot.get(entry.getKey()), entry.getValue()));
|
||||||
|
}
|
||||||
|
criteriaQuery.where(criteriaBuilder.and(andPredicates.toArray(new Predicate[]{})));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countTotalWithParameters(Context context, ProcessQueryParameterContainer processQueryParameterContainer)
|
||||||
|
throws SQLException {
|
||||||
|
|
||||||
|
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||||
|
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
|
||||||
|
Root<Process> processRoot = criteriaQuery.from(Process.class);
|
||||||
|
criteriaQuery.select(processRoot);
|
||||||
|
|
||||||
|
addProcessQueryParameters(processQueryParameterContainer, criteriaBuilder, criteriaQuery, processRoot);
|
||||||
|
return count(context, criteriaQuery, criteriaBuilder, processRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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.discovery.indexobject;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.dspace.core.ReloadableEntity;
|
||||||
|
import org.dspace.discovery.IndexableObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class exists in order to provide a default implementation for the equals and hashCode methods.
|
||||||
|
* Since IndexableObjects can be made multiple times for the same underlying object, we needed a more finetuned
|
||||||
|
* equals and hashcode methods. We're simply checking that the underlying objects are equal and generating the hashcode
|
||||||
|
* for the underlying object. This way, we'll always get a proper result when calling equals or hashcode on an
|
||||||
|
* IndexableObject because it'll depend on the underlying object
|
||||||
|
* @param <T> Refers to the underlying entity that is linked to this object
|
||||||
|
* @param <PK> The type of ID that this entity uses
|
||||||
|
*/
|
||||||
|
public abstract class AbstractIndexableObject<T extends ReloadableEntity<PK>, PK extends Serializable>
|
||||||
|
implements IndexableObject<T,PK> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
//Two IndexableObjects of the same DSpaceObject are considered equal
|
||||||
|
if (!(obj instanceof AbstractIndexableObject)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IndexableDSpaceObject other = (IndexableDSpaceObject) obj;
|
||||||
|
return other.getIndexedObject().equals(getIndexedObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
//Two IndexableObjects of the same DSpaceObject are considered equal
|
||||||
|
return getIndexedObject().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.discovery.indexobject;
|
package org.dspace.discovery.indexobject;
|
||||||
|
|
||||||
import org.dspace.discovery.IndexableObject;
|
|
||||||
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
|
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,7 +14,7 @@ import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
|
|||||||
*
|
*
|
||||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public class IndexableClaimedTask implements IndexableObject<ClaimedTask, Integer> {
|
public class IndexableClaimedTask extends AbstractIndexableObject<ClaimedTask, Integer> {
|
||||||
|
|
||||||
private ClaimedTask claimedTask;
|
private ClaimedTask claimedTask;
|
||||||
public static final String TYPE = ClaimedTask.class.getSimpleName();
|
public static final String TYPE = ClaimedTask.class.getSimpleName();
|
||||||
|
@@ -10,7 +10,6 @@ package org.dspace.discovery.indexobject;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.discovery.IndexableObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DSpaceObject implementation for the IndexableObject, contains methods used by all DSpaceObject methods
|
* DSpaceObject implementation for the IndexableObject, contains methods used by all DSpaceObject methods
|
||||||
@@ -18,7 +17,7 @@ import org.dspace.discovery.IndexableObject;
|
|||||||
*
|
*
|
||||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public abstract class IndexableDSpaceObject<T extends DSpaceObject> implements IndexableObject<T, UUID> {
|
public abstract class IndexableDSpaceObject<T extends DSpaceObject> extends AbstractIndexableObject<T, UUID> {
|
||||||
|
|
||||||
private T dso;
|
private T dso;
|
||||||
|
|
||||||
@@ -40,4 +39,6 @@ public abstract class IndexableDSpaceObject<T extends DSpaceObject> implements I
|
|||||||
public UUID getID() {
|
public UUID getID() {
|
||||||
return dso.getID();
|
return dso.getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@@ -8,14 +8,13 @@
|
|||||||
package org.dspace.discovery.indexobject;
|
package org.dspace.discovery.indexobject;
|
||||||
|
|
||||||
import org.dspace.content.InProgressSubmission;
|
import org.dspace.content.InProgressSubmission;
|
||||||
import org.dspace.discovery.IndexableObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InProgressSubmission implementation for the IndexableObject
|
* InProgressSubmission implementation for the IndexableObject
|
||||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public abstract class IndexableInProgressSubmission<T extends InProgressSubmission>
|
public abstract class IndexableInProgressSubmission<T extends InProgressSubmission>
|
||||||
implements IndexableObject<T, Integer> {
|
extends AbstractIndexableObject<T, Integer> {
|
||||||
|
|
||||||
protected T inProgressSubmission;
|
protected T inProgressSubmission;
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@ import org.dspace.discovery.IndexableObject;
|
|||||||
*
|
*
|
||||||
* @author Maria Verdonck (Atmire) on 14/07/2020
|
* @author Maria Verdonck (Atmire) on 14/07/2020
|
||||||
*/
|
*/
|
||||||
public class IndexableMetadataField implements IndexableObject<MetadataField, Integer> {
|
public class IndexableMetadataField extends AbstractIndexableObject<MetadataField, Integer> {
|
||||||
|
|
||||||
private MetadataField metadataField;
|
private MetadataField metadataField;
|
||||||
public static final String TYPE = MetadataField.class.getSimpleName();
|
public static final String TYPE = MetadataField.class.getSimpleName();
|
||||||
|
@@ -7,14 +7,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.discovery.indexobject;
|
package org.dspace.discovery.indexobject;
|
||||||
|
|
||||||
import org.dspace.discovery.IndexableObject;
|
|
||||||
import org.dspace.xmlworkflow.storedcomponents.PoolTask;
|
import org.dspace.xmlworkflow.storedcomponents.PoolTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PoolTask implementation for the IndexableObject
|
* PoolTask implementation for the IndexableObject
|
||||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public class IndexablePoolTask implements IndexableObject<PoolTask, Integer> {
|
public class IndexablePoolTask extends AbstractIndexableObject<PoolTask, Integer> {
|
||||||
|
|
||||||
public static final String TYPE = PoolTask.class.getSimpleName();
|
public static final String TYPE = PoolTask.class.getSimpleName();
|
||||||
|
|
||||||
|
@@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* 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.scripts;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a container class in which the variables can be stored that a {@link Process} must adhere to when being
|
||||||
|
* retrieved from the DB through the search methods
|
||||||
|
*/
|
||||||
|
public class ProcessQueryParameterContainer {
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String, Object> queryParameterMap = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the queryParameterMap
|
||||||
|
* @return the queryParameterMap value of this ProcessQueryParameterContainer
|
||||||
|
*/
|
||||||
|
public Map<String, Object> getQueryParameterMap() {
|
||||||
|
return queryParameterMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sortProperty = "startTime";
|
||||||
|
private String sortOrder = "desc";
|
||||||
|
/**
|
||||||
|
* Generic setter for the queryParameterMap
|
||||||
|
* @param queryParameterMap The queryParameterMap to be set on this ProcessQueryParameterContainer
|
||||||
|
*/
|
||||||
|
public void setQueryParameterMap(Map<String, Object> queryParameterMap) {
|
||||||
|
this.queryParameterMap = queryParameterMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addToQueryParameterMap(String key, Object object) {
|
||||||
|
if (queryParameterMap == null) {
|
||||||
|
queryParameterMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
queryParameterMap.put(key, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the sortProperty
|
||||||
|
* @return the sortProperty value of this ProcessQueryParameterContainer
|
||||||
|
*/
|
||||||
|
public String getSortProperty() {
|
||||||
|
return sortProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the sortProperty
|
||||||
|
* @param sortProperty The sortProperty to be set on this ProcessQueryParameterContainer
|
||||||
|
*/
|
||||||
|
public void setSortProperty(String sortProperty) {
|
||||||
|
this.sortProperty = sortProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the sortOrder
|
||||||
|
* @return the sortOrder value of this ProcessQueryParameterContainer
|
||||||
|
*/
|
||||||
|
public String getSortOrder() {
|
||||||
|
return sortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the sortOrder
|
||||||
|
* @param sortOrder The sortOrder to be set on this ProcessQueryParameterContainer
|
||||||
|
*/
|
||||||
|
public void setSortOrder(String sortOrder) {
|
||||||
|
this.sortOrder = sortOrder;
|
||||||
|
}
|
||||||
|
}
|
@@ -255,6 +255,19 @@ public class ProcessServiceImpl implements ProcessService {
|
|||||||
return new ArrayList<>(fileTypesSet);
|
return new ArrayList<>(fileTypesSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Process> search(Context context, ProcessQueryParameterContainer processQueryParameterContainer,
|
||||||
|
int limit, int offset) throws SQLException {
|
||||||
|
return processDAO.search(context, processQueryParameterContainer, limit, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countSearch(Context context, ProcessQueryParameterContainer processQueryParameterContainer)
|
||||||
|
throws SQLException {
|
||||||
|
return processDAO.countTotalWithParameters(context, processQueryParameterContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendLog(int processId, String scriptName, String output, ProcessLogLevel processLogLevel)
|
public void appendLog(int processId, String scriptName, String output, ProcessLogLevel processLogLevel)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
@@ -19,6 +19,7 @@ import org.dspace.eperson.EPerson;
|
|||||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||||
import org.dspace.scripts.Process;
|
import org.dspace.scripts.Process;
|
||||||
import org.dspace.scripts.ProcessLogLevel;
|
import org.dspace.scripts.ProcessLogLevel;
|
||||||
|
import org.dspace.scripts.ProcessQueryParameterContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for the ProcessService with methods regarding the Process workload
|
* An interface for the ProcessService with methods regarding the Process workload
|
||||||
@@ -190,6 +191,30 @@ public interface ProcessService {
|
|||||||
*/
|
*/
|
||||||
public List<String> getFileTypesForProcessBitstreams(Context context, Process process);
|
public List<String> getFileTypesForProcessBitstreams(Context context, Process process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all Processes in the database which match the given field requirements. If the
|
||||||
|
* requirements are not null, they will be combined with an AND operation.
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param processQueryParameterContainer The {@link ProcessQueryParameterContainer} containing all the values
|
||||||
|
* that the returned {@link Process} objects must adhere to
|
||||||
|
* @param limit The limit for the amount of Processes returned
|
||||||
|
* @param offset The offset for the Processes to be returned
|
||||||
|
* @return The list of all Processes which match the metadata requirements
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
List<Process> search(Context context, ProcessQueryParameterContainer processQueryParameterContainer, int limit,
|
||||||
|
int offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count all the processes which match the requirements. The requirements are evaluated like the search
|
||||||
|
* method.
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param processQueryParameterContainer The {@link ProcessQueryParameterContainer} containing all the values
|
||||||
|
* that the returned {@link Process} objects must adhere to
|
||||||
|
* @return The number of results matching the query
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
int countSearch(Context context, ProcessQueryParameterContainer processQueryParameterContainer) throws SQLException;
|
||||||
/**
|
/**
|
||||||
* This method will append the given output to the {@link Process} its logs
|
* This method will append the given output to the {@link Process} its logs
|
||||||
* @param processId The ID of the {@link Process} to append the log for
|
* @param processId The ID of the {@link Process} to append the log for
|
||||||
|
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.statistics.export.dao.OpenURLTrackerDAO;
|
||||||
|
import org.dspace.statistics.export.service.FailedOpenURLTrackerService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the service that handles the OpenURLTracker database operations
|
||||||
|
*/
|
||||||
|
public class FailedOpenURLTrackerServiceImpl implements FailedOpenURLTrackerService {
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
protected OpenURLTrackerDAO openURLTrackerDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an OpenURLTracker from the database
|
||||||
|
* @param context
|
||||||
|
* @param openURLTracker
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void remove(Context context, OpenURLTracker openURLTracker) throws SQLException {
|
||||||
|
openURLTrackerDAO.delete(context, openURLTracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all OpenURLTrackers from the database
|
||||||
|
* @param context
|
||||||
|
* @return all OpenURLTrackers
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<OpenURLTracker> findAll(Context context) throws SQLException {
|
||||||
|
return openURLTrackerDAO.findAll(context, OpenURLTracker.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new OpenURLTracker
|
||||||
|
* @param context
|
||||||
|
* @return the creatred OpenURLTracker
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public OpenURLTracker create(Context context) throws SQLException {
|
||||||
|
OpenURLTracker openURLTracker = openURLTrackerDAO.create(context, new OpenURLTracker());
|
||||||
|
return openURLTracker;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.core.LogManager;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.model.Event;
|
||||||
|
import org.dspace.statistics.export.processor.BitstreamEventProcessor;
|
||||||
|
import org.dspace.statistics.export.processor.ItemEventProcessor;
|
||||||
|
import org.dspace.usage.AbstractUsageEventListener;
|
||||||
|
import org.dspace.usage.UsageEvent;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to receive usage events and send corresponding data to IRUS
|
||||||
|
*/
|
||||||
|
public class IrusExportUsageEventListener extends AbstractUsageEventListener {
|
||||||
|
/* Log4j logger*/
|
||||||
|
private static Logger log = Logger.getLogger(IrusExportUsageEventListener.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ConfigurationService configurationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives an event and processes to create a URL to send to IRUS when certain conditions are met
|
||||||
|
*
|
||||||
|
* @param event includes all the information related to the event that occurred
|
||||||
|
*/
|
||||||
|
public void receiveEvent(Event event) {
|
||||||
|
if (configurationService.getBooleanProperty("irus.statistics.tracker.enabled", false)) {
|
||||||
|
if (event instanceof UsageEvent) {
|
||||||
|
UsageEvent ue = (UsageEvent) event;
|
||||||
|
Context context = ue.getContext();
|
||||||
|
|
||||||
|
try {
|
||||||
|
//Check for item investigation
|
||||||
|
if (ue.getObject() instanceof Item) {
|
||||||
|
ItemEventProcessor itemEventProcessor = new ItemEventProcessor(context, ue.getRequest(),
|
||||||
|
(Item) ue.getObject());
|
||||||
|
itemEventProcessor.processEvent();
|
||||||
|
} else if (ue.getObject() instanceof Bitstream) {
|
||||||
|
|
||||||
|
BitstreamEventProcessor bitstreamEventProcessor =
|
||||||
|
new BitstreamEventProcessor(context, ue.getRequest(), (Bitstream) ue.getObject());
|
||||||
|
bitstreamEventProcessor.processEvent();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
UUID id;
|
||||||
|
id = ue.getObject().getID();
|
||||||
|
|
||||||
|
int type;
|
||||||
|
try {
|
||||||
|
type = ue.getObject().getType();
|
||||||
|
} catch (Exception e1) {
|
||||||
|
type = -1;
|
||||||
|
}
|
||||||
|
log.error(LogManager.getHeader(ue.getContext(), "Error while processing export of use event",
|
||||||
|
"Id: " + id + " type: " + type), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.SequenceGenerator;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Temporal;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
|
import org.dspace.core.ReloadableEntity;
|
||||||
|
import org.hibernate.proxy.HibernateProxyHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that represents an OpenURLTracker which tracks a failed transmission to IRUS
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "OpenUrlTracker")
|
||||||
|
public class OpenURLTracker implements ReloadableEntity<Integer> {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "tracker_id")
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "openurltracker_seq")
|
||||||
|
@SequenceGenerator(name = "openurltracker_seq", sequenceName = "openurltracker_seq", allocationSize = 1)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Column(name = "tracker_url", length = 1000)
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@Column(name = "uploaddate")
|
||||||
|
@Temporal(TemporalType.DATE)
|
||||||
|
private Date uploadDate;
|
||||||
|
|
||||||
|
protected OpenURLTracker() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the OpenURLTracker id
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Integer getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the OpenURLTracker url
|
||||||
|
* @return the url
|
||||||
|
*/
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the OpenURLTracker url
|
||||||
|
* @param url
|
||||||
|
*/
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the upload date
|
||||||
|
* @return upload date
|
||||||
|
*/
|
||||||
|
public Date getUploadDate() {
|
||||||
|
return uploadDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the upload date
|
||||||
|
* @param uploadDate
|
||||||
|
*/
|
||||||
|
public void setUploadDate(Date uploadDate) {
|
||||||
|
this.uploadDate = uploadDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether two objects of this class are equal by comparing the ID
|
||||||
|
* @param o - object to compare
|
||||||
|
* @return whether the objects are equal
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Class<?> objClass = HibernateProxyHelper.getClassWithoutInitializingProxy(o);
|
||||||
|
if (getClass() != objClass) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final OpenURLTracker that = (OpenURLTracker) o;
|
||||||
|
if (!this.getID().equals(that.getID())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hash code value for the object
|
||||||
|
* @return hash code
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 8;
|
||||||
|
hash = 74 * hash + this.getID();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.ParseException;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.statistics.export.factory.OpenURLTrackerLoggerServiceFactory;
|
||||||
|
import org.dspace.statistics.export.service.OpenUrlService;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script to retry the failed url transmissions to IRUS
|
||||||
|
* This script also has an option to add new failed urls for testing purposes
|
||||||
|
*/
|
||||||
|
public class RetryFailedOpenUrlTracker extends DSpaceRunnable<RetryFailedOpenUrlTrackerScriptConfiguration> {
|
||||||
|
|
||||||
|
private String lineToAdd = null;
|
||||||
|
private boolean help = false;
|
||||||
|
private boolean retryFailed = false;
|
||||||
|
|
||||||
|
private OpenUrlService openUrlService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the script
|
||||||
|
* When the -a option is used, a new "failed" url will be added to the database
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void internalRun() throws Exception {
|
||||||
|
if (help) {
|
||||||
|
printHelp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Context context = new Context();
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(lineToAdd)) {
|
||||||
|
openUrlService.logfailed(context, lineToAdd);
|
||||||
|
handler.logInfo("Created dummy entry in OpenUrlTracker with URL: " + lineToAdd);
|
||||||
|
}
|
||||||
|
if (retryFailed) {
|
||||||
|
handler.logInfo("Reprocessing failed URLs stored in the db");
|
||||||
|
openUrlService.reprocessFailedQueue(context);
|
||||||
|
}
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
context.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetryFailedOpenUrlTrackerScriptConfiguration getScriptConfiguration() {
|
||||||
|
return new DSpace().getServiceManager().getServiceByName("retry-tracker",
|
||||||
|
RetryFailedOpenUrlTrackerScriptConfiguration.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setups the parameters
|
||||||
|
*
|
||||||
|
* @throws ParseException
|
||||||
|
*/
|
||||||
|
public void setup() throws ParseException {
|
||||||
|
openUrlService = OpenURLTrackerLoggerServiceFactory.getInstance().getOpenUrlService();
|
||||||
|
|
||||||
|
if (!(commandLine.hasOption('a') || commandLine.hasOption('r') || commandLine.hasOption('h'))) {
|
||||||
|
throw new ParseException("At least one of the parameters (-a, -r, -h) is required!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption('h')) {
|
||||||
|
help = true;
|
||||||
|
}
|
||||||
|
if (commandLine.hasOption('a')) {
|
||||||
|
lineToAdd = commandLine.getOptionValue('a');
|
||||||
|
}
|
||||||
|
if (commandLine.hasOption('r')) {
|
||||||
|
retryFailed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ScriptConfiguration} for the {@link RetryFailedOpenUrlTracker} script
|
||||||
|
*/
|
||||||
|
public class RetryFailedOpenUrlTrackerScriptConfiguration<T extends RetryFailedOpenUrlTracker>
|
||||||
|
extends ScriptConfiguration<T> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
private Class<T> dspaceRunnableClass;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getDspaceRunnableClass() {
|
||||||
|
return dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the dspaceRunnableClass
|
||||||
|
*
|
||||||
|
* @param dspaceRunnableClass The dspaceRunnableClass to be set on this RetryFailedOpenUrlTrackerScriptConfiguration
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
|
||||||
|
this.dspaceRunnableClass = dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowedToExecute(Context context) {
|
||||||
|
try {
|
||||||
|
return authorizeService.isAdmin(context);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("SQLException occurred when checking if the current user is an admin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Options getOptions() {
|
||||||
|
if (options == null) {
|
||||||
|
Options options = new Options();
|
||||||
|
|
||||||
|
options.addOption("a", true, "Add a new \"failed\" row to the table with a url (test purposes only)");
|
||||||
|
options.getOption("a").setType(String.class);
|
||||||
|
|
||||||
|
options.addOption("r", false,
|
||||||
|
"Retry sending requests to all urls stored in the table with failed requests. " +
|
||||||
|
"This includes the url that can be added through the -a option.");
|
||||||
|
options.getOption("r").setType(boolean.class);
|
||||||
|
|
||||||
|
options.addOption("h", "help", false, "print this help message");
|
||||||
|
options.getOption("h").setType(boolean.class);
|
||||||
|
|
||||||
|
super.options = options;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.dao;
|
||||||
|
|
||||||
|
import org.dspace.core.GenericDAO;
|
||||||
|
import org.dspace.statistics.export.OpenURLTracker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database Access Object interface class for the OpenURLTracker object.
|
||||||
|
* The implementation of this class is responsible for all database calls for the OpenURLTracker object and is
|
||||||
|
* autowired by spring
|
||||||
|
* This class should only be accessed from a single service and should never be exposed outside of the API
|
||||||
|
*/
|
||||||
|
public interface OpenURLTrackerDAO extends GenericDAO<OpenURLTracker> {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.statistics.export.dao.impl;
|
||||||
|
|
||||||
|
import org.dspace.core.AbstractHibernateDAO;
|
||||||
|
import org.dspace.statistics.export.OpenURLTracker;
|
||||||
|
import org.dspace.statistics.export.dao.OpenURLTrackerDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hibernate implementation of the Database Access Object interface class for the OpenURLTracker object.
|
||||||
|
* This class is responsible for all database calls for the OpenURLTracker object and is autowired by spring
|
||||||
|
* This class should never be accessed directly.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class OpenURLTrackerDAOImpl extends AbstractHibernateDAO<OpenURLTracker> implements OpenURLTrackerDAO {
|
||||||
|
|
||||||
|
protected OpenURLTrackerDAOImpl() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.factory;
|
||||||
|
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.statistics.export.service.FailedOpenURLTrackerService;
|
||||||
|
import org.dspace.statistics.export.service.OpenUrlService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service factory for the OpenUrlTracker related services
|
||||||
|
*/
|
||||||
|
public abstract class OpenURLTrackerLoggerServiceFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FailedOpenURLTrackerService
|
||||||
|
* @return FailedOpenURLTrackerService instance
|
||||||
|
*/
|
||||||
|
public abstract FailedOpenURLTrackerService getOpenUrlTrackerLoggerService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the OpenURLTrackerLoggerServiceFactory
|
||||||
|
* @return OpenURLTrackerLoggerServiceFactory instance
|
||||||
|
*/
|
||||||
|
public static OpenURLTrackerLoggerServiceFactory getInstance() {
|
||||||
|
return DSpaceServicesFactory.getInstance().getServiceManager()
|
||||||
|
.getServiceByName("openURLTrackerLoggerServiceFactory",
|
||||||
|
OpenURLTrackerLoggerServiceFactory.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the OpenUrlService
|
||||||
|
* @return OpenUrlService instance
|
||||||
|
*/
|
||||||
|
public abstract OpenUrlService getOpenUrlService();
|
||||||
|
}
|
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.statistics.export.factory;
|
||||||
|
|
||||||
|
import org.dspace.statistics.export.service.FailedOpenURLTrackerService;
|
||||||
|
import org.dspace.statistics.export.service.OpenUrlService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service factory implementation for the OpenUrlTracker related services
|
||||||
|
*/
|
||||||
|
public class OpenURLTrackerLoggerServiceFactoryImpl extends OpenURLTrackerLoggerServiceFactory {
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
private FailedOpenURLTrackerService failedOpenURLTrackerService;
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
private OpenUrlService openUrlService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FailedOpenURLTrackerService
|
||||||
|
* @return FailedOpenURLTrackerService instance
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public FailedOpenURLTrackerService getOpenUrlTrackerLoggerService() {
|
||||||
|
return failedOpenURLTrackerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the OpenUrlService
|
||||||
|
* @return OpenUrlService instance
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public OpenUrlService getOpenUrlService() {
|
||||||
|
return openUrlService;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.processor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.Bundle;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.statistics.util.SpiderDetector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processor that handles Bitstream events from the IrusExportUsageEventListener
|
||||||
|
*/
|
||||||
|
public class BitstreamEventProcessor extends ExportEventProcessor {
|
||||||
|
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
|
||||||
|
private Item item;
|
||||||
|
private Bitstream bitstream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new BitstreamEventProcessor that will set the params and obtain the parent item of the bitstream
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param request
|
||||||
|
* @param bitstream
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public BitstreamEventProcessor(Context context, HttpServletRequest request, Bitstream bitstream)
|
||||||
|
throws SQLException {
|
||||||
|
super(context, request);
|
||||||
|
this.bitstream = bitstream;
|
||||||
|
this.item = getItem(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parent item of the bitsream
|
||||||
|
*
|
||||||
|
* @return parent item of the bitstream
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
private Item getItem(HttpServletRequest request) throws SQLException {
|
||||||
|
if (0 < bitstream.getBundles().size()) {
|
||||||
|
if (!SpiderDetector.isSpider(request)) {
|
||||||
|
Bundle bundle = bitstream.getBundles().get(0);
|
||||||
|
if (bundle.getName() == null || !bundle.getName().equals("ORIGINAL")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 < bundle.getItems().size()) {
|
||||||
|
Item item = bundle.getItems().get(0);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the event
|
||||||
|
* Check if the item should be processed
|
||||||
|
* Create the url to be transmitted based on item and bitstream data
|
||||||
|
*
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void processEvent() throws SQLException, IOException {
|
||||||
|
if (shouldProcessItem(item)) {
|
||||||
|
String baseParam = getBaseParameters(item);
|
||||||
|
String fullParam = addObjectSpecificData(baseParam, bitstream);
|
||||||
|
processObject(fullParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds additional item and bitstream data to the url
|
||||||
|
*
|
||||||
|
* @param string to which the additional data needs to be added
|
||||||
|
* @param bitstream
|
||||||
|
* @return the string with additional data
|
||||||
|
* @throws UnsupportedEncodingException
|
||||||
|
*/
|
||||||
|
protected String addObjectSpecificData(final String string, Bitstream bitstream)
|
||||||
|
throws UnsupportedEncodingException {
|
||||||
|
StringBuilder data = new StringBuilder(string);
|
||||||
|
|
||||||
|
String bitstreamInfo = getBitstreamInfo(bitstream);
|
||||||
|
data.append("&").append(URLEncoder.encode("svc_dat", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(bitstreamInfo, UTF_8));
|
||||||
|
data.append("&").append(URLEncoder.encode("rft_dat", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(BITSTREAM_DOWNLOAD, UTF_8));
|
||||||
|
|
||||||
|
return data.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Bitstream info used for the url
|
||||||
|
*
|
||||||
|
* @param bitstream
|
||||||
|
* @return bitstream info
|
||||||
|
*/
|
||||||
|
private String getBitstreamInfo(final Bitstream bitstream) {
|
||||||
|
|
||||||
|
String dspaceRestUrl = configurationService.getProperty("dspace.server.url");
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.append(dspaceRestUrl);
|
||||||
|
sb.append("/api/core/bitstreams/");
|
||||||
|
sb.append(bitstream.getID());
|
||||||
|
sb.append("/content");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,258 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.processor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.CharEncoding;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.content.DCDate;
|
||||||
|
import org.dspace.content.Entity;
|
||||||
|
import org.dspace.content.EntityType;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.MetadataValue;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.EntityService;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.core.Utils;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.statistics.export.factory.OpenURLTrackerLoggerServiceFactory;
|
||||||
|
import org.dspace.statistics.export.service.OpenUrlService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract export event processor that contains all shared logic to handle both Items and Bitstreams
|
||||||
|
* from the IrusExportUsageEventListener
|
||||||
|
*/
|
||||||
|
public abstract class ExportEventProcessor {
|
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(ExportEventProcessor.class);
|
||||||
|
|
||||||
|
protected static final String ENTITY_TYPE_DEFAULT = "Publication";
|
||||||
|
|
||||||
|
protected static final String ITEM_VIEW = "Investigation";
|
||||||
|
protected static final String BITSTREAM_DOWNLOAD = "Request";
|
||||||
|
|
||||||
|
protected final static String UTF_8 = CharEncoding.UTF_8;
|
||||||
|
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
private EntityService entityService = ContentServiceFactory.getInstance().getEntityService();
|
||||||
|
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
private OpenUrlService openUrlService = OpenURLTrackerLoggerServiceFactory.getInstance().getOpenUrlService();
|
||||||
|
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private HttpServletRequest request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ExportEventProcessor based on the params and initializes the services
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param request
|
||||||
|
*/
|
||||||
|
ExportEventProcessor(Context context, HttpServletRequest request) {
|
||||||
|
this.context = context;
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the event
|
||||||
|
*
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract void processEvent() throws SQLException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the url obtained from the object to be transmitted
|
||||||
|
*
|
||||||
|
* @param urlParameters
|
||||||
|
* @throws IOException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
protected void processObject(String urlParameters) throws IOException, SQLException {
|
||||||
|
String baseUrl;
|
||||||
|
if (StringUtils.equals(configurationService.getProperty("irus.statistics.tracker.environment"), "production")) {
|
||||||
|
baseUrl = configurationService.getProperty("irus.statistics.tracker.produrl");
|
||||||
|
} else {
|
||||||
|
baseUrl = configurationService.getProperty("irus.statistics.tracker.testurl");
|
||||||
|
}
|
||||||
|
|
||||||
|
openUrlService.processUrl(context, baseUrl + "?" + urlParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the base parameters for the url to be transmitted
|
||||||
|
*
|
||||||
|
* @param item
|
||||||
|
* @return the parameter string to be used in the url
|
||||||
|
* @throws UnsupportedEncodingException
|
||||||
|
*/
|
||||||
|
protected String getBaseParameters(Item item)
|
||||||
|
throws UnsupportedEncodingException {
|
||||||
|
|
||||||
|
//We have a valid url collect the rest of the data
|
||||||
|
String clientIP = request.getRemoteAddr();
|
||||||
|
if (configurationService.getBooleanProperty("useProxies", false) && request
|
||||||
|
.getHeader("X-Forwarded-For") != null) {
|
||||||
|
/* This header is a comma delimited list */
|
||||||
|
for (String xfip : request.getHeader("X-Forwarded-For").split(",")) {
|
||||||
|
/* proxy itself will sometime populate this header with the same value in
|
||||||
|
remote address. ordering in spec is vague, we'll just take the last
|
||||||
|
not equal to the proxy
|
||||||
|
*/
|
||||||
|
if (!request.getHeader("X-Forwarded-For").contains(clientIP)) {
|
||||||
|
clientIP = xfip.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String clientUA = StringUtils.defaultIfBlank(request.getHeader("USER-AGENT"), "");
|
||||||
|
String referer = StringUtils.defaultIfBlank(request.getHeader("referer"), "");
|
||||||
|
|
||||||
|
//Start adding our data
|
||||||
|
StringBuilder data = new StringBuilder();
|
||||||
|
data.append(URLEncoder.encode("url_ver", UTF_8) + "=" +
|
||||||
|
URLEncoder.encode(configurationService.getProperty("irus.statistics.tracker.urlversion"), UTF_8));
|
||||||
|
data.append("&").append(URLEncoder.encode("req_id", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(clientIP, UTF_8));
|
||||||
|
data.append("&").append(URLEncoder.encode("req_dat", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(clientUA, UTF_8));
|
||||||
|
|
||||||
|
String hostName = Utils.getHostName(configurationService.getProperty("dspace.ui.url"));
|
||||||
|
|
||||||
|
data.append("&").append(URLEncoder.encode("rft.artnum", UTF_8)).append("=").
|
||||||
|
append(URLEncoder.encode("oai:" + hostName + ":" + item
|
||||||
|
.getHandle(), UTF_8));
|
||||||
|
data.append("&").append(URLEncoder.encode("rfr_dat", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(referer, UTF_8));
|
||||||
|
data.append("&").append(URLEncoder.encode("rfr_id", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(hostName, UTF_8));
|
||||||
|
data.append("&").append(URLEncoder.encode("url_tim", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(getCurrentDateString(), UTF_8));
|
||||||
|
|
||||||
|
return data.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current date
|
||||||
|
*
|
||||||
|
* @return the current date as a string
|
||||||
|
*/
|
||||||
|
protected String getCurrentDateString() {
|
||||||
|
return new DCDate(new Date()).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an item should be processed
|
||||||
|
*
|
||||||
|
* @param item to be checked
|
||||||
|
* @return whether the item should be processed
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
protected boolean shouldProcessItem(Item item) throws SQLException {
|
||||||
|
if (item == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!item.isArchived()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (itemService.canEdit(context, item)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!shouldProcessItemType(item)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!shouldProcessEntityType(item)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the item's entity type should be processed
|
||||||
|
*
|
||||||
|
* @param item to be checked
|
||||||
|
* @return whether the item should be processed
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
protected boolean shouldProcessEntityType(Item item) throws SQLException {
|
||||||
|
Entity entity = entityService.findByItemId(context, item.getID());
|
||||||
|
EntityType type = entityService.getType(context, entity);
|
||||||
|
|
||||||
|
String[] entityTypeStrings = configurationService.getArrayProperty("irus.statistics.tracker.entity-types");
|
||||||
|
List<String> entityTypes = new ArrayList<>();
|
||||||
|
|
||||||
|
if (entityTypeStrings.length != 0) {
|
||||||
|
entityTypes.addAll(Arrays.asList(entityTypeStrings));
|
||||||
|
} else {
|
||||||
|
entityTypes.add(ENTITY_TYPE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != null && entityTypes.contains(type.getLabel())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the item should be excluded based on the its type
|
||||||
|
*
|
||||||
|
* @param item to be checked
|
||||||
|
* @return whether the item should be processed
|
||||||
|
*/
|
||||||
|
protected boolean shouldProcessItemType(Item item) {
|
||||||
|
String trackerTypeMetadataField = configurationService.getProperty("irus.statistics.tracker.type-field");
|
||||||
|
String[] metadataValues = configurationService.getArrayProperty("irus.statistics.tracker.type-value");
|
||||||
|
List<String> trackerTypeMetadataValues;
|
||||||
|
if (metadataValues.length > 0) {
|
||||||
|
trackerTypeMetadataValues = new ArrayList<>();
|
||||||
|
for (String metadataValue : metadataValues) {
|
||||||
|
trackerTypeMetadataValues.add(metadataValue.toLowerCase());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trackerTypeMetadataValues = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trackerTypeMetadataField != null && trackerTypeMetadataValues != null) {
|
||||||
|
|
||||||
|
// Contains the schema, element and if present qualifier of the metadataField
|
||||||
|
String[] metadataFieldSplit = trackerTypeMetadataField.split("\\.");
|
||||||
|
|
||||||
|
List<MetadataValue> types = itemService
|
||||||
|
.getMetadata(item, metadataFieldSplit[0], metadataFieldSplit[1],
|
||||||
|
metadataFieldSplit.length == 2 ? null : metadataFieldSplit[2], Item.ANY);
|
||||||
|
|
||||||
|
if (!types.isEmpty()) {
|
||||||
|
//Find out if we have a type that needs to be excluded
|
||||||
|
for (MetadataValue type : types) {
|
||||||
|
if (trackerTypeMetadataValues.contains(type.getValue().toLowerCase())) {
|
||||||
|
//We have found no type so process this item
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// No types in this item, so not excluded
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No types to be excluded
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.processor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processor that handles Item events from the IrusExportUsageEventListener
|
||||||
|
*/
|
||||||
|
public class ItemEventProcessor extends ExportEventProcessor {
|
||||||
|
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
private Item item;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ItemEventProcessor that will set the params
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param request
|
||||||
|
* @param item
|
||||||
|
*/
|
||||||
|
public ItemEventProcessor(Context context, HttpServletRequest request, Item item) {
|
||||||
|
super(context, request);
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the event
|
||||||
|
* Check if the item should be processed
|
||||||
|
* Create the url to be transmitted based on item data
|
||||||
|
*
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void processEvent() throws SQLException, IOException {
|
||||||
|
if (shouldProcessItem(item)) {
|
||||||
|
String baseParam = getBaseParameters(item);
|
||||||
|
String fullParam = addObjectSpecificData(baseParam, item);
|
||||||
|
processObject(fullParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds additional item data to the url
|
||||||
|
*
|
||||||
|
* @param string to which the additional data needs to be added
|
||||||
|
* @param item
|
||||||
|
* @return the string with additional data
|
||||||
|
* @throws UnsupportedEncodingException
|
||||||
|
*/
|
||||||
|
protected String addObjectSpecificData(final String string, Item item) throws UnsupportedEncodingException {
|
||||||
|
StringBuilder data = new StringBuilder(string);
|
||||||
|
String itemInfo = getItemInfo(item);
|
||||||
|
data.append("&").append(URLEncoder.encode("svc_dat", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(itemInfo, UTF_8));
|
||||||
|
data.append("&").append(URLEncoder.encode("rft_dat", UTF_8)).append("=")
|
||||||
|
.append(URLEncoder.encode(ITEM_VIEW, UTF_8));
|
||||||
|
return data.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Item info used for the url
|
||||||
|
*
|
||||||
|
* @param item
|
||||||
|
* @return item info
|
||||||
|
*/
|
||||||
|
private String getItemInfo(final Item item) {
|
||||||
|
StringBuilder sb = new StringBuilder(configurationService.getProperty("dspace.ui.url"));
|
||||||
|
sb.append("/handle/").append(item.getHandle());
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.service;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.statistics.export.OpenURLTracker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface of the service that handles the OpenURLTracker database operations
|
||||||
|
*/
|
||||||
|
public interface FailedOpenURLTrackerService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an OpenURLTracker from the database
|
||||||
|
* @param context
|
||||||
|
* @param openURLTracker
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
void remove(Context context, OpenURLTracker openURLTracker) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all OpenURLTrackers from the database
|
||||||
|
* @param context
|
||||||
|
* @return all OpenURLTrackers
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
List<OpenURLTracker> findAll(Context context) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new OpenURLTracker
|
||||||
|
* @param context
|
||||||
|
* @return the creatred OpenURLTracker
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
OpenURLTracker create(Context context) throws SQLException;
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Service responsible for processing urls
|
||||||
|
*/
|
||||||
|
public interface OpenUrlService {
|
||||||
|
/**
|
||||||
|
* Process the url
|
||||||
|
* @param c - the context
|
||||||
|
* @param urlStr - the url to be processed
|
||||||
|
* @throws IOException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
void processUrl(Context c, String urlStr) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will process all urls stored in the database and try contacting them again
|
||||||
|
* @param context
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
void reprocessFailedQueue(Context context) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will log the failed url in the database
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
void logfailed(Context context, String url) throws SQLException;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,139 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.statistics.export.OpenURLTracker;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the OpenUrlService interface
|
||||||
|
*/
|
||||||
|
public class OpenUrlServiceImpl implements OpenUrlService {
|
||||||
|
|
||||||
|
private Logger log = Logger.getLogger(OpenUrlService.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected FailedOpenURLTrackerService failedOpenUrlTrackerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the url
|
||||||
|
* When the contacting the url fails, the url will be logged in a db table
|
||||||
|
* @param c - the context
|
||||||
|
* @param urlStr - the url to be processed
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public void processUrl(Context c, String urlStr) throws SQLException {
|
||||||
|
log.debug("Prepared to send url to tracker URL: " + urlStr);
|
||||||
|
|
||||||
|
try {
|
||||||
|
int responseCode = getResponseCodeFromUrl(urlStr);
|
||||||
|
if (responseCode != HttpURLConnection.HTTP_OK) {
|
||||||
|
logfailed(c, urlStr);
|
||||||
|
} else if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Successfully posted " + urlStr + " on " + new Date());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to send url to tracker URL: " + urlStr);
|
||||||
|
logfailed(c, urlStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the response code from accessing the url
|
||||||
|
* @param urlStr
|
||||||
|
* @return response code from the url
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected int getResponseCodeFromUrl(final String urlStr) throws IOException {
|
||||||
|
URLConnection conn;
|
||||||
|
URL url = new URL(urlStr);
|
||||||
|
conn = url.openConnection();
|
||||||
|
|
||||||
|
HttpURLConnection httpURLConnection = (HttpURLConnection) conn;
|
||||||
|
int responseCode = httpURLConnection.getResponseCode();
|
||||||
|
httpURLConnection.disconnect();
|
||||||
|
|
||||||
|
return responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retry to send a failed url
|
||||||
|
* @param context
|
||||||
|
* @param tracker - db object containing the failed url
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
protected void tryReprocessFailed(Context context, OpenURLTracker tracker) throws SQLException {
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
|
||||||
|
int responseCode = getResponseCodeFromUrl(tracker.getUrl());
|
||||||
|
|
||||||
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
success = false;
|
||||||
|
} finally {
|
||||||
|
if (success) {
|
||||||
|
failedOpenUrlTrackerService
|
||||||
|
.remove(context, tracker);
|
||||||
|
// If the tracker was able to post successfully, we remove it from the database
|
||||||
|
log.info("Successfully posted " + tracker.getUrl() + " from " + tracker.getUploadDate());
|
||||||
|
} else {
|
||||||
|
// Still no luck - write an error msg but keep the entry in the table for future executions
|
||||||
|
log.error("Failed attempt from " + tracker.getUrl() + " originating from " + tracker.getUploadDate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reprocess all url trackers present in the database
|
||||||
|
* @param context
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public void reprocessFailedQueue(Context context) throws SQLException {
|
||||||
|
if (failedOpenUrlTrackerService == null) {
|
||||||
|
log.error("Error retrieving the \"failedOpenUrlTrackerService\" instance, aborting the processing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<OpenURLTracker> openURLTrackers = failedOpenUrlTrackerService.findAll(context);
|
||||||
|
for (OpenURLTracker openURLTracker : openURLTrackers) {
|
||||||
|
tryReprocessFailed(context, openURLTracker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a failed url in the database
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public void logfailed(Context context, String url) throws SQLException {
|
||||||
|
Date now = new Date();
|
||||||
|
if (StringUtils.isBlank(url)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenURLTracker tracker = failedOpenUrlTrackerService.create(context);
|
||||||
|
tracker.setUploadDate(now);
|
||||||
|
tracker.setUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -10,8 +10,13 @@ package org.dspace.storage.rdbms;
|
|||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Site;
|
||||||
import org.dspace.content.service.SiteService;
|
import org.dspace.content.service.SiteService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.Group;
|
||||||
|
import org.dspace.eperson.service.GroupService;
|
||||||
import org.flywaydb.core.api.MigrationInfo;
|
import org.flywaydb.core.api.MigrationInfo;
|
||||||
import org.flywaydb.core.api.callback.FlywayCallback;
|
import org.flywaydb.core.api.callback.FlywayCallback;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -29,6 +34,12 @@ public class SiteServiceInitializer implements FlywayCallback {
|
|||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected SiteService siteService;
|
protected SiteService siteService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GroupService groupService;
|
||||||
|
|
||||||
public void initializeSiteObject() {
|
public void initializeSiteObject() {
|
||||||
// After every migrate, ensure default Site is setup correctly.
|
// After every migrate, ensure default Site is setup correctly.
|
||||||
Context context = null;
|
Context context = null;
|
||||||
@@ -37,10 +48,19 @@ public class SiteServiceInitializer implements FlywayCallback {
|
|||||||
context.turnOffAuthorisationSystem();
|
context.turnOffAuthorisationSystem();
|
||||||
// While it's not really a formal "registry", we need to ensure the
|
// While it's not really a formal "registry", we need to ensure the
|
||||||
// default, required Groups exist in the DSpace database
|
// default, required Groups exist in the DSpace database
|
||||||
|
Site site = null;
|
||||||
if (siteService.findSite(context) == null) {
|
if (siteService.findSite(context) == null) {
|
||||||
siteService.createSite(context);
|
site = siteService.createSite(context);
|
||||||
}
|
}
|
||||||
context.restoreAuthSystemState();
|
context.restoreAuthSystemState();
|
||||||
|
if (!authorizeService.authorizeActionBoolean(context, site, Constants.READ)) {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Group anonGroup = groupService.findByName(context, Group.ANONYMOUS);
|
||||||
|
if (anonGroup != null) {
|
||||||
|
authorizeService.addPolicy(context, site, Constants.READ, anonGroup);
|
||||||
|
}
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
// Commit changes and close context
|
// Commit changes and close context
|
||||||
context.complete();
|
context.complete();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@@ -0,0 +1,29 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-- ===============================================================
|
||||||
|
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||||
|
--
|
||||||
|
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
|
||||||
|
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
|
||||||
|
-- http://flywaydb.org/
|
||||||
|
-- ===============================================================
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
-- This will create the setup for the IRUS statistics harvester
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE SEQUENCE openurltracker_seq;
|
||||||
|
|
||||||
|
CREATE TABLE openurltracker
|
||||||
|
(
|
||||||
|
tracker_id INTEGER,
|
||||||
|
tracker_url VARCHAR(1000),
|
||||||
|
uploaddate DATE,
|
||||||
|
CONSTRAINT openurltracker_PK PRIMARY KEY (tracker_id)
|
||||||
|
);
|
@@ -0,0 +1,29 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-- ===============================================================
|
||||||
|
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||||
|
--
|
||||||
|
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
|
||||||
|
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
|
||||||
|
-- http://flywaydb.org/
|
||||||
|
-- ===============================================================
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
-- This will create the setup for the IRUS statistics harvester
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE SEQUENCE openurltracker_seq;
|
||||||
|
|
||||||
|
CREATE TABLE openurltracker
|
||||||
|
(
|
||||||
|
tracker_id NUMBER,
|
||||||
|
tracker_url VARCHAR2(1000),
|
||||||
|
uploaddate DATE,
|
||||||
|
CONSTRAINT openurltracker_PK PRIMARY KEY (tracker_id)
|
||||||
|
);
|
@@ -0,0 +1,29 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-- ===============================================================
|
||||||
|
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||||
|
--
|
||||||
|
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
|
||||||
|
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
|
||||||
|
-- http://flywaydb.org/
|
||||||
|
-- ===============================================================
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
-- This will create the setup for the IRUS statistics harvester
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE SEQUENCE openurltracker_seq;
|
||||||
|
|
||||||
|
CREATE TABLE openurltracker
|
||||||
|
(
|
||||||
|
tracker_id INTEGER,
|
||||||
|
tracker_url VARCHAR(1000),
|
||||||
|
uploaddate DATE,
|
||||||
|
CONSTRAINT openurltracker_PK PRIMARY KEY (tracker_id)
|
||||||
|
);
|
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans
|
||||||
|
xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:util="http://www.springframework.org/schema/util"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
|
||||||
|
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
|
||||||
|
|
||||||
|
<!-- Irus statistics tracking -->
|
||||||
|
<bean class="org.dspace.statistics.export.IrusExportUsageEventListener">
|
||||||
|
<property name="eventService" ref="org.dspace.services.EventService"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
|
||||||
|
default-lazy-init="true">
|
||||||
|
|
||||||
|
|
||||||
|
<bean class="org.dspace.statistics.export.FailedOpenURLTrackerServiceImpl"/>
|
||||||
|
<bean class="org.dspace.statistics.export.service.MockOpenUrlServiceImpl"
|
||||||
|
id="org.dspace.statistics.export.service.OpenUrlService"/>
|
||||||
|
|
||||||
|
<bean id="testProcessedUrls" class="java.util.ArrayList"/>
|
||||||
|
|
||||||
|
</beans>
|
@@ -27,9 +27,19 @@
|
|||||||
<property name="dspaceRunnableClass" value="org.dspace.curate.CurationCli"/>
|
<property name="dspaceRunnableClass" value="org.dspace.curate.CurationCli"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="retry-tracker" class="org.dspace.statistics.export.RetryFailedOpenUrlTrackerScriptConfiguration" scope="prototype">
|
||||||
|
<property name="description" value="Retry all failed commits to the OpenURLTracker"/>
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.statistics.export.RetryFailedOpenUrlTracker"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="another-mock-script" class="org.dspace.scripts.MockDSpaceRunnableScriptConfiguration" scope="prototype">
|
||||||
|
<property name="description" value="Mocking a script for testing purposes" />
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.scripts.impl.MockDSpaceRunnableScript"/>
|
||||||
|
</bean>
|
||||||
<!-- Keep as last script; for test ScriptRestRepository#findOneScriptByNameTest -->
|
<!-- Keep as last script; for test ScriptRestRepository#findOneScriptByNameTest -->
|
||||||
<bean id="mock-script" class="org.dspace.scripts.MockDSpaceRunnableScriptConfiguration" scope="prototype">
|
<bean id="mock-script" class="org.dspace.scripts.MockDSpaceRunnableScriptConfiguration" scope="prototype">
|
||||||
<property name="description" value="Mocking a script for testing purposes" />
|
<property name="description" value="Mocking a script for testing purposes" />
|
||||||
<property name="dspaceRunnableClass" value="org.dspace.scripts.impl.MockDSpaceRunnableScript"/>
|
<property name="dspaceRunnableClass" value="org.dspace.scripts.impl.MockDSpaceRunnableScript"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -90,6 +90,10 @@ public class ItemBuilder extends AbstractDSpaceObjectBuilder<Item> {
|
|||||||
return addMetadataValue(item, "relationship", "type", null, relationshipType);
|
return addMetadataValue(item, "relationship", "type", null, relationshipType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ItemBuilder withType(final String type) {
|
||||||
|
return addMetadataValue(item, "dc", "type", null, type);
|
||||||
|
}
|
||||||
|
|
||||||
public ItemBuilder withPublicationIssueNumber(final String issueNumber) {
|
public ItemBuilder withPublicationIssueNumber(final String issueNumber) {
|
||||||
return addMetadataValue(item, "publicationissue", "issueNumber", null, issueNumber);
|
return addMetadataValue(item, "publicationissue", "issueNumber", null, issueNumber);
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,8 @@ package org.dspace.builder;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
@@ -43,6 +45,18 @@ public class ProcessBuilder extends AbstractBuilder<Process, ProcessService> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProcessBuilder withProcessStatus(ProcessStatus processStatus) {
|
||||||
|
process.setProcessStatus(processStatus);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessBuilder withStartAndEndTime(String startTime, String endTime) throws ParseException {
|
||||||
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");
|
||||||
|
process.setStartTime(simpleDateFormat.parse(startTime));
|
||||||
|
process.setFinishedTime(simpleDateFormat.parse(endTime));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cleanup() throws Exception {
|
public void cleanup() throws Exception {
|
||||||
try (Context c = new Context()) {
|
try (Context c = new Context()) {
|
||||||
|
@@ -1013,7 +1013,8 @@ public class CommunityTest extends AbstractDSpaceObjectTest {
|
|||||||
equalTo(c));
|
equalTo(c));
|
||||||
assertThat("testGetAdminObject 1", (Community) communityService.getAdminObject(context, c, Constants.ADD),
|
assertThat("testGetAdminObject 1", (Community) communityService.getAdminObject(context, c, Constants.ADD),
|
||||||
equalTo(c));
|
equalTo(c));
|
||||||
assertThat("testGetAdminObject 2", communityService.getAdminObject(context, c, Constants.DELETE), nullValue());
|
assertThat("testGetAdminObject 2", (Community) communityService.getAdminObject(context, c, Constants.DELETE),
|
||||||
|
equalTo(c));
|
||||||
assertThat("testGetAdminObject 3", (Community) communityService.getAdminObject(context, c, Constants.ADMIN),
|
assertThat("testGetAdminObject 3", (Community) communityService.getAdminObject(context, c, Constants.ADMIN),
|
||||||
equalTo(c));
|
equalTo(c));
|
||||||
}
|
}
|
||||||
|
@@ -1598,8 +1598,8 @@ public class ItemTest extends AbstractDSpaceObjectTest {
|
|||||||
assertThat("testGetAdminObject 0", (Item) itemService.getAdminObject(context, it, Constants.REMOVE),
|
assertThat("testGetAdminObject 0", (Item) itemService.getAdminObject(context, it, Constants.REMOVE),
|
||||||
equalTo(it));
|
equalTo(it));
|
||||||
assertThat("testGetAdminObject 1", (Item) itemService.getAdminObject(context, it, Constants.ADD), equalTo(it));
|
assertThat("testGetAdminObject 1", (Item) itemService.getAdminObject(context, it, Constants.ADD), equalTo(it));
|
||||||
assertThat("testGetAdminObject 2", (Collection) itemService.getAdminObject(context, it, Constants.DELETE),
|
assertThat("testGetAdminObject 2", (Item) itemService.getAdminObject(context, it, Constants.DELETE),
|
||||||
equalTo(collection));
|
equalTo(it));
|
||||||
assertThat("testGetAdminObject 3", (Item) itemService.getAdminObject(context, it, Constants.ADMIN),
|
assertThat("testGetAdminObject 3", (Item) itemService.getAdminObject(context, it, Constants.ADMIN),
|
||||||
equalTo(it));
|
equalTo(it));
|
||||||
}
|
}
|
||||||
|
@@ -14,13 +14,16 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.AbstractUnitTest;
|
import org.dspace.AbstractUnitTest;
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
import org.dspace.content.service.SiteService;
|
import org.dspace.content.service.SiteService;
|
||||||
import org.dspace.core.ConfigurationManager;
|
import org.dspace.core.ConfigurationManager;
|
||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.eperson.Group;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -143,4 +146,17 @@ public class SiteTest extends AbstractUnitTest {
|
|||||||
assertThat("testGetURL 0", s.getURL(), equalTo(ConfigurationManager.getProperty("dspace.ui.url")));
|
assertThat("testGetURL 0", s.getURL(), equalTo(ConfigurationManager.getProperty("dspace.ui.url")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAnonymousReadRights() throws Exception {
|
||||||
|
List<Group> groupList = authorizeService.getAuthorizedGroups(context, s, Constants.READ);
|
||||||
|
boolean foundAnonInList = false;
|
||||||
|
for (Group group : groupList) {
|
||||||
|
if (StringUtils.equalsIgnoreCase(group.getName(), "Anonymous")) {
|
||||||
|
foundAnonInList = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(foundAnonInList);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.statistics.export.dao.OpenURLTrackerDAO;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to test the FailedOpenURLTrackerServiceImpl
|
||||||
|
*/
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class FailedOpenURLTrackerServiceImplTest {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private FailedOpenURLTrackerServiceImpl openURLTrackerLoggerService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private OpenURLTracker openURLTracker;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private OpenURLTrackerDAO openURLTrackerDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the remove method
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemove() throws SQLException {
|
||||||
|
openURLTrackerLoggerService.remove(context, openURLTracker);
|
||||||
|
|
||||||
|
Mockito.verify(openURLTrackerDAO, times(1)).delete(context, openURLTracker);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the findAll method
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testFindAll() throws SQLException {
|
||||||
|
List<OpenURLTracker> trackers = new ArrayList<>();
|
||||||
|
|
||||||
|
when(openURLTrackerDAO.findAll(context, OpenURLTracker.class)).thenReturn(trackers);
|
||||||
|
|
||||||
|
assertEquals("TestFindAll 0", trackers, openURLTrackerLoggerService.findAll(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the create method
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCreate() throws SQLException {
|
||||||
|
OpenURLTracker tracker = new OpenURLTracker();
|
||||||
|
|
||||||
|
when(openURLTrackerDAO.create(any(), any())).thenReturn(tracker);
|
||||||
|
|
||||||
|
assertEquals("TestCreate 0", tracker, openURLTrackerLoggerService.create(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,418 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.CharEncoding;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.builder.BitstreamBuilder;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.EntityTypeBuilder;
|
||||||
|
import org.dspace.builder.ItemBuilder;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.EntityType;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.BitstreamService;
|
||||||
|
import org.dspace.content.service.BundleService;
|
||||||
|
import org.dspace.content.service.CollectionService;
|
||||||
|
import org.dspace.content.service.CommunityService;
|
||||||
|
import org.dspace.content.service.EntityTypeService;
|
||||||
|
import org.dspace.content.service.InstallItemService;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.content.service.WorkspaceItemService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||||
|
import org.dspace.eperson.service.EPersonService;
|
||||||
|
import org.dspace.eperson.service.GroupService;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.statistics.export.factory.OpenURLTrackerLoggerServiceFactory;
|
||||||
|
import org.dspace.statistics.export.service.FailedOpenURLTrackerService;
|
||||||
|
import org.dspace.usage.UsageEvent;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for the IrusExportUsageEventListener
|
||||||
|
*/
|
||||||
|
//@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class ITIrusExportUsageEventListener extends AbstractIntegrationTestWithDatabase {
|
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(ITIrusExportUsageEventListener.class);
|
||||||
|
|
||||||
|
|
||||||
|
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
|
||||||
|
protected ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||||
|
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
protected InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService();
|
||||||
|
protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
|
||||||
|
protected EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||||
|
protected GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
|
||||||
|
protected BundleService bundleService = ContentServiceFactory.getInstance().getBundleService();
|
||||||
|
protected BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
|
||||||
|
protected EntityTypeService entityTypeService = ContentServiceFactory.getInstance().getEntityTypeService();
|
||||||
|
protected FailedOpenURLTrackerService failedOpenURLTrackerService =
|
||||||
|
OpenURLTrackerLoggerServiceFactory.getInstance().getOpenUrlTrackerLoggerService();
|
||||||
|
|
||||||
|
protected ArrayList testProcessedUrls = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||||
|
.getServiceByName("testProcessedUrls",
|
||||||
|
ArrayList.class);
|
||||||
|
|
||||||
|
private IrusExportUsageEventListener exportUsageEventListener =
|
||||||
|
DSpaceServicesFactory.getInstance()
|
||||||
|
.getServiceManager()
|
||||||
|
.getServicesByType(IrusExportUsageEventListener.class)
|
||||||
|
.get(0);
|
||||||
|
|
||||||
|
private Item item;
|
||||||
|
private Item itemNotToBeProcessed;
|
||||||
|
private Bitstream bitstream;
|
||||||
|
private Bitstream bitstreamNotToBeProcessed;
|
||||||
|
private EntityType entityType;
|
||||||
|
private Community community;
|
||||||
|
private Collection collection;
|
||||||
|
|
||||||
|
private String encodedUrl;
|
||||||
|
private String encodedUIUrl;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the test by setting up all objects needed to create a test item
|
||||||
|
*/
|
||||||
|
@Before()
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.enabled", true);
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.type-field", "dc.type");
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.type-value", "Excluded type");
|
||||||
|
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
try {
|
||||||
|
|
||||||
|
entityType = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication").build();
|
||||||
|
community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
item = ItemBuilder.createItem(context, collection)
|
||||||
|
.withRelationshipType(entityType.getLabel())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
File f = new File(testProps.get("test.bitstream").toString());
|
||||||
|
bitstream = BitstreamBuilder.createBitstream(context, item, new FileInputStream(f)).build();
|
||||||
|
|
||||||
|
itemNotToBeProcessed = ItemBuilder.createItem(context, collection)
|
||||||
|
.withRelationshipType(entityType.getLabel())
|
||||||
|
.withType("Excluded type")
|
||||||
|
.build();
|
||||||
|
File itemNotToBeProcessedFile = new File(testProps.get("test.bitstream").toString());
|
||||||
|
bitstreamNotToBeProcessed = BitstreamBuilder
|
||||||
|
.createBitstream(context, itemNotToBeProcessed, new FileInputStream(itemNotToBeProcessedFile))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String dspaceUrl = configurationService.getProperty("dspace.server.url");
|
||||||
|
encodedUrl = URLEncoder.encode(dspaceUrl, CharEncoding.UTF_8);
|
||||||
|
String dspaceUIUrl = configurationService.getProperty("dspace.ui.url");
|
||||||
|
encodedUIUrl = URLEncoder.encode(dspaceUIUrl, CharEncoding.UTF_8);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up the created objects
|
||||||
|
* Empty the testProcessedUrls used to store succeeded urls
|
||||||
|
* Empty the database table where the failed urls are logged
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
try {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
for (OpenURLTracker tracker : all) {
|
||||||
|
failedOpenURLTrackerService.remove(context, tracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the list of processedUrls
|
||||||
|
testProcessedUrls.clear();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
context.complete();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the usage event of an item meeting all conditions is processed and succeeds
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReceiveEventOnItemThatShouldBeProcessed() throws UnsupportedEncodingException, SQLException {
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
when(request.getRemoteAddr()).thenReturn("client-ip");
|
||||||
|
when(request.getHeader(anyString())).thenReturn(null);
|
||||||
|
|
||||||
|
UsageEvent usageEvent = mock(UsageEvent.class);
|
||||||
|
when(usageEvent.getObject()).thenReturn(item);
|
||||||
|
when(usageEvent.getRequest()).thenReturn(request);
|
||||||
|
when(usageEvent.getContext()).thenReturn(new Context());
|
||||||
|
|
||||||
|
exportUsageEventListener.receiveEvent(usageEvent);
|
||||||
|
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
|
||||||
|
|
||||||
|
String regex = "https://irus.jisc.ac.uk/counter/test/\\?url_ver=Z39.88-2004&req_id=" +
|
||||||
|
URLEncoder.encode(request.getRemoteAddr(), "UTF-8") + "&req_dat=&rft" +
|
||||||
|
".artnum=oai%3Alocalhost%3A" + URLEncoder.encode(item.getHandle(), "UTF-8") + "&rfr_dat=&rfr_id" +
|
||||||
|
"=localhost&url_tim=" + ".*" + "?&svc_dat=" + encodedUIUrl + "%2Fhandle%2F" + URLEncoder
|
||||||
|
.encode(item.getHandle(), "UTF-8") + "&rft_dat=Investigation";
|
||||||
|
|
||||||
|
boolean isMatch = matchesString(String.valueOf(testProcessedUrls.get(0)), regex);
|
||||||
|
|
||||||
|
assertEquals(1, testProcessedUrls.size());
|
||||||
|
assertTrue(isMatch);
|
||||||
|
assertEquals(0, all.size());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the usage event of an item meeting all conditions is processed but fails
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReceiveEventOnItemThatShouldBeProcessedFailed() throws SQLException, UnsupportedEncodingException {
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
when(request.getRemoteAddr()).thenReturn("client-ip-fail");
|
||||||
|
when(request.getHeader(anyString())).thenReturn(null);
|
||||||
|
|
||||||
|
UsageEvent usageEvent = mock(UsageEvent.class);
|
||||||
|
when(usageEvent.getObject()).thenReturn(item);
|
||||||
|
when(usageEvent.getRequest()).thenReturn(request);
|
||||||
|
when(usageEvent.getContext()).thenReturn(new Context());
|
||||||
|
|
||||||
|
exportUsageEventListener.receiveEvent(usageEvent);
|
||||||
|
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
|
||||||
|
String regex = "https://irus.jisc.ac.uk/counter/test/\\?url_ver=Z39.88-2004&req_id=" +
|
||||||
|
URLEncoder.encode(request.getRemoteAddr(), "UTF-8") + "&req_dat=&rft" +
|
||||||
|
".artnum=oai%3Alocalhost%3A" + URLEncoder.encode(item.getHandle(), "UTF-8") + "&rfr_dat=&rfr_id" +
|
||||||
|
"=localhost&url_tim=" + ".*" + "?&svc_dat=" + encodedUIUrl + "%2Fhandle%2F" + URLEncoder
|
||||||
|
.encode(item.getHandle(), "UTF-8") + "&rft_dat=Investigation";
|
||||||
|
|
||||||
|
boolean isMatch = matchesString(all.get(0).getUrl(), regex);
|
||||||
|
|
||||||
|
assertEquals(0, testProcessedUrls.size());
|
||||||
|
|
||||||
|
assertEquals(1, all.size());
|
||||||
|
assertTrue(isMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the usage event of an item that does not meet all conditions is not processed
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReceiveEventOnItemThatShouldNotBeProcessed() throws SQLException, AuthorizeException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
|
||||||
|
UsageEvent usageEvent = mock(UsageEvent.class);
|
||||||
|
when(usageEvent.getObject()).thenReturn(itemNotToBeProcessed);
|
||||||
|
when(usageEvent.getRequest()).thenReturn(request);
|
||||||
|
when(usageEvent.getContext()).thenReturn(new Context());
|
||||||
|
|
||||||
|
itemService.clearMetadata(context, item, "relationship", "type", null, Item.ANY);
|
||||||
|
itemService.addMetadata(context, item, "relationship", "type", null, null, "OrgUnit");
|
||||||
|
itemService.update(context, item);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
// doCallRealMethod().when(IrusExportUsageEventListener).receiveEvent(usageEvent);
|
||||||
|
exportUsageEventListener.receiveEvent(usageEvent);
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(0, testProcessedUrls.size());
|
||||||
|
assertEquals(0, all.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the usage event of a bitstream meeting all conditions is processed and succeeds
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReceiveEventOnBitstreamThatShouldBeProcessed() throws SQLException, UnsupportedEncodingException {
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
when(request.getRemoteAddr()).thenReturn("client-ip");
|
||||||
|
when(request.getHeader(anyString())).thenReturn(null);
|
||||||
|
|
||||||
|
UsageEvent usageEvent = mock(UsageEvent.class);
|
||||||
|
when(usageEvent.getObject()).thenReturn(bitstream);
|
||||||
|
when(usageEvent.getRequest()).thenReturn(request);
|
||||||
|
when(usageEvent.getContext()).thenReturn(new Context());
|
||||||
|
|
||||||
|
exportUsageEventListener.receiveEvent(usageEvent);
|
||||||
|
|
||||||
|
String regex = "https://irus.jisc.ac.uk/counter/test/\\?url_ver=Z39.88-2004&req_id=" +
|
||||||
|
URLEncoder.encode(request.getRemoteAddr(), "UTF-8") + "&req_dat=&rft" +
|
||||||
|
".artnum=oai%3Alocalhost%3A" + URLEncoder.encode(item.getHandle(), "UTF-8") + "&rfr_dat=&rfr_id" +
|
||||||
|
"=localhost&url_tim=" + ".*" + "?&svc_dat=" + encodedUrl + "%2Fapi%2Fcore%2Fbitstreams" +
|
||||||
|
"%2F" + bitstream.getID() + "%2Fcontent" + "&rft_dat=Request";
|
||||||
|
|
||||||
|
boolean isMatch = matchesString(String.valueOf(testProcessedUrls.get(0)), regex);
|
||||||
|
|
||||||
|
assertEquals(1, testProcessedUrls.size());
|
||||||
|
assertTrue(isMatch);
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
assertEquals(0, all.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the usage event of a bitstream meeting all conditions is processed but fails
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReceiveEventOnBitstreamThatShouldBeProcessedFail() throws UnsupportedEncodingException,
|
||||||
|
SQLException {
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
when(request.getRemoteAddr()).thenReturn("client-ip-fail");
|
||||||
|
when(request.getHeader(anyString())).thenReturn(null);
|
||||||
|
|
||||||
|
UsageEvent usageEvent = mock(UsageEvent.class);
|
||||||
|
when(usageEvent.getObject()).thenReturn(bitstream);
|
||||||
|
when(usageEvent.getRequest()).thenReturn(request);
|
||||||
|
when(usageEvent.getContext()).thenReturn(new Context());
|
||||||
|
|
||||||
|
exportUsageEventListener.receiveEvent(usageEvent);
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
|
||||||
|
String regex = "https://irus.jisc.ac.uk/counter/test/\\?url_ver=Z39.88-2004&req_id=" +
|
||||||
|
URLEncoder.encode(request.getRemoteAddr(), "UTF-8") + "&req_dat=&rft" +
|
||||||
|
".artnum=oai%3Alocalhost%3A" + URLEncoder.encode(item.getHandle(), "UTF-8") + "&rfr_dat=&rfr_id" +
|
||||||
|
"=localhost&url_tim=" + ".*" + "?&svc_dat=" + encodedUrl + "%2Fapi%2Fcore%2Fbitstreams" +
|
||||||
|
"%2F" + bitstream.getID() + "%2Fcontent" + "&rft_dat=Request";
|
||||||
|
|
||||||
|
|
||||||
|
boolean isMatch = matchesString(all.get(0).getUrl(), regex);
|
||||||
|
|
||||||
|
assertEquals(1, all.size());
|
||||||
|
assertEquals(true, isMatch);
|
||||||
|
assertEquals(0, testProcessedUrls.size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the usage event of a bitstream that does not meet all conditions is not processed
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReceiveEventOnBitstreamThatShouldNotBeProcessed() throws SQLException, AuthorizeException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
when(request.getRemoteAddr()).thenReturn("client-ip-fail");
|
||||||
|
when(request.getHeader(anyString())).thenReturn(null);
|
||||||
|
|
||||||
|
UsageEvent usageEvent = mock(UsageEvent.class);
|
||||||
|
when(usageEvent.getObject()).thenReturn(bitstreamNotToBeProcessed);
|
||||||
|
when(usageEvent.getRequest()).thenReturn(request);
|
||||||
|
when(usageEvent.getContext()).thenReturn(new Context());
|
||||||
|
|
||||||
|
itemService.clearMetadata(context, item, "relationship", "type", null, Item.ANY);
|
||||||
|
itemService.addMetadata(context, item, "relationship", "type", null, null, "OrgUnit");
|
||||||
|
itemService.update(context, item);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
exportUsageEventListener.receiveEvent(usageEvent);
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(0, all.size());
|
||||||
|
assertEquals(0, testProcessedUrls.size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that an object that is not an Item or Bitstream is not processed
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReceiveEventOnNonRelevantObject() throws SQLException {
|
||||||
|
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
|
||||||
|
UsageEvent usageEvent = mock(UsageEvent.class);
|
||||||
|
when(usageEvent.getObject()).thenReturn(community);
|
||||||
|
when(usageEvent.getContext()).thenReturn(new Context());
|
||||||
|
|
||||||
|
exportUsageEventListener.receiveEvent(usageEvent);
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(0, all.size());
|
||||||
|
assertEquals(0, testProcessedUrls.size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to test if a string matches a regex
|
||||||
|
*
|
||||||
|
* @param string
|
||||||
|
* @param regex
|
||||||
|
* @return whether the regex matches the string
|
||||||
|
*/
|
||||||
|
private boolean matchesString(String string, String regex) {
|
||||||
|
|
||||||
|
Pattern p = Pattern.compile(regex);
|
||||||
|
|
||||||
|
if (p.matcher(string).matches()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,182 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.AbstractIntegrationTest;
|
||||||
|
import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
import org.dspace.scripts.factory.ScriptServiceFactory;
|
||||||
|
import org.dspace.scripts.service.ScriptService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.statistics.export.factory.OpenURLTrackerLoggerServiceFactory;
|
||||||
|
import org.dspace.statistics.export.service.FailedOpenURLTrackerService;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to test the RetryFailedOpenUrlTracker
|
||||||
|
*/
|
||||||
|
public class ITRetryFailedOpenUrlTracker extends AbstractIntegrationTest {
|
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(ITRetryFailedOpenUrlTracker.class);
|
||||||
|
|
||||||
|
|
||||||
|
protected FailedOpenURLTrackerService failedOpenURLTrackerService =
|
||||||
|
OpenURLTrackerLoggerServiceFactory.getInstance().getOpenUrlTrackerLoggerService();
|
||||||
|
|
||||||
|
protected ArrayList testProcessedUrls = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||||
|
.getServiceByName("testProcessedUrls",
|
||||||
|
ArrayList.class);
|
||||||
|
|
||||||
|
private ScriptService scriptService = ScriptServiceFactory.getInstance().getScriptService();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up the logged entries from the db after each test
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
try {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
for (OpenURLTracker tracker : all) {
|
||||||
|
failedOpenURLTrackerService.remove(context, tracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the list of processedUrls
|
||||||
|
testProcessedUrls.clear();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
context.complete();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the mode of the script that allows the user to add a failed url to the database
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAddNewFailedUrl() throws Exception {
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptConfiguration retryOpenUrlTrackerConfig = scriptService.getScriptConfiguration("retry-tracker");
|
||||||
|
DSpaceRunnable retryOpenUrlTracker =
|
||||||
|
scriptService.createDSpaceRunnableForScriptConfiguration(retryOpenUrlTrackerConfig);
|
||||||
|
String urlToAdd = "test-failed-url";
|
||||||
|
String[] args = {"-a", urlToAdd};
|
||||||
|
|
||||||
|
retryOpenUrlTracker.initialize(args, testDSpaceRunnableHandler, eperson);
|
||||||
|
retryOpenUrlTracker.internalRun();
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
|
||||||
|
assertEquals(0, testProcessedUrls.size());
|
||||||
|
assertEquals(1, all.size());
|
||||||
|
assertEquals(urlToAdd, all.get(0).getUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test to check that all logged failed urls are reprocessed succesfully and removed from the db
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReprocessAllUrls() throws Exception {
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptConfiguration retryOpenUrlTrackerConfig = scriptService.getScriptConfiguration("retry-tracker");
|
||||||
|
DSpaceRunnable retryOpenUrlTracker =
|
||||||
|
scriptService.createDSpaceRunnableForScriptConfiguration(retryOpenUrlTrackerConfig);
|
||||||
|
String[] args = {"-r"};
|
||||||
|
|
||||||
|
OpenURLTracker tracker1 = failedOpenURLTrackerService.create(context);
|
||||||
|
tracker1.setUrl("test-url-1");
|
||||||
|
OpenURLTracker tracker2 = failedOpenURLTrackerService.create(context);
|
||||||
|
tracker2.setUrl("test-url-2");
|
||||||
|
OpenURLTracker tracker3 = failedOpenURLTrackerService.create(context);
|
||||||
|
tracker3.setUrl("test-url-3");
|
||||||
|
|
||||||
|
|
||||||
|
retryOpenUrlTracker.initialize(args, testDSpaceRunnableHandler, eperson);
|
||||||
|
retryOpenUrlTracker.internalRun();
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
|
||||||
|
assertEquals(3, testProcessedUrls.size());
|
||||||
|
assertEquals(true, testProcessedUrls.contains("test-url-1"));
|
||||||
|
assertEquals(true, testProcessedUrls.contains("test-url-2"));
|
||||||
|
assertEquals(true, testProcessedUrls.contains("test-url-3"));
|
||||||
|
|
||||||
|
assertEquals(0, all.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test to check that the successful retries are removed, but the failed retries remain in the db
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReprocessPartOfUrls() throws Exception {
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptConfiguration retryOpenUrlTrackerConfig = scriptService.getScriptConfiguration("retry-tracker");
|
||||||
|
DSpaceRunnable retryOpenUrlTracker =
|
||||||
|
scriptService.createDSpaceRunnableForScriptConfiguration(retryOpenUrlTrackerConfig);
|
||||||
|
String[] args = {"-r"};
|
||||||
|
|
||||||
|
OpenURLTracker tracker1 = failedOpenURLTrackerService.create(context);
|
||||||
|
tracker1.setUrl("test-url-1");
|
||||||
|
OpenURLTracker tracker2 = failedOpenURLTrackerService.create(context);
|
||||||
|
tracker2.setUrl("test-url-2-fail");
|
||||||
|
OpenURLTracker tracker3 = failedOpenURLTrackerService.create(context);
|
||||||
|
tracker3.setUrl("test-url-3-fail");
|
||||||
|
OpenURLTracker tracker4 = failedOpenURLTrackerService.create(context);
|
||||||
|
tracker4.setUrl("test-url-4-fail");
|
||||||
|
OpenURLTracker tracker5 = failedOpenURLTrackerService.create(context);
|
||||||
|
tracker5.setUrl("test-url-5");
|
||||||
|
|
||||||
|
|
||||||
|
retryOpenUrlTracker.initialize(args, testDSpaceRunnableHandler, eperson);
|
||||||
|
retryOpenUrlTracker.internalRun();
|
||||||
|
|
||||||
|
List<OpenURLTracker> all = failedOpenURLTrackerService.findAll(context);
|
||||||
|
List<String> storedTrackerUrls = new ArrayList<>();
|
||||||
|
for (OpenURLTracker tracker : all) {
|
||||||
|
storedTrackerUrls.add(tracker.getUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(2, testProcessedUrls.size());
|
||||||
|
assertEquals(true, testProcessedUrls.contains("test-url-1"));
|
||||||
|
assertEquals(true, testProcessedUrls.contains("test-url-5"));
|
||||||
|
|
||||||
|
assertEquals(3, all.size());
|
||||||
|
assertEquals(true, storedTrackerUrls.contains("test-url-2-fail"));
|
||||||
|
assertEquals(true, storedTrackerUrls.contains("test-url-3-fail"));
|
||||||
|
assertEquals(true, storedTrackerUrls.contains("test-url-4-fail"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.processor;
|
||||||
|
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.CharEncoding;
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.builder.BitstreamBuilder;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.ItemBuilder;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for the BitstreamEventProcessor
|
||||||
|
*/
|
||||||
|
public class BitstreamEventProcessorTest extends AbstractIntegrationTestWithDatabase {
|
||||||
|
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
|
||||||
|
private String encodedUrl;
|
||||||
|
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.enabled", true);
|
||||||
|
|
||||||
|
String dspaceUrl = configurationService.getProperty("dspace.server.url");
|
||||||
|
try {
|
||||||
|
encodedUrl = URLEncoder.encode(dspaceUrl, CharEncoding.UTF_8);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new AssertionError("Error occurred in setup()", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the method that adds data based on the object types
|
||||||
|
*/
|
||||||
|
public void testAddObectSpecificData() throws Exception {
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).build();
|
||||||
|
|
||||||
|
File f = new File(testProps.get("test.bitstream").toString());
|
||||||
|
Bitstream bitstream = BitstreamBuilder.createBitstream(context, item, new FileInputStream(f)).build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
BitstreamEventProcessor bitstreamEventProcessor = new BitstreamEventProcessor(context, request, bitstream);
|
||||||
|
|
||||||
|
String result = bitstreamEventProcessor.addObjectSpecificData("existing-string", bitstream);
|
||||||
|
|
||||||
|
assertThat(result,
|
||||||
|
is("existing-string&svc_dat=" + encodedUrl + "%2Fapi%2Fcore%2Fbitstreams%2F" + bitstream.getID()
|
||||||
|
+ "%2Fcontent&rft_dat=Request"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,281 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.processor;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.startsWith;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.CharEncoding;
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.EntityTypeBuilder;
|
||||||
|
import org.dspace.builder.ItemBuilder;
|
||||||
|
import org.dspace.builder.WorkspaceItemBuilder;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.EntityType;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.WorkspaceItem;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for the ExportEventProcessor class
|
||||||
|
*/
|
||||||
|
public class ExportEventProcessorTest extends AbstractIntegrationTestWithDatabase {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
private EntityType publication;
|
||||||
|
private EntityType otherEntity;
|
||||||
|
private final String excluded_type = "Excluded type";
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.urlversion", "Z39.88-2004");
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.enabled", true);
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.type-field", "dc.type");
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.type-value", "Excluded type");
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
publication = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication").build();
|
||||||
|
otherEntity = EntityTypeBuilder.createEntityTypeBuilder(context, "Other").build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the getBaseParameters method
|
||||||
|
*/
|
||||||
|
public void testGetBaseParameters() throws UnsupportedEncodingException {
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).build();
|
||||||
|
String encodedHandle = URLEncoder.encode(item.getHandle(), CharEncoding.UTF_8);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
when(request.getRemoteAddr()).thenReturn("test-client-ip");
|
||||||
|
when(request.getHeader("USER-AGENT")).thenReturn("test-user-agent");
|
||||||
|
when(request.getHeader("referer")).thenReturn("test-referer");
|
||||||
|
|
||||||
|
String result = exportEventProcessor.getBaseParameters(item);
|
||||||
|
String expected = "url_ver=Z39.88-2004&req_id=test-client-ip&req_dat=test-user-agent&rft.artnum=" +
|
||||||
|
"oai%3Alocalhost%3A" + encodedHandle + "&rfr_dat=test-referer&rfr_id=localhost&url_tim=";
|
||||||
|
|
||||||
|
assertThat(result, startsWith(expected));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the ShouldProcessItem method where the item is null
|
||||||
|
*/
|
||||||
|
public void testShouldProcessItemWhenNull() throws SQLException {
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, null);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessItem(null);
|
||||||
|
assertThat(result, is(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the ShouldProcessItem method where the item is not archived
|
||||||
|
*/
|
||||||
|
public void testShouldProcessItemWhenNotArchived() throws SQLException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection).build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, workspaceItem.getItem());
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessItem(workspaceItem.getItem());
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the ShouldProcessItem method where the item can be edit by the current user
|
||||||
|
*/
|
||||||
|
public void testShouldProcessItemWhenCanEdit() throws SQLException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).withRelationshipType(otherEntity.getLabel()).build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
context.setCurrentUser(admin);
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessItem(item);
|
||||||
|
assertFalse(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the ShouldProcessItem method where the item type should be excluded
|
||||||
|
*/
|
||||||
|
public void testShouldProcessItemWhenShouldNotProcessType() throws Exception {
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection)
|
||||||
|
.withType("Excluded type")
|
||||||
|
.withRelationshipType(publication.getLabel())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessItem(item);
|
||||||
|
assertFalse(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the ShouldProcessItem method where the item entity type should not be processed
|
||||||
|
*/
|
||||||
|
public void testShouldProcessItemWhenShouldNotProcessEntity() throws SQLException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).withRelationshipType(otherEntity.getLabel()).build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessItem(item);
|
||||||
|
assertFalse(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the ShouldProcessItem method where all conditions are met
|
||||||
|
*/
|
||||||
|
public void testShouldProcessItem() throws SQLException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).withRelationshipType(publication.getLabel()).build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessItem(item);
|
||||||
|
assertTrue(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the ShouldProcessEntityType method where all conditions are met
|
||||||
|
*/
|
||||||
|
public void testShouldProcessEntityType() throws SQLException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).withRelationshipType(publication.getLabel()).build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessEntityType(item);
|
||||||
|
|
||||||
|
assertTrue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the ShouldProcessEntityType method where the item entity type is not present in the configured list
|
||||||
|
*/
|
||||||
|
public void testShouldProcessEntityTypeWhenNotInList() throws SQLException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).withRelationshipType(otherEntity.getLabel()).build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessEntityType(item);
|
||||||
|
|
||||||
|
assertFalse(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the shouldProcessItemType method where the item type is present in the list of excluded types
|
||||||
|
*/
|
||||||
|
public void testShouldProcessItemTypeInExcludeTrackerTypeList() {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).withType(excluded_type).build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessItemType(item);
|
||||||
|
assertFalse(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the shouldProcessItemType method where the item type is not present in the list of excluded types
|
||||||
|
*/
|
||||||
|
public void testShouldProcessItemTypeNotInExcludeTrackerTypeList() {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).withType("Not excluded type").build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
ExportEventProcessor exportEventProcessor = new ItemEventProcessor(context, request, item);
|
||||||
|
|
||||||
|
boolean result = exportEventProcessor.shouldProcessItemType(item);
|
||||||
|
assertTrue(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.processor;
|
||||||
|
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.CharEncoding;
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.ItemBuilder;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for the ItemEventProcessor
|
||||||
|
*/
|
||||||
|
public class ItemEventProcessorTest extends AbstractIntegrationTestWithDatabase {
|
||||||
|
|
||||||
|
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
private String encodedUrl;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
configurationService.setProperty("irus.statistics.tracker.enabled", true);
|
||||||
|
|
||||||
|
String dspaceUrl = configurationService.getProperty("dspace.ui.url");
|
||||||
|
try {
|
||||||
|
encodedUrl = URLEncoder.encode(dspaceUrl, CharEncoding.UTF_8);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new AssertionError("Error occurred in setup()", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the method that adds data based on the object types
|
||||||
|
*/
|
||||||
|
public void testAddObectSpecificData() throws UnsupportedEncodingException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context).build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String encodedHandle = URLEncoder.encode(item.getHandle(), CharEncoding.UTF_8);
|
||||||
|
|
||||||
|
ItemEventProcessor itemEventProcessor = new ItemEventProcessor(context, null, item);
|
||||||
|
String result = itemEventProcessor.addObjectSpecificData("existing-string", item);
|
||||||
|
|
||||||
|
assertThat(result,
|
||||||
|
is("existing-string&svc_dat=" + encodedUrl + "%2Fhandle%2F" + encodedHandle +
|
||||||
|
"&rft_dat=Investigation"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock OpenUrlService that will ensure that IRUS tracker does need to be contacted in order to test the functionality
|
||||||
|
*/
|
||||||
|
public class MockOpenUrlServiceImpl extends OpenUrlServiceImpl {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ArrayList testProcessedUrls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a response code to simulate contact to the external url
|
||||||
|
* When the url contains "fail", a fail code 500 will be returned
|
||||||
|
* Otherwise the success code 200 will be returned
|
||||||
|
* @param urlStr
|
||||||
|
* @return 200 or 500 depending on whether the "fail" keyword is present in the url
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected int getResponseCodeFromUrl(final String urlStr) throws IOException {
|
||||||
|
if (StringUtils.contains(urlStr, "fail")) {
|
||||||
|
return HttpURLConnection.HTTP_INTERNAL_ERROR;
|
||||||
|
} else {
|
||||||
|
testProcessedUrls.add(urlStr);
|
||||||
|
return HttpURLConnection.HTTP_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.service;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doCallRealMethod;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.statistics.export.OpenURLTracker;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Spy;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for the OpenUrlServiceImpl
|
||||||
|
*/
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class OpenUrlServiceImplTest {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
@Spy
|
||||||
|
private OpenUrlServiceImpl openUrlService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private FailedOpenURLTrackerService failedOpenURLTrackerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the processUrl method
|
||||||
|
* @throws IOException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testProcessUrl() throws IOException, SQLException {
|
||||||
|
Context context = mock(Context.class);
|
||||||
|
|
||||||
|
doReturn(HttpURLConnection.HTTP_OK).when(openUrlService)
|
||||||
|
.getResponseCodeFromUrl(anyString());
|
||||||
|
openUrlService.processUrl(context, "test-url");
|
||||||
|
|
||||||
|
verify(openUrlService, times(0)).logfailed(context, "test-url");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the processUrl method when the url connection fails
|
||||||
|
* @throws IOException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testProcessUrlOnFail() throws IOException, SQLException {
|
||||||
|
Context context = mock(Context.class);
|
||||||
|
|
||||||
|
doReturn(HttpURLConnection.HTTP_INTERNAL_ERROR).when(openUrlService)
|
||||||
|
.getResponseCodeFromUrl(anyString());
|
||||||
|
doNothing().when(openUrlService).logfailed(any(Context.class), anyString());
|
||||||
|
|
||||||
|
openUrlService.processUrl(context, "test-url");
|
||||||
|
|
||||||
|
verify(openUrlService, times(1)).logfailed(context, "test-url");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the ReprocessFailedQueue method
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReprocessFailedQueue() throws SQLException {
|
||||||
|
Context context = mock(Context.class);
|
||||||
|
|
||||||
|
List<OpenURLTracker> trackers = new ArrayList<>();
|
||||||
|
OpenURLTracker tracker1 = mock(OpenURLTracker.class);
|
||||||
|
OpenURLTracker tracker2 = mock(OpenURLTracker.class);
|
||||||
|
OpenURLTracker tracker3 = mock(OpenURLTracker.class);
|
||||||
|
|
||||||
|
trackers.add(tracker1);
|
||||||
|
trackers.add(tracker2);
|
||||||
|
trackers.add(tracker3);
|
||||||
|
|
||||||
|
when(failedOpenURLTrackerService.findAll(any(Context.class))).thenReturn(trackers);
|
||||||
|
doNothing().when(openUrlService).tryReprocessFailed(any(Context.class), any(OpenURLTracker.class));
|
||||||
|
|
||||||
|
openUrlService.reprocessFailedQueue(context);
|
||||||
|
|
||||||
|
verify(openUrlService, times(3)).tryReprocessFailed(any(Context.class), any(OpenURLTracker.class));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the method that logs the failed urls in the db
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLogfailed() throws SQLException {
|
||||||
|
Context context = mock(Context.class);
|
||||||
|
OpenURLTracker tracker1 = mock(OpenURLTracker.class);
|
||||||
|
|
||||||
|
doCallRealMethod().when(tracker1).setUrl(anyString());
|
||||||
|
when(tracker1.getUrl()).thenCallRealMethod();
|
||||||
|
|
||||||
|
when(failedOpenURLTrackerService.create(any(Context.class))).thenReturn(tracker1);
|
||||||
|
|
||||||
|
String failedUrl = "failed-url";
|
||||||
|
openUrlService.logfailed(context, failedUrl);
|
||||||
|
|
||||||
|
Assert.assertThat(tracker1.getUrl(), is(failedUrl));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -29,121 +29,6 @@
|
|||||||
<start-class>org.dspace.app.rest.Application</start-class>
|
<start-class>org.dspace.app.rest.Application</start-class>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<!-- If Unit Testing is enabled, then setup the Unit Test Environment.
|
|
||||||
See also the 'skiptests' profile in Parent POM. -->
|
|
||||||
<profile>
|
|
||||||
<id>test-environment</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
<property>
|
|
||||||
<name>skipTests</name>
|
|
||||||
<value>false</value>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<!-- Unit/Integration Testing setup: This plugin unzips the
|
|
||||||
'testEnvironment.zip' file (created by dspace-parent POM), into
|
|
||||||
the 'target/testing/' folder, to essentially create a test
|
|
||||||
install of DSpace, against which Tests can be run. -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/testing</outputDirectory>
|
|
||||||
<artifactItems>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.dspace</groupId>
|
|
||||||
<artifactId>dspace-parent</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<type>zip</type>
|
|
||||||
<classifier>testEnvironment</classifier>
|
|
||||||
</artifactItem>
|
|
||||||
</artifactItems>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>setupTestEnvironment</id>
|
|
||||||
<phase>generate-test-resources</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>unpack</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>setupIntegrationTestEnvironment</id>
|
|
||||||
<phase>pre-integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>unpack</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
|
||||||
(see: http://gmaven.codehaus.org/Executing+Groovy+Code )
|
|
||||||
We are generating a OS-agnostic version (agnostic.build.dir) of
|
|
||||||
the ${project.build.directory} property (full path of target dir).
|
|
||||||
This is needed by the FileWeaver & Surefire plugins (see below)
|
|
||||||
to initialize the Unit Test environment's dspace.cfg file.
|
|
||||||
Otherwise, the Unit Test Framework will not work on Windows OS.
|
|
||||||
This Groovy code was mostly borrowed from:
|
|
||||||
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
|
||||||
-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.gmaven</groupId>
|
|
||||||
<artifactId>groovy-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>setproperty</id>
|
|
||||||
<phase>generate-test-resources
|
|
||||||
</phase> <!-- XXX I think this should be 'initialize' - MHW -->
|
|
||||||
<goals>
|
|
||||||
<goal>execute</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<source>
|
|
||||||
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
|
||||||
println("Initializing Maven property 'agnostic.build.dir' to: " + project.properties['agnostic.build.dir']);
|
|
||||||
</source>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<!-- Run Unit Testing! This plugin just kicks off the tests (when enabled). -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<!-- Specify the dspace.dir to use for test environment -->
|
|
||||||
<!-- This system property is loaded by AbstractDSpaceTest to initialize the test environment -->
|
|
||||||
<dspace.dir>${agnostic.build.dir}/testing/dspace/</dspace.dir>
|
|
||||||
<!-- Turn off any DSpace logging -->
|
|
||||||
<dspace.log.init.disable>true</dspace.log.init.disable>
|
|
||||||
<solr.install.dir>${agnostic.build.dir}/testing/dspace/solr/</solr.install.dir>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<!-- Specify the dspace.dir to use for test environment -->
|
|
||||||
<dspace.dir>${agnostic.build.dir}/testing/dspace/</dspace.dir>
|
|
||||||
<!-- Turn off any DSpace logging -->
|
|
||||||
<dspace.log.init.disable>true</dspace.log.init.disable>
|
|
||||||
<solr.install.dir>${agnostic.build.dir}/testing/dspace/solr/</solr.install.dir>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -187,9 +72,160 @@
|
|||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
||||||
|
(see: https://groovy.github.io/gmaven/groovy-maven-plugin/execute.html )
|
||||||
|
We are generating a OS-agnostic version (agnostic.build.dir) of
|
||||||
|
the ${project.build.directory} property (full path of target dir).
|
||||||
|
This is needed by the Surefire & Failsafe plugins (see below)
|
||||||
|
to initialize the Unit Test environment's dspace.cfg file.
|
||||||
|
Otherwise, the Unit Test Framework will not work on Windows OS.
|
||||||
|
This Groovy code was mostly borrowed from:
|
||||||
|
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
||||||
|
-->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.gmaven</groupId>
|
||||||
|
<artifactId>groovy-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setproperty</id>
|
||||||
|
<phase>initialize</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>execute</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<source>
|
||||||
|
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
||||||
|
log.info("Initializing Maven property 'agnostic.build.dir' to: {}", project.properties['agnostic.build.dir']);
|
||||||
|
</source>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<!-- Setup the Unit Test Environment (when -DskipUnitTests=false) -->
|
||||||
|
<profile>
|
||||||
|
<id>unit-test-environment</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
<property>
|
||||||
|
<name>skipUnitTests</name>
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Unit Testing setup: This plugin unzips the
|
||||||
|
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||||
|
the 'target/testing/' folder, to essentially create a test
|
||||||
|
install of DSpace, against which Tests can be run. -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/testing</outputDirectory>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.dspace</groupId>
|
||||||
|
<artifactId>dspace-parent</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<classifier>testEnvironment</classifier>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setupUnitTestEnvironment</id>
|
||||||
|
<phase>generate-test-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>unpack</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Run Unit Testing! This plugin just kicks off the tests -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<!-- Specify the dspace.dir to use for test environment -->
|
||||||
|
<!-- This system property is loaded by AbstractDSpaceTest to initialize the test environment -->
|
||||||
|
<dspace.dir>${agnostic.build.dir}/testing/dspace/</dspace.dir>
|
||||||
|
<!-- Turn off any DSpace logging -->
|
||||||
|
<dspace.log.init.disable>true</dspace.log.init.disable>
|
||||||
|
<solr.install.dir>${agnostic.build.dir}/testing/dspace/solr/</solr.install.dir>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<!-- Setup the Integration Test Environment (when -DskipIntegrationTests=false) -->
|
||||||
|
<profile>
|
||||||
|
<id>integration-test-environment</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
<property>
|
||||||
|
<name>skipIntegrationTests</name>
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Integration Testing setup: This plugin unzips the
|
||||||
|
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||||
|
the 'target/testing/' folder, to essentially create a test
|
||||||
|
install of DSpace, against which Tests can be run. -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/testing</outputDirectory>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.dspace</groupId>
|
||||||
|
<artifactId>dspace-parent</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<classifier>testEnvironment</classifier>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setupIntegrationTestEnvironment</id>
|
||||||
|
<phase>pre-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>unpack</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<!-- Specify the dspace.dir to use for test environment -->
|
||||||
|
<dspace.dir>${agnostic.build.dir}/testing/dspace/</dspace.dir>
|
||||||
|
<!-- Turn off any DSpace logging -->
|
||||||
|
<dspace.log.init.disable>true</dspace.log.init.disable>
|
||||||
|
<solr.install.dir>${agnostic.build.dir}/testing/dspace/solr/</solr.install.dir>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.app.rest;
|
package org.dspace.app.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
@@ -62,8 +63,14 @@ public class ShibbolethRestController implements InitializingBean {
|
|||||||
// Validate that the redirectURL matches either the server or UI hostname. It *cannot* be an arbitrary URL.
|
// Validate that the redirectURL matches either the server or UI hostname. It *cannot* be an arbitrary URL.
|
||||||
String redirectHostName = Utils.getHostName(redirectUrl);
|
String redirectHostName = Utils.getHostName(redirectUrl);
|
||||||
String serverHostName = Utils.getHostName(configurationService.getProperty("dspace.server.url"));
|
String serverHostName = Utils.getHostName(configurationService.getProperty("dspace.server.url"));
|
||||||
String clientHostName = Utils.getHostName(configurationService.getProperty("dspace.ui.url"));
|
ArrayList<String> allowedHostNames = new ArrayList<String>();
|
||||||
if (StringUtils.equalsAnyIgnoreCase(redirectHostName, serverHostName, clientHostName)) {
|
allowedHostNames.add(serverHostName);
|
||||||
|
String[] allowedUrls = configurationService.getArrayProperty("rest.cors.allowed-origins");
|
||||||
|
for (String url : allowedUrls) {
|
||||||
|
allowedHostNames.add(Utils.getHostName(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.equalsAnyIgnoreCase(redirectHostName, allowedHostNames.toArray(new String[0]))) {
|
||||||
log.debug("Shibboleth redirecting to " + redirectUrl);
|
log.debug("Shibboleth redirecting to " + redirectUrl);
|
||||||
response.sendRedirect(redirectUrl);
|
response.sendRedirect(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.DSpaceObjectService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is a wrapper around the AuthorizationService which takes Rest objects instead of dspace objects
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AuthorizeServiceRestUtil {
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
@Autowired
|
||||||
|
private Utils utils;
|
||||||
|
@Autowired
|
||||||
|
private ContentServiceFactory contentServiceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the specified eperson can perform the given action on the rest given object.
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param object The Rest object to test the action against
|
||||||
|
* @param dSpaceRestPermission The permission to check
|
||||||
|
* @return A boolean indicating if the action is allowed by the logged in ePerson on the given object
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public boolean authorizeActionBoolean(Context context, BaseObjectRest object,
|
||||||
|
DSpaceRestPermission dSpaceRestPermission)
|
||||||
|
throws SQLException {
|
||||||
|
|
||||||
|
DSpaceObject dSpaceObject = (DSpaceObject)utils.getDSpaceAPIObjectFromRest(context, object);
|
||||||
|
if (dSpaceObject == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSpaceObjectService<DSpaceObject> dSpaceObjectService =
|
||||||
|
contentServiceFactory.getDSpaceObjectService(dSpaceObject.getType());
|
||||||
|
|
||||||
|
EPerson ePerson = context.getCurrentUser();
|
||||||
|
|
||||||
|
// If the item is still inprogress we can process here only the READ permission.
|
||||||
|
// Other actions need to be evaluated against the wrapper object (workspace or workflow item)
|
||||||
|
if (dSpaceObject instanceof Item) {
|
||||||
|
if (!DSpaceRestPermission.READ.equals(dSpaceRestPermission)
|
||||||
|
&& !((Item) dSpaceObject).isArchived() && !((Item) dSpaceObject).isWithdrawn()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizeService.authorizeActionBoolean(context, ePerson, dSpaceObject,
|
||||||
|
dSpaceRestPermission.getDspaceApiActionId(), true);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizeServiceRestUtil;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Bundle;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.service.BundleService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The create bitstream feature. It can be used to verify if bitstreams can be created in a specific bundle.
|
||||||
|
*
|
||||||
|
* Authorization is granted if the current user has ADD & WRITE permissions on the given bundle AND the item
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = CreateBitstreamFeature.NAME,
|
||||||
|
description = "It can be used to verify if bitstreams can be created in a specific bundle")
|
||||||
|
public class CreateBitstreamFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
Logger log = Logger.getLogger(CreateBitstreamFeature.class);
|
||||||
|
|
||||||
|
public final static String NAME = "canCreateBitstream";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceRestUtil authorizeServiceRestUtil;
|
||||||
|
@Autowired
|
||||||
|
private BundleService bundleService;
|
||||||
|
@Autowired
|
||||||
|
private Utils utils;
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof BundleRest) {
|
||||||
|
if (!authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.WRITE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.ADD)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSpaceObject owningObject = bundleService.getParentObject(context,
|
||||||
|
(Bundle)utils.getDSpaceAPIObjectFromRest(context, object));
|
||||||
|
|
||||||
|
// Safety check. In case this is ever not true, this method should be revised.
|
||||||
|
if (!(owningObject instanceof Item)) {
|
||||||
|
log.error("The parent object of bundle " + object.getType() + " is not an item");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authorizeService.authorizeActionBoolean(context, context.getCurrentUser(), owningObject,
|
||||||
|
Constants.WRITE, true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizeService.authorizeActionBoolean(context, context.getCurrentUser(), owningObject,
|
||||||
|
Constants.ADD, true);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
BundleRest.CATEGORY + "." + BundleRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizeServiceRestUtil;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The create bundle feature. It can be used to verify if bundles can be created in a specific item.
|
||||||
|
*
|
||||||
|
* Authorization is granted if the current user has ADD & WRITE permissions on the given item
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = CreateBundleFeature.NAME,
|
||||||
|
description = "It can be used to verify if bundles can be created in a specific item")
|
||||||
|
public class CreateBundleFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
public final static String NAME = "canCreateBundle";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceRestUtil authorizeServiceRestUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof ItemRest) {
|
||||||
|
if (!authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.WRITE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.ADD);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
ItemRest.CATEGORY + "." + ItemRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizeServiceRestUtil;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
|
import org.dspace.app.rest.model.CollectionRest;
|
||||||
|
import org.dspace.app.rest.model.CommunityRest;
|
||||||
|
import org.dspace.app.rest.model.EPersonRest;
|
||||||
|
import org.dspace.app.rest.model.GroupRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.model.WorkspaceItemRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.WorkspaceItem;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The delete feature. It can be used to verify if specific content can be deleted/expunged.
|
||||||
|
*
|
||||||
|
* Authorization is granted
|
||||||
|
* - for a bitstream if the current used has REMOVE permissions on both the Item and the Bundle
|
||||||
|
* - for a bundle if the current user has REMOVE permissions on the Item
|
||||||
|
* - for an item if the current user has REMOVE permissions on the collection AND and DELETE permissions on the item
|
||||||
|
* - for a collection if the current user has REMOVE permissions on the community
|
||||||
|
* - for a community with a parent community if the current user has REMOVE permissions on the parent community
|
||||||
|
* - for a community without a parent community if the current user has DELETE permissions on the current community
|
||||||
|
* - for other objects if the current user has REMOVE permissions on the parent object if there is one. Otherwise if the
|
||||||
|
* current user has DELETE permissions on the current object
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = DeleteFeature.NAME,
|
||||||
|
description = "It can be used to verify if specific content can be deleted/expunged")
|
||||||
|
public class DeleteFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
public final static String NAME = "canDelete";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceRestUtil authorizeServiceRestUtil;
|
||||||
|
@Autowired
|
||||||
|
private Utils utils;
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
@Autowired
|
||||||
|
private ContentServiceFactory contentServiceFactory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof BaseObjectRest) {
|
||||||
|
if (object.getType().equals(WorkspaceItemRest.NAME)) {
|
||||||
|
object = ((WorkspaceItemRest)object).getItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
DSpaceObject dSpaceObject = (DSpaceObject) utils.getDSpaceAPIObjectFromRest(context, object);
|
||||||
|
DSpaceObject parentObject = getParentObject(context, dSpaceObject);
|
||||||
|
|
||||||
|
switch (object.getType()) {
|
||||||
|
case BitstreamRest.NAME:
|
||||||
|
return (
|
||||||
|
authorizeService.authorizeActionBoolean(context, context.getCurrentUser(), parentObject,
|
||||||
|
Constants.REMOVE, true)
|
||||||
|
&& authorizeService.authorizeActionBoolean(context, context.getCurrentUser(), dSpaceObject,
|
||||||
|
Constants.REMOVE, true)
|
||||||
|
);
|
||||||
|
case ItemRest.NAME:
|
||||||
|
return (
|
||||||
|
authorizeService.authorizeActionBoolean(context, context.getCurrentUser(), parentObject,
|
||||||
|
Constants.REMOVE, true)
|
||||||
|
&& authorizeServiceRestUtil.authorizeActionBoolean(context, object,
|
||||||
|
DSpaceRestPermission.DELETE)
|
||||||
|
);
|
||||||
|
case CollectionRest.NAME:
|
||||||
|
case CommunityRest.NAME:
|
||||||
|
case BundleRest.NAME:
|
||||||
|
case WorkspaceItemRest.NAME:
|
||||||
|
case EPersonRest.NAME:
|
||||||
|
case GroupRest.NAME:
|
||||||
|
default:
|
||||||
|
if (parentObject != null) {
|
||||||
|
return authorizeService.authorizeActionBoolean(context, context.getCurrentUser(), parentObject,
|
||||||
|
Constants.REMOVE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizeServiceRestUtil.authorizeActionBoolean(context, object,
|
||||||
|
DSpaceRestPermission.DELETE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DSpaceObject getParentObject(Context context, DSpaceObject object) throws SQLException {
|
||||||
|
DSpaceObject parentObject
|
||||||
|
= contentServiceFactory.getDSpaceObjectService(object.getType()).getParentObject(context, object);
|
||||||
|
if (object.getType() == Constants.ITEM && parentObject == null) {
|
||||||
|
Item item = (Item) object;
|
||||||
|
parentObject = item.getOwningCollection();
|
||||||
|
WorkspaceItem byItem = ContentServiceFactory.getInstance()
|
||||||
|
.getWorkspaceItemService()
|
||||||
|
.findByItem(context, item);
|
||||||
|
if (byItem != null) {
|
||||||
|
parentObject = byItem.getCollection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parentObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
CommunityRest.CATEGORY + "." + CommunityRest.NAME,
|
||||||
|
CollectionRest.CATEGORY + "." + CollectionRest.NAME,
|
||||||
|
ItemRest.CATEGORY + "." + ItemRest.NAME,
|
||||||
|
BundleRest.CATEGORY + "." + BundleRest.NAME,
|
||||||
|
BitstreamRest.CATEGORY + "." + BitstreamRest.NAME,
|
||||||
|
WorkspaceItemRest.CATEGORY + "." + WorkspaceItemRest.NAME,
|
||||||
|
EPersonRest.CATEGORY + "." + EPersonRest.NAME,
|
||||||
|
GroupRest.CATEGORY + "." + GroupRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizeServiceRestUtil;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
|
import org.dspace.app.rest.model.CollectionRest;
|
||||||
|
import org.dspace.app.rest.model.CommunityRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.model.SiteRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The edit metadata feature. It can be used to verify if the metadata of the specified objects can be edited.
|
||||||
|
*
|
||||||
|
* Authorization is granted if the current user has WRITE permissions on the given DSO
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = EditMetadataFeature.NAME,
|
||||||
|
description = "It can be used to verify if the metadata of the specified objects can be edited")
|
||||||
|
public class EditMetadataFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
public final static String NAME = "canEditMetadata";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceRestUtil authorizeServiceRestUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof CommunityRest
|
||||||
|
|| object instanceof CollectionRest
|
||||||
|
|| object instanceof ItemRest
|
||||||
|
|| object instanceof BundleRest
|
||||||
|
|| object instanceof BitstreamRest
|
||||||
|
|| object instanceof SiteRest
|
||||||
|
) {
|
||||||
|
return authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.WRITE);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
CommunityRest.CATEGORY + "." + CommunityRest.NAME,
|
||||||
|
CollectionRest.CATEGORY + "." + CollectionRest.NAME,
|
||||||
|
ItemRest.CATEGORY + "." + ItemRest.NAME,
|
||||||
|
BundleRest.CATEGORY + "." + BundleRest.NAME,
|
||||||
|
BitstreamRest.CATEGORY + "." + BitstreamRest.NAME,
|
||||||
|
SiteRest.CATEGORY + "." + SiteRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizeServiceRestUtil;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The make discoverable feature. It can be used to verify if an item can be made discoverable.
|
||||||
|
*
|
||||||
|
* Authorization is granted if the current user has WRITE permissions on the given item
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = MakeDiscoverableFeature.NAME,
|
||||||
|
description = "It can be used to verify if an item can be made discoverable")
|
||||||
|
public class MakeDiscoverableFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
public final static String NAME = "canMakeDiscoverable";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceRestUtil authorizeServiceRestUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof ItemRest) {
|
||||||
|
return authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.WRITE);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
ItemRest.CATEGORY + "." + ItemRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizeServiceRestUtil;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The make private feature. It can be used to verify if an item can be made private.
|
||||||
|
*
|
||||||
|
* Authorization is granted if the current user has WRITE permissions on the given item
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = MakePrivateFeature.NAME,
|
||||||
|
description = "It can be used to verify if an item can be made private")
|
||||||
|
public class MakePrivateFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
public final static String NAME = "canMakePrivate";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceRestUtil authorizeServiceRestUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof ItemRest) {
|
||||||
|
return authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.WRITE);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
ItemRest.CATEGORY + "." + ItemRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizeServiceRestUtil;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The move feature. It can be used to verify if item can be moved to a different collection.
|
||||||
|
*
|
||||||
|
* Authorization is granted if the current user has WRITE permissions on the given item and REMOVE permissions on the
|
||||||
|
* item’s owning collection
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = MoveFeature.NAME,
|
||||||
|
description = "It can be used to verify if item can be moved to a different collection")
|
||||||
|
public class MoveFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
Logger log = Logger.getLogger(MoveFeature.class);
|
||||||
|
|
||||||
|
public final static String NAME = "canMove";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceRestUtil authorizeServiceRestUtil;
|
||||||
|
@Autowired
|
||||||
|
private Utils utils;
|
||||||
|
@Autowired
|
||||||
|
private ItemService itemService;
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof ItemRest) {
|
||||||
|
if (!authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.WRITE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSpaceObject owningObject = itemService.getParentObject(context,
|
||||||
|
(Item)utils.getDSpaceAPIObjectFromRest(context, object));
|
||||||
|
|
||||||
|
if (!(owningObject instanceof Collection)) {
|
||||||
|
log.error("The partent object of item " + object.getType() + " is not a collection");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizeService.authorizeActionBoolean(context, context.getCurrentUser(), owningObject,
|
||||||
|
Constants.REMOVE, true);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
ItemRest.CATEGORY + "." + ItemRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
|
import org.dspace.app.rest.model.CollectionRest;
|
||||||
|
import org.dspace.app.rest.model.CommunityRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.model.SiteRest;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
import org.dspace.app.util.AuthorizeUtil;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.Bundle;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The policy feature. It can be used by administrators (or community/collection delegate) to manage resource policies
|
||||||
|
*
|
||||||
|
* Authorization is granted
|
||||||
|
* - for the site if the current user is administrator
|
||||||
|
* - for other objects if the current user has ADMIN permissions on the object
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = PolicyFeature.NAME,
|
||||||
|
description = "It can be used to verify if the resourcepolicies of the specified objects can be managed")
|
||||||
|
public class PolicyFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
public static final String NAME = "canManagePolicies";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
AuthorizeService authService;
|
||||||
|
@Autowired
|
||||||
|
private Utils utils;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object != null) {
|
||||||
|
try {
|
||||||
|
if (object instanceof SiteRest) {
|
||||||
|
return authService.isAdmin(context);
|
||||||
|
}
|
||||||
|
if (object instanceof CommunityRest) {
|
||||||
|
AuthorizeUtil.authorizeManageCommunityPolicy(context,
|
||||||
|
(Community)utils.getDSpaceAPIObjectFromRest(context, object));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (object instanceof CollectionRest) {
|
||||||
|
AuthorizeUtil.authorizeManageCollectionPolicy(context,
|
||||||
|
(Collection) utils.getDSpaceAPIObjectFromRest(context, object));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (object instanceof ItemRest) {
|
||||||
|
AuthorizeUtil.authorizeManageItemPolicy(context,
|
||||||
|
(Item)utils.getDSpaceAPIObjectFromRest(context, object));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (object instanceof BundleRest) {
|
||||||
|
AuthorizeUtil.authorizeManageBundlePolicy(context,
|
||||||
|
(Bundle)utils.getDSpaceAPIObjectFromRest(context, object));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (object instanceof BitstreamRest) {
|
||||||
|
AuthorizeUtil.authorizeManageBitstreamPolicy(context,
|
||||||
|
(Bitstream)utils.getDSpaceAPIObjectFromRest(context, object));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (AuthorizeException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
SiteRest.CATEGORY + "." + SiteRest.NAME,
|
||||||
|
CommunityRest.CATEGORY + "." + CommunityRest.NAME,
|
||||||
|
CollectionRest.CATEGORY + "." + CollectionRest.NAME,
|
||||||
|
ItemRest.CATEGORY + "." + ItemRest.NAME,
|
||||||
|
BundleRest.CATEGORY + "." + BundleRest.NAME,
|
||||||
|
BitstreamRest.CATEGORY + "." + BitstreamRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizeServiceRestUtil;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
|
import org.dspace.app.rest.security.DSpaceRestPermission;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reorder bitstream feature. It can be used to verify if bitstreams can be reordered in a specific bundle.
|
||||||
|
*
|
||||||
|
* Authorization is granted if the current user has WRITE permissions on the given bundle
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = ReorderBitstreamFeature.NAME,
|
||||||
|
description = "It can be used to verify if bitstreams can be reordered in a specific bundle")
|
||||||
|
public class ReorderBitstreamFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
public final static String NAME = "canReorderBitstreams";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceRestUtil authorizeServiceRestUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof BundleRest) {
|
||||||
|
return authorizeServiceRestUtil.authorizeActionBoolean(context, object, DSpaceRestPermission.WRITE);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
BundleRest.CATEGORY + "." + BundleRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -9,11 +9,17 @@ package org.dspace.app.rest.repository;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.app.rest.Parameter;
|
||||||
|
import org.dspace.app.rest.SearchRestMethod;
|
||||||
import org.dspace.app.rest.converter.ConverterService;
|
import org.dspace.app.rest.converter.ConverterService;
|
||||||
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||||
import org.dspace.app.rest.model.BitstreamRest;
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
import org.dspace.app.rest.model.ProcessRest;
|
import org.dspace.app.rest.model.ProcessRest;
|
||||||
@@ -21,12 +27,18 @@ import org.dspace.app.rest.projection.Projection;
|
|||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.authorize.service.AuthorizeService;
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.ProcessStatus;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.eperson.service.EPersonService;
|
||||||
import org.dspace.scripts.Process;
|
import org.dspace.scripts.Process;
|
||||||
|
import org.dspace.scripts.ProcessQueryParameterContainer;
|
||||||
|
import org.dspace.scripts.Process_;
|
||||||
import org.dspace.scripts.service.ProcessService;
|
import org.dspace.scripts.service.ProcessService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -49,6 +61,9 @@ public class ProcessRestRepository extends DSpaceRestRepository<ProcessRest, Int
|
|||||||
@Autowired
|
@Autowired
|
||||||
private AuthorizeService authorizeService;
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EPersonService epersonService;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PreAuthorize("hasPermission(#id, 'PROCESS', 'READ')")
|
@PreAuthorize("hasPermission(#id, 'PROCESS', 'READ')")
|
||||||
@@ -135,6 +150,104 @@ public class ProcessRestRepository extends DSpaceRestRepository<ProcessRest, Int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search method that will take Parameters and return a list of {@link ProcessRest} objects
|
||||||
|
* based on the {@link Process} objects that were in the databank that adhere to these params
|
||||||
|
* @param ePersonUuid The UUID for the EPerson that started the Process
|
||||||
|
* @param scriptName The name of the Script for which the Process belongs to
|
||||||
|
* @param processStatusString The status of the Process
|
||||||
|
* @param pageable The pageable
|
||||||
|
* @return A page of {@link ProcessRest} objects adhering to the params
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
@SearchRestMethod(name = "byProperty")
|
||||||
|
@PreAuthorize("hasAuthority('ADMIN')")
|
||||||
|
public Page<ProcessRest> findProcessesByProperty(@Parameter(value = "userId") UUID ePersonUuid,
|
||||||
|
@Parameter(value = "scriptName") String scriptName,
|
||||||
|
@Parameter(value = "processStatus") String processStatusString,
|
||||||
|
Pageable pageable)
|
||||||
|
throws SQLException {
|
||||||
|
if (StringUtils.isBlank(scriptName) && ePersonUuid == null && StringUtils.isBlank(processStatusString)) {
|
||||||
|
throw new DSpaceBadRequestException("Either a name, user UUID or ProcessStatus should be provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
Context context = obtainContext();
|
||||||
|
EPerson ePerson = null;
|
||||||
|
if (ePersonUuid != null) {
|
||||||
|
ePerson = epersonService.find(context, ePersonUuid);
|
||||||
|
if (ePerson == null) {
|
||||||
|
throw new DSpaceBadRequestException("No EPerson with the given UUID is found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessStatus processStatus = StringUtils.isBlank(processStatusString) ? null :
|
||||||
|
ProcessStatus.valueOf(processStatusString);
|
||||||
|
ProcessQueryParameterContainer processQueryParameterContainer = createProcessQueryParameterContainer(scriptName,
|
||||||
|
ePerson, processStatus);
|
||||||
|
handleSearchSort(pageable, processQueryParameterContainer);
|
||||||
|
List<Process> processes = processService.search(context, processQueryParameterContainer, pageable.getPageSize(),
|
||||||
|
Math.toIntExact(pageable.getOffset()));
|
||||||
|
return converterService.toRestPage(processes, pageable,
|
||||||
|
processService.countSearch(context, processQueryParameterContainer),
|
||||||
|
utils.obtainProjection());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will retrieve the {@link Sort} from the given {@link Pageable} and it'll create the sortOrder and
|
||||||
|
* sortProperty Strings on the {@link ProcessQueryParameterContainer} object so that we can store how the sorting
|
||||||
|
* should be done
|
||||||
|
* @param pageable The pageable object
|
||||||
|
* @param processQueryParameterContainer The object in which the sorting will be filled in
|
||||||
|
*/
|
||||||
|
private void handleSearchSort(Pageable pageable, ProcessQueryParameterContainer processQueryParameterContainer) {
|
||||||
|
Sort sort = pageable.getSort();
|
||||||
|
if (sort != null) {
|
||||||
|
Iterator<Sort.Order> iterator = sort.iterator();
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
Sort.Order order = iterator.next();
|
||||||
|
if (StringUtils.equalsIgnoreCase(order.getProperty(), "startTime")) {
|
||||||
|
processQueryParameterContainer.setSortProperty(Process_.START_TIME);
|
||||||
|
processQueryParameterContainer.setSortOrder(order.getDirection().name());
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(order.getProperty(), "endTime")) {
|
||||||
|
processQueryParameterContainer.setSortProperty(Process_.FINISHED_TIME);
|
||||||
|
processQueryParameterContainer.setSortOrder(order.getDirection().name());
|
||||||
|
} else {
|
||||||
|
throw new DSpaceBadRequestException("The given sort option was invalid: " + order.getProperty());
|
||||||
|
}
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
throw new DSpaceBadRequestException("Only one sort method is supported, can't give multiples");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will create a new {@link ProcessQueryParameterContainer} object and return it.
|
||||||
|
* This object will contain a map which is filled in with the database column reference as key and the value that
|
||||||
|
* it should contain when searching as the value of the entry
|
||||||
|
* @param scriptName The name that the script of the process should have
|
||||||
|
* @param ePerson The eperson that the process should have
|
||||||
|
* @param processStatus The status that the process should have
|
||||||
|
* @return The newly created {@link ProcessQueryParameterContainer}
|
||||||
|
*/
|
||||||
|
private ProcessQueryParameterContainer createProcessQueryParameterContainer(String scriptName, EPerson ePerson,
|
||||||
|
ProcessStatus processStatus) {
|
||||||
|
ProcessQueryParameterContainer processQueryParameterContainer =
|
||||||
|
new ProcessQueryParameterContainer();
|
||||||
|
if (StringUtils.isNotBlank(scriptName)) {
|
||||||
|
processQueryParameterContainer.addToQueryParameterMap(Process_.NAME, scriptName);
|
||||||
|
}
|
||||||
|
if (ePerson != null) {
|
||||||
|
processQueryParameterContainer.addToQueryParameterMap(Process_.E_PERSON, ePerson);
|
||||||
|
}
|
||||||
|
if (processStatus != null) {
|
||||||
|
processQueryParameterContainer.addToQueryParameterMap(Process_.PROCESS_STATUS, processStatus);
|
||||||
|
}
|
||||||
|
return processQueryParameterContainer;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<ProcessRest> getDomainClass() {
|
public Class<ProcessRest> getDomainClass() {
|
||||||
return ProcessRest.class;
|
return ProcessRest.class;
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.rest;
|
package org.dspace.app.rest;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
@@ -18,6 +19,7 @@ import java.sql.SQLException;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.codec.CharEncoding;
|
import org.apache.commons.codec.CharEncoding;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
@@ -158,39 +160,40 @@ public class ProcessRestRepositoryIT extends AbstractControllerIntegrationTest {
|
|||||||
|
|
||||||
getClient(token).perform(get("/api/system/processes/"))
|
getClient(token).perform(get("/api/system/processes/"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._embedded.processes", containsInAnyOrder(
|
// Expect all processes to be returned, newest to oldest
|
||||||
ProcessMatcher.matchProcess(process.getName(), String.valueOf(process.getEPerson().getID()),
|
.andExpect(jsonPath("$._embedded.processes", contains(
|
||||||
process.getID(), parameters, ProcessStatus.SCHEDULED),
|
ProcessMatcher.matchProcess(newProcess9.getName(),
|
||||||
ProcessMatcher.matchProcess(newProcess.getName(),
|
String.valueOf(newProcess9.getEPerson().getID()),
|
||||||
String.valueOf(newProcess.getEPerson().getID()),
|
newProcess9.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
newProcess.getID(), parameters, ProcessStatus.SCHEDULED),
|
|
||||||
ProcessMatcher.matchProcess(newProcess1.getName(),
|
|
||||||
String.valueOf(newProcess1.getEPerson().getID()),
|
|
||||||
newProcess1.getID(), parameters, ProcessStatus.SCHEDULED),
|
|
||||||
ProcessMatcher.matchProcess(newProcess2.getName(),
|
|
||||||
String.valueOf(newProcess2.getEPerson().getID()),
|
|
||||||
newProcess2.getID(), parameters, ProcessStatus.SCHEDULED),
|
|
||||||
ProcessMatcher.matchProcess(newProcess3.getName(),
|
|
||||||
String.valueOf(newProcess3.getEPerson().getID()),
|
|
||||||
newProcess3.getID(), parameters, ProcessStatus.SCHEDULED),
|
|
||||||
ProcessMatcher.matchProcess(newProcess4.getName(),
|
|
||||||
String.valueOf(newProcess4.getEPerson().getID()),
|
|
||||||
newProcess4.getID(), parameters, ProcessStatus.SCHEDULED),
|
|
||||||
ProcessMatcher.matchProcess(newProcess5.getName(),
|
|
||||||
String.valueOf(newProcess5.getEPerson().getID()),
|
|
||||||
newProcess5.getID(), parameters, ProcessStatus.SCHEDULED),
|
|
||||||
ProcessMatcher.matchProcess(newProcess6.getName(),
|
|
||||||
String.valueOf(newProcess6.getEPerson().getID()),
|
|
||||||
newProcess6.getID(), parameters, ProcessStatus.SCHEDULED),
|
|
||||||
ProcessMatcher.matchProcess(newProcess7.getName(),
|
|
||||||
String.valueOf(newProcess7.getEPerson().getID()),
|
|
||||||
newProcess7.getID(), parameters, ProcessStatus.SCHEDULED),
|
|
||||||
ProcessMatcher.matchProcess(newProcess8.getName(),
|
ProcessMatcher.matchProcess(newProcess8.getName(),
|
||||||
String.valueOf(newProcess8.getEPerson().getID()),
|
String.valueOf(newProcess8.getEPerson().getID()),
|
||||||
newProcess8.getID(), parameters, ProcessStatus.SCHEDULED),
|
newProcess8.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
ProcessMatcher.matchProcess(newProcess9.getName(),
|
ProcessMatcher.matchProcess(newProcess7.getName(),
|
||||||
String.valueOf(newProcess9.getEPerson().getID()),
|
String.valueOf(newProcess7.getEPerson().getID()),
|
||||||
newProcess9.getID(), parameters, ProcessStatus.SCHEDULED)
|
newProcess7.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess6.getName(),
|
||||||
|
String.valueOf(newProcess6.getEPerson().getID()),
|
||||||
|
newProcess6.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess5.getName(),
|
||||||
|
String.valueOf(newProcess5.getEPerson().getID()),
|
||||||
|
newProcess5.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess4.getName(),
|
||||||
|
String.valueOf(newProcess4.getEPerson().getID()),
|
||||||
|
newProcess4.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess3.getName(),
|
||||||
|
String.valueOf(newProcess3.getEPerson().getID()),
|
||||||
|
newProcess3.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess2.getName(),
|
||||||
|
String.valueOf(newProcess2.getEPerson().getID()),
|
||||||
|
newProcess2.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess1.getName(),
|
||||||
|
String.valueOf(newProcess1.getEPerson().getID()),
|
||||||
|
newProcess1.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess.getName(),
|
||||||
|
String.valueOf(newProcess.getEPerson().getID()),
|
||||||
|
newProcess.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(process.getName(), String.valueOf(process.getEPerson().getID()),
|
||||||
|
process.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
)))
|
)))
|
||||||
.andExpect(jsonPath("$.page", is(
|
.andExpect(jsonPath("$.page", is(
|
||||||
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 11))));
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 11))));
|
||||||
@@ -323,6 +326,464 @@ public class ProcessRestRepositoryIT extends AbstractControllerIntegrationTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestForbidden() throws Exception {
|
||||||
|
String token = getAuthToken(eperson.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty"))
|
||||||
|
.andExpect(status().isForbidden());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestUnauthorized() throws Exception {
|
||||||
|
|
||||||
|
getClient().perform(get("/api/system/processes/search/byProperty"))
|
||||||
|
.andExpect(status().isUnauthorized());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUser() throws Exception {
|
||||||
|
Process newProcess = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess4 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess5 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess6 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess7 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters).build();
|
||||||
|
Process newProcess8 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters).build();
|
||||||
|
Process newProcess9 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters).build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", admin.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", containsInAnyOrder(
|
||||||
|
ProcessMatcher.matchProcess(process.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
process.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess7.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess7.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess8.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess8.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess9.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess9.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 4))));
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", eperson.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", containsInAnyOrder(
|
||||||
|
ProcessMatcher.matchProcess(newProcess.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess1.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess1.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess2.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess2.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess3.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess3.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess4.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess4.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess5.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess5.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess6.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess6.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByProcessStatus() throws Exception {
|
||||||
|
Process newProcess = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess4 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess5 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess6 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess7 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
Process newProcess8 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters).build();
|
||||||
|
Process newProcess9 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("processStatus", "FAILED"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", containsInAnyOrder(
|
||||||
|
ProcessMatcher.matchProcess(newProcess7.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess7.getID(), parameters, ProcessStatus.FAILED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess9.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess9.getID(), parameters, ProcessStatus.FAILED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 2))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByScriptName() throws Exception {
|
||||||
|
Process newProcess = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess4 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess5 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess6 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess7 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
Process newProcess8 = ProcessBuilder.createProcess(context, admin, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess9 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("scriptName", "another-mock-script"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", containsInAnyOrder(
|
||||||
|
ProcessMatcher.matchProcess(newProcess8.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess8.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByScriptNameAndUserId() throws Exception {
|
||||||
|
Process newProcess = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess4 = ProcessBuilder.createProcess(context, eperson, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess5 = ProcessBuilder.createProcess(context, eperson, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess6 = ProcessBuilder.createProcess(context, eperson, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess7 = ProcessBuilder.createProcess(context, admin, "another-mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
Process newProcess8 = ProcessBuilder.createProcess(context, admin, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess9 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("scriptName", "another-mock-script")
|
||||||
|
.param("userId", admin.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", containsInAnyOrder(
|
||||||
|
ProcessMatcher.matchProcess(newProcess7.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess7.getID(), parameters, ProcessStatus.FAILED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess8.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess8.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 2))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserIdAndProcessStatus() throws Exception {
|
||||||
|
Process newProcess = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
Process newProcess4 = ProcessBuilder.createProcess(context, eperson, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess5 = ProcessBuilder.createProcess(context, eperson, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess6 = ProcessBuilder.createProcess(context, eperson, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess7 = ProcessBuilder.createProcess(context, admin, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess8 = ProcessBuilder.createProcess(context, admin, "another-mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
Process newProcess9 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("processStatus", "FAILED")
|
||||||
|
.param("userId", admin.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", containsInAnyOrder(
|
||||||
|
ProcessMatcher.matchProcess(newProcess9.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess9.getID(), parameters, ProcessStatus.FAILED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess8.getName(),
|
||||||
|
String.valueOf(admin.getID().toString()),
|
||||||
|
newProcess8.getID(), parameters, ProcessStatus.FAILED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 2))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserIdAndProcessStatusAndScriptName() throws Exception {
|
||||||
|
Process newProcess = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
Process newProcess4 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters).build();
|
||||||
|
Process newProcess5 = ProcessBuilder.createProcess(context, eperson, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess6 = ProcessBuilder.createProcess(context, eperson, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess7 = ProcessBuilder.createProcess(context, admin, "another-mock-script", parameters).build();
|
||||||
|
Process newProcess8 = ProcessBuilder.createProcess(context, admin, "another-mock-script", parameters)
|
||||||
|
.withProcessStatus(ProcessStatus.FAILED).build();
|
||||||
|
Process newProcess9 = ProcessBuilder.createProcess(context, admin, "mock-script", parameters).build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("processStatus", "FAILED")
|
||||||
|
.param("userId", eperson.getID().toString())
|
||||||
|
.param("scriptName", "mock-script"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", containsInAnyOrder(
|
||||||
|
ProcessMatcher.matchProcess("mock-script",
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess1.getID(), parameters, ProcessStatus.FAILED),
|
||||||
|
ProcessMatcher.matchProcess("mock-script",
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess3.getID(), parameters, ProcessStatus.FAILED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 2))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestNoParametersBadRequest() throws Exception {
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty"))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestUnparseableProcessStatusParamBadRequest() throws Exception {
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("processStatus", "not-a-valid-status"))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestInvalidEPersonUuid() throws Exception {
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", UUID.randomUUID().toString()))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserSortedOnStartTimeAsc() throws Exception {
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("10/01/1990", "20/01/1990").build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("11/01/1990", "19/01/1990").build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("12/01/1990", "18/01/1990").build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", eperson.getID().toString())
|
||||||
|
.param("sort", "startTime,asc"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", contains(
|
||||||
|
ProcessMatcher.matchProcess(newProcess1.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess1.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess2.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess2.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess3.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess3.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserSortedOnStartTimeDesc() throws Exception {
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("10/01/1990", "20/01/1990").build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("11/01/1990", "19/01/1990").build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("12/01/1990", "18/01/1990").build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", eperson.getID().toString())
|
||||||
|
.param("sort", "startTime,desc"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", contains(
|
||||||
|
ProcessMatcher.matchProcess(newProcess3.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess3.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess2.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess2.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess1.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess1.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserSortedOnEndTimeAsc() throws Exception {
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("10/01/1990", "20/01/1990").build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("11/01/1990", "19/01/1990").build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("12/01/1990", "18/01/1990").build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", eperson.getID().toString())
|
||||||
|
.param("sort", "endTime,asc"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", contains(
|
||||||
|
ProcessMatcher.matchProcess(newProcess3.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess3.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess2.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess2.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess1.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess1.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserSortedOnEndTimeDesc() throws Exception {
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("10/01/1990", "20/01/1990").build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("11/01/1990", "19/01/1990").build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("12/01/1990", "18/01/1990").build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", eperson.getID().toString())
|
||||||
|
.param("sort", "endTime,desc"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", contains(
|
||||||
|
ProcessMatcher.matchProcess(newProcess1.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess1.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess2.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess2.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess3.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess3.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserSortedOnMultipleBadRequest() throws Exception {
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("10/01/1990", "20/01/1990").build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("11/01/1990", "19/01/1990").build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("12/01/1990", "18/01/1990").build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", eperson.getID().toString())
|
||||||
|
.param("sort", "endTime,desc")
|
||||||
|
.param("sort", "startTime,desc"))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserSortedOnDefault() throws Exception {
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("10/01/1990", "20/01/1990").build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("11/01/1990", "19/01/1990").build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("12/01/1990", "18/01/1990").build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", eperson.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.processes", contains(
|
||||||
|
ProcessMatcher.matchProcess(newProcess3.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess3.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess2.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess2.getID(), parameters, ProcessStatus.SCHEDULED),
|
||||||
|
ProcessMatcher.matchProcess(newProcess1.getName(),
|
||||||
|
String.valueOf(eperson.getID().toString()),
|
||||||
|
newProcess1.getID(), parameters, ProcessStatus.SCHEDULED)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page", is(
|
||||||
|
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchProcessTestByUserSortedOnNonExistingIsSortedAsDefault() throws Exception {
|
||||||
|
Process newProcess1 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("10/01/1990", "20/01/1990").build();
|
||||||
|
Process newProcess2 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("11/01/1990", "19/01/1990").build();
|
||||||
|
Process newProcess3 = ProcessBuilder.createProcess(context, eperson, "mock-script", parameters)
|
||||||
|
.withStartAndEndTime("12/01/1990", "18/01/1990").build();
|
||||||
|
|
||||||
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/system/processes/search/byProperty")
|
||||||
|
.param("userId", eperson.getID().toString())
|
||||||
|
.param("sort", "eaz,desc"))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getProcessOutput() throws Exception {
|
public void getProcessOutput() throws Exception {
|
||||||
try (InputStream is = IOUtils.toInputStream("Test File For Process", CharEncoding.UTF_8)) {
|
try (InputStream is = IOUtils.toInputStream("Test File For Process", CharEncoding.UTF_8)) {
|
||||||
|
@@ -91,7 +91,11 @@ public class ScriptRestRepositoryIT extends AbstractControllerIntegrationTest {
|
|||||||
ScriptMatcher.matchScript(scriptConfigurations.get(3).getName(),
|
ScriptMatcher.matchScript(scriptConfigurations.get(3).getName(),
|
||||||
scriptConfigurations.get(3).getDescription()),
|
scriptConfigurations.get(3).getDescription()),
|
||||||
ScriptMatcher.matchScript(scriptConfigurations.get(4).getName(),
|
ScriptMatcher.matchScript(scriptConfigurations.get(4).getName(),
|
||||||
scriptConfigurations.get(4).getDescription())
|
scriptConfigurations.get(4).getDescription()),
|
||||||
|
ScriptMatcher.matchScript(scriptConfigurations.get(5).getName(),
|
||||||
|
scriptConfigurations.get(5).getDescription()),
|
||||||
|
ScriptMatcher.matchScript(scriptConfigurations.get(6).getName(),
|
||||||
|
scriptConfigurations.get(6).getDescription())
|
||||||
)));
|
)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration test that cover ShibbolethRestController
|
* Integration test that cover ShibbolethRestController
|
||||||
@@ -21,6 +24,17 @@ import org.junit.Test;
|
|||||||
*/
|
*/
|
||||||
public class ShibbolethRestControllerIT extends AbstractControllerIntegrationTest {
|
public class ShibbolethRestControllerIT extends AbstractControllerIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ConfigurationService configurationService;
|
||||||
|
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
configurationService.setProperty("rest.cors.allowed-origins",
|
||||||
|
"${dspace.ui.url}, http://anotherdspacehost:4000");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRedirectToDefaultDspaceUrl() throws Exception {
|
public void testRedirectToDefaultDspaceUrl() throws Exception {
|
||||||
String token = getAuthToken(eperson.getEmail(), password);
|
String token = getAuthToken(eperson.getEmail(), password);
|
||||||
@@ -32,6 +46,7 @@ public class ShibbolethRestControllerIT extends AbstractControllerIntegrationTes
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRedirectToGivenTrustedUrl() throws Exception {
|
public void testRedirectToGivenTrustedUrl() throws Exception {
|
||||||
|
|
||||||
String token = getAuthToken(eperson.getEmail(), password);
|
String token = getAuthToken(eperson.getEmail(), password);
|
||||||
|
|
||||||
getClient(token).perform(get("/api/authn/shibboleth")
|
getClient(token).perform(get("/api/authn/shibboleth")
|
||||||
@@ -40,6 +55,16 @@ public class ShibbolethRestControllerIT extends AbstractControllerIntegrationTes
|
|||||||
.andExpect(redirectedUrl("http://localhost:8080/server/api/authn/status"));
|
.andExpect(redirectedUrl("http://localhost:8080/server/api/authn/status"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedirectToAnotherGivenTrustedUrl() throws Exception {
|
||||||
|
String token = getAuthToken(eperson.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/authn/shibboleth")
|
||||||
|
.param("redirectUrl", "http://anotherdspacehost:4000/home"))
|
||||||
|
.andExpect(status().is3xxRedirection())
|
||||||
|
.andExpect(redirectedUrl("http://anotherdspacehost:4000/home"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRedirectToGivenUntrustedUrl() throws Exception {
|
public void testRedirectToGivenUntrustedUrl() throws Exception {
|
||||||
String token = getAuthToken(eperson.getEmail(), password);
|
String token = getAuthToken(eperson.getEmail(), password);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.statistics.export.service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock OpenUrlService that will ensure that IRUS tracker does need to be contacted in order to test the functionality
|
||||||
|
*/
|
||||||
|
public class MockOpenUrlServiceImpl extends OpenUrlServiceImpl {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ArrayList testProcessedUrls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a response code to simulate contact to the external url
|
||||||
|
* When the url contains "fail", a fail code 500 will be returned
|
||||||
|
* Otherwise the success code 200 will be returned
|
||||||
|
* @param urlStr
|
||||||
|
* @return 200 or 500 depending on whether the "fail" keyword is present in the url
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected int getResponseCodeFromUrl(final String urlStr) throws IOException {
|
||||||
|
if (StringUtils.contains(urlStr, "fail")) {
|
||||||
|
return HttpURLConnection.HTTP_INTERNAL_ERROR;
|
||||||
|
} else {
|
||||||
|
testProcessedUrls.add(urlStr);
|
||||||
|
return HttpURLConnection.HTTP_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -18,21 +18,20 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<!-- If Unit Testing is enabled, then setup the Unit Test Environment.
|
<!-- Setup the Unit Test Environment (when -DskipUnitTests=false) -->
|
||||||
See also the 'skiptests' profile in Parent POM. -->
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>test-environment</id>
|
<id>unit-test-environment</id>
|
||||||
<activation>
|
<activation>
|
||||||
<activeByDefault>false</activeByDefault>
|
<activeByDefault>false</activeByDefault>
|
||||||
<property>
|
<property>
|
||||||
<name>skipTests</name>
|
<name>skipUnitTests</name>
|
||||||
<value>false</value>
|
<value>false</value>
|
||||||
</property>
|
</property>
|
||||||
</activation>
|
</activation>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
||||||
(see: http://gmaven.codehaus.org/Executing+Groovy+Code )
|
(see: https://groovy.github.io/gmaven/groovy-maven-plugin/execute.html )
|
||||||
We are generating a OS-agnostic version (agnostic.build.dir) of
|
We are generating a OS-agnostic version (agnostic.build.dir) of
|
||||||
the ${project.build.directory} property (full path of target dir).
|
the ${project.build.directory} property (full path of target dir).
|
||||||
This is needed by the Surefire plugin (see below) to
|
This is needed by the Surefire plugin (see below) to
|
||||||
@@ -59,21 +58,9 @@
|
|||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
<!-- TODO: When Groovy 3.0.0 is released, we should upgrade to fix this warning
|
|
||||||
(which appears in Maven builds) https://issues.apache.org/jira/browse/GROOVY-8339
|
|
||||||
The below (commented out) dependency should let us upgrade to v3.0.0 once released. -->
|
|
||||||
<!--<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.codehaus.groovy</groupId>
|
|
||||||
<artifactId>groovy-all</artifactId>
|
|
||||||
<version>3.0.0</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
<type>pom</type>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>-->
|
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<!-- Run Unit Testing! This plugin just kicks off the tests (when enabled). -->
|
<!-- Run Unit Testing! This plugin just kicks off the tests. -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
@@ -21,7 +21,8 @@ import org.springframework.context.ConfigurableApplicationContext;
|
|||||||
public interface ServiceManager {
|
public interface ServiceManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the application context
|
* Get the application context.
|
||||||
|
* @return the Spring application context.
|
||||||
*/
|
*/
|
||||||
public ConfigurableApplicationContext getApplicationContext();
|
public ConfigurableApplicationContext getApplicationContext();
|
||||||
|
|
||||||
@@ -46,18 +47,14 @@ public interface ServiceManager {
|
|||||||
* service manager objects. If using Spring this allows access to the
|
* service manager objects. If using Spring this allows access to the
|
||||||
* underlying ApplicationContext object like so:<br>
|
* underlying ApplicationContext object like so:<br>
|
||||||
* {@code getServiceByName(ApplicationContext.class.getName(), ApplicationContext.class);}
|
* {@code getServiceByName(ApplicationContext.class.getName(), ApplicationContext.class);}
|
||||||
* If using Guice then the same applies like so:<br>
|
|
||||||
* {@code getServiceByName(Injector.class.getName(), Injector.class);}
|
|
||||||
* It is also possible to register a module and cause Guice to fill
|
|
||||||
* in any injected core services (see register method).
|
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param <T> Class type
|
* @param <T> Class type.
|
||||||
* @param name (optional) the unique name for this service.
|
* @param name (optional) the unique name for this service.
|
||||||
* If null then the bean will be returned if there is only one
|
* If null then the bean will be returned if there is only one
|
||||||
* service of this type.
|
* service of this type.
|
||||||
* @param type the type for the requested service (this will typically be the interface class but can be concrete
|
* @param type the type for the requested service (this will typically be
|
||||||
* as well)
|
* the interface class but can be concrete as well).
|
||||||
* @return the service singleton OR null if none is found
|
* @return the service singleton OR null if none is found
|
||||||
*/
|
*/
|
||||||
public <T> T getServiceByName(String name, Class<T> type);
|
public <T> T getServiceByName(String name, Class<T> type);
|
||||||
@@ -90,12 +87,6 @@ public interface ServiceManager {
|
|||||||
* down the context (webapp, etc.) that registered the service so
|
* down the context (webapp, etc.) that registered the service so
|
||||||
* that the full lifecycle completes correctly.
|
* that the full lifecycle completes correctly.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
|
||||||
* <em>NOTE:</em> if using Guice it is possible to register a Guice
|
|
||||||
* Module as a service, which will not actually register it but will
|
|
||||||
* cause anything in the Module to have existing core services injected
|
|
||||||
* into it. You can use anything as the name in this case.
|
|
||||||
* </p>
|
|
||||||
*
|
*
|
||||||
* @param name the name of the service (must be unique)
|
* @param name the name of the service (must be unique)
|
||||||
* @param service the object to register as a singleton service
|
* @param service the object to register as a singleton service
|
||||||
@@ -103,6 +94,14 @@ public interface ServiceManager {
|
|||||||
*/
|
*/
|
||||||
public void registerService(String name, Object service);
|
public void registerService(String name, Object service);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a singleton service at runtime, but do not inject dependencies.
|
||||||
|
* Typically used with a service instance that has already had all
|
||||||
|
* dependencies injected explicitly, for example in test code.
|
||||||
|
*
|
||||||
|
* @param name the name of the service (must be unique).
|
||||||
|
* @param service the instance to register as a singleton service.
|
||||||
|
*/
|
||||||
public void registerServiceNoAutowire(String name, Object service);
|
public void registerServiceNoAutowire(String name, Object service);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,7 +111,7 @@ public interface ServiceManager {
|
|||||||
* except that it allows the core service manager to startup your
|
* except that it allows the core service manager to startup your
|
||||||
* service for you instead of you providing a service to the core.
|
* service for you instead of you providing a service to the core.
|
||||||
* In general, it is better if you use your own service manager
|
* In general, it is better if you use your own service manager
|
||||||
* (like Spring or Guice) to manage your services and simply
|
* (like Spring) to manage your services and simply
|
||||||
* inherit the core service beans from the DSpace core service
|
* inherit the core service beans from the DSpace core service
|
||||||
* manager using the special capabilities of
|
* manager using the special capabilities of
|
||||||
* {@link #getServiceByName(String, Class)}.
|
* {@link #getServiceByName(String, Class)}.
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.kernel.mixins;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow the service or provider to be initialized when it is started
|
|
||||||
* by the service manager. After all injections are complete the init
|
|
||||||
* method will be called. Any initialization that a service needs to do
|
|
||||||
* should happen here.
|
|
||||||
*
|
|
||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
|
||||||
*/
|
|
||||||
public interface InitializedService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed after the service is created and all dependencies and
|
|
||||||
* configurations injected.
|
|
||||||
*/
|
|
||||||
public void init();
|
|
||||||
|
|
||||||
}
|
|
@@ -1,26 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.kernel.mixins;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow the service to be notified when the service manager is shutting
|
|
||||||
* it down. This will typically be called when the kernel is stopped or
|
|
||||||
* destroyed. Any cleanup that a service needs to do when it is
|
|
||||||
* shut down should happen here.
|
|
||||||
*
|
|
||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
|
||||||
*/
|
|
||||||
public interface ShutdownService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called as the service manager is stopping or shutting down.
|
|
||||||
*/
|
|
||||||
public void shutdown();
|
|
||||||
|
|
||||||
}
|
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.servicemanager;
|
package org.dspace.servicemanager;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -17,23 +18,19 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.dspace.kernel.Activator;
|
import org.dspace.kernel.Activator;
|
||||||
import org.dspace.kernel.config.SpringLoader;
|
import org.dspace.kernel.config.SpringLoader;
|
||||||
import org.dspace.kernel.mixins.ConfigChangeListener;
|
import org.dspace.kernel.mixins.ConfigChangeListener;
|
||||||
import org.dspace.kernel.mixins.InitializedService;
|
|
||||||
import org.dspace.kernel.mixins.ServiceChangeListener;
|
import org.dspace.kernel.mixins.ServiceChangeListener;
|
||||||
import org.dspace.kernel.mixins.ServiceManagerReadyAware;
|
import org.dspace.kernel.mixins.ServiceManagerReadyAware;
|
||||||
import org.dspace.kernel.mixins.ShutdownService;
|
|
||||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||||
import org.dspace.servicemanager.spring.DSpaceBeanFactoryPostProcessor;
|
import org.dspace.servicemanager.spring.DSpaceBeanFactoryPostProcessor;
|
||||||
import org.dspace.services.ConfigurationService;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeanWrapper;
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.PropertyAccessorFactory;
|
|
||||||
import org.springframework.beans.factory.ListableBeanFactory;
|
import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||||
@@ -374,7 +371,18 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
|||||||
applicationContext.getBeanFactory().destroyBean(name, beanInstance);
|
applicationContext.getBeanFactory().destroyBean(name, beanInstance);
|
||||||
} catch (NoSuchBeanDefinitionException e) {
|
} catch (NoSuchBeanDefinitionException e) {
|
||||||
// this happens if the bean was registered manually (annoyingly)
|
// this happens if the bean was registered manually (annoyingly)
|
||||||
DSpaceServiceManager.shutdownService(beanInstance);
|
for (final Method method : beanInstance.getClass().getMethods()) {
|
||||||
|
if (method.isAnnotationPresent(PreDestroy.class)) {
|
||||||
|
try {
|
||||||
|
method.invoke(beanInstance);
|
||||||
|
} catch (IllegalAccessException
|
||||||
|
| IllegalArgumentException
|
||||||
|
| InvocationTargetException ex) {
|
||||||
|
log.warn("Failed to call declared @PreDestroy method of {} service",
|
||||||
|
name, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (BeansException e) {
|
} catch (BeansException e) {
|
||||||
// nothing to do here, could not find the bean
|
// nothing to do here, could not find the bean
|
||||||
@@ -578,79 +586,6 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
|||||||
|
|
||||||
// STATICS
|
// STATICS
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures a given service (i.e. bean) based on any DSpace configuration
|
|
||||||
* settings which refer to it by name. .
|
|
||||||
* <P>
|
|
||||||
* NOTE: Any configurations related to a specific service MUST be prefixed
|
|
||||||
* with the given service's name (e.g. [serviceName].setting = value)
|
|
||||||
* <P>
|
|
||||||
* This method logs an error if it encounters configs which refer to a
|
|
||||||
* service by name, but is an invalid setting for that service.
|
|
||||||
*
|
|
||||||
* @param serviceName the name of the service
|
|
||||||
* @param service the service object (which will be configured)
|
|
||||||
* @param config the running configuration service
|
|
||||||
*/
|
|
||||||
public static void configureService(String serviceName, Object service, ConfigurationService config) {
|
|
||||||
|
|
||||||
// Check if the configuration has any properties whose prefix
|
|
||||||
// corresponds to this service's name
|
|
||||||
List<String> configKeys = config.getPropertyKeys(serviceName);
|
|
||||||
if (configKeys != null && !configKeys.isEmpty()) {
|
|
||||||
BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(service);
|
|
||||||
for (String key : configKeys) {
|
|
||||||
// Remove serviceName prefix from key. This is the name of the actual bean's parameter
|
|
||||||
// This removes the first x chars, where x is length of serviceName + 1 char
|
|
||||||
// Format of Key: [serviceName].[param]
|
|
||||||
String param = key.substring(serviceName.length() + 1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Attempt to set this configuration on the given service's bean
|
|
||||||
beanWrapper.setPropertyValue(param, config.getProperty(key));
|
|
||||||
log.info("Set param (" + param + ") on service bean (" + serviceName + ") to: " + config
|
|
||||||
.getProperty(key));
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
// If an error occurs, just log it
|
|
||||||
log.error("Unable to set param (" + param + ") on service bean (" + serviceName + ") to: " + config
|
|
||||||
.getProperty(key), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a service if it asks to be initialized or does nothing.
|
|
||||||
*
|
|
||||||
* @param service any bean
|
|
||||||
* @throws IllegalStateException if the service init fails
|
|
||||||
*/
|
|
||||||
public static void initService(Object service) {
|
|
||||||
if (service instanceof InitializedService) {
|
|
||||||
try {
|
|
||||||
((InitializedService) service).init();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Failure attempting to initialize service (" + service + "): " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shuts down a service if it asks to be shutdown or does nothing.
|
|
||||||
*
|
|
||||||
* @param service any bean
|
|
||||||
*/
|
|
||||||
public static void shutdownService(Object service) {
|
|
||||||
if (service instanceof ShutdownService) {
|
|
||||||
try {
|
|
||||||
((ShutdownService) service).shutdown();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Failure shutting down service: {}", service, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the complete list of Spring configuration paths, including
|
* Build the complete list of Spring configuration paths, including
|
||||||
* hard-wired paths.
|
* hard-wired paths.
|
||||||
@@ -702,5 +637,4 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
|||||||
}
|
}
|
||||||
return pathList.toArray(new String[pathList.size()]);
|
return pathList.toArray(new String[pathList.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,72 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.servicemanager.spring;
|
|
||||||
|
|
||||||
import org.dspace.servicemanager.DSpaceServiceManager;
|
|
||||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
|
||||||
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This processes beans as they are loaded into the system by spring.
|
|
||||||
* Allows us to handle the init method and also push config options.
|
|
||||||
*
|
|
||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
|
||||||
*/
|
|
||||||
public final class DSpaceBeanPostProcessor implements BeanPostProcessor, DestructionAwareBeanPostProcessor {
|
|
||||||
|
|
||||||
private DSpaceConfigurationService configurationService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public DSpaceBeanPostProcessor(DSpaceConfigurationService configurationService) {
|
|
||||||
if (configurationService == null) {
|
|
||||||
throw new IllegalArgumentException("configuration service cannot be null");
|
|
||||||
}
|
|
||||||
this.configurationService = configurationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang
|
|
||||||
* .Object, java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
|
||||||
throws BeansException {
|
|
||||||
// Before initializing the service, first configure it based on any related settings in the configurationService
|
|
||||||
// NOTE: configs related to this bean MUST be prefixed with the bean's name (e.g. [beanName].setting = value)
|
|
||||||
DSpaceServiceManager.configureService(beanName, bean, configurationService);
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang
|
|
||||||
* .Object, java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
|
||||||
throws BeansException {
|
|
||||||
DSpaceServiceManager.initService(bean);
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
|
|
||||||
* (java.lang.Object, java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
|
|
||||||
DSpaceServiceManager.shutdownService(bean);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
public boolean requiresDestruction(Object arg0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -16,14 +16,14 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import net.sf.ehcache.Ehcache;
|
import net.sf.ehcache.Ehcache;
|
||||||
import net.sf.ehcache.Statistics;
|
import net.sf.ehcache.Statistics;
|
||||||
import org.dspace.kernel.ServiceManager;
|
import org.dspace.kernel.ServiceManager;
|
||||||
import org.dspace.kernel.mixins.ConfigChangeListener;
|
import org.dspace.kernel.mixins.ConfigChangeListener;
|
||||||
import org.dspace.kernel.mixins.InitializedService;
|
|
||||||
import org.dspace.kernel.mixins.ServiceChangeListener;
|
import org.dspace.kernel.mixins.ServiceChangeListener;
|
||||||
import org.dspace.kernel.mixins.ShutdownService;
|
|
||||||
import org.dspace.providers.CacheProvider;
|
import org.dspace.providers.CacheProvider;
|
||||||
import org.dspace.services.CachingService;
|
import org.dspace.services.CachingService;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
@@ -38,7 +38,6 @@ import org.dspace.utils.servicemanager.ProviderHolder;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Required;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the core caching service, which is available for
|
* Implementation of the core caching service, which is available for
|
||||||
@@ -47,16 +46,16 @@ import org.springframework.beans.factory.annotation.Required;
|
|||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||||
*/
|
*/
|
||||||
public final class CachingServiceImpl
|
public final class CachingServiceImpl
|
||||||
implements CachingService, InitializedService, ShutdownService, ConfigChangeListener, ServiceChangeListener {
|
implements CachingService, ConfigChangeListener, ServiceChangeListener {
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(CachingServiceImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(CachingServiceImpl.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the event key for a full cache reset.
|
* This is the event key for a full cache reset.
|
||||||
*/
|
*/
|
||||||
protected static final String EVENT_RESET = "caching.reset";
|
protected static final String EVENT_RESET = "caching.reset";
|
||||||
/**
|
/**
|
||||||
* The default config location.
|
* The default configuration location.
|
||||||
*/
|
*/
|
||||||
protected static final String DEFAULT_CONFIG = "org/dspace/services/caching/ehcache-config.xml";
|
protected static final String DEFAULT_CONFIG = "org/dspace/services/caching/ehcache-config.xml";
|
||||||
|
|
||||||
@@ -64,15 +63,14 @@ public final class CachingServiceImpl
|
|||||||
* All the non-thread caches that we know about.
|
* All the non-thread caches that we know about.
|
||||||
* Mostly used for tracking purposes.
|
* Mostly used for tracking purposes.
|
||||||
*/
|
*/
|
||||||
private Map<String, EhcacheCache> cacheRecord = new ConcurrentHashMap<String, EhcacheCache>();
|
private final Map<String, EhcacheCache> cacheRecord = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the request caches. This is bound to the thread.
|
* All the request caches. This is bound to the thread.
|
||||||
* The initial value of this TL is set automatically when it is
|
* The initial value of this TL is set automatically when it is
|
||||||
* created.
|
* created.
|
||||||
*/
|
*/
|
||||||
private Map<String, Map<String, MapCache>> requestCachesMap = new ConcurrentHashMap<String, Map<String,
|
private final Map<String, Map<String, MapCache>> requestCachesMap = new ConcurrentHashMap<>();
|
||||||
MapCache>>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the current request map which is bound to the current thread
|
* @return the current request map which is bound to the current thread
|
||||||
@@ -84,7 +82,7 @@ public final class CachingServiceImpl
|
|||||||
|
|
||||||
Map<String, MapCache> requestCaches = requestCachesMap.get(requestService.getCurrentRequestId());
|
Map<String, MapCache> requestCaches = requestCachesMap.get(requestService.getCurrentRequestId());
|
||||||
if (requestCaches == null) {
|
if (requestCaches == null) {
|
||||||
requestCaches = new HashMap<String, MapCache>();
|
requestCaches = new HashMap<>();
|
||||||
requestCachesMap.put(requestService.getCurrentRequestId(), requestCaches);
|
requestCachesMap.put(requestService.getCurrentRequestId(), requestCaches);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +92,7 @@ public final class CachingServiceImpl
|
|||||||
/**
|
/**
|
||||||
* Unbinds all request caches. Destroys the caches completely.
|
* Unbinds all request caches. Destroys the caches completely.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void unbindRequestCaches() {
|
public void unbindRequestCaches() {
|
||||||
if (requestService != null) {
|
if (requestService != null) {
|
||||||
requestCachesMap.remove(requestService.getCurrentRequestId());
|
requestCachesMap.remove(requestService.getCurrentRequestId());
|
||||||
@@ -102,8 +101,7 @@ public final class CachingServiceImpl
|
|||||||
|
|
||||||
private ConfigurationService configurationService;
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired(required = true)
|
||||||
@Required
|
|
||||||
public void setConfigurationService(ConfigurationService configurationService) {
|
public void setConfigurationService(ConfigurationService configurationService) {
|
||||||
this.configurationService = configurationService;
|
this.configurationService = configurationService;
|
||||||
}
|
}
|
||||||
@@ -117,8 +115,7 @@ public final class CachingServiceImpl
|
|||||||
|
|
||||||
private ServiceManager serviceManager;
|
private ServiceManager serviceManager;
|
||||||
|
|
||||||
@Autowired
|
@Autowired(required = true)
|
||||||
@Required
|
|
||||||
public void setServiceManager(ServiceManager serviceManager) {
|
public void setServiceManager(ServiceManager serviceManager) {
|
||||||
this.serviceManager = serviceManager;
|
this.serviceManager = serviceManager;
|
||||||
}
|
}
|
||||||
@@ -128,8 +125,7 @@ public final class CachingServiceImpl
|
|||||||
*/
|
*/
|
||||||
protected net.sf.ehcache.CacheManager cacheManager;
|
protected net.sf.ehcache.CacheManager cacheManager;
|
||||||
|
|
||||||
@Autowired
|
@Autowired(required = true)
|
||||||
@Required
|
|
||||||
public void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {
|
public void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {
|
||||||
this.cacheManager = cacheManager;
|
this.cacheManager = cacheManager;
|
||||||
}
|
}
|
||||||
@@ -145,7 +141,7 @@ public final class CachingServiceImpl
|
|||||||
private int timeToIdleSecs = 600;
|
private int timeToIdleSecs = 600;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the config settings from the configuration service.
|
* Reloads the configuration settings from the configuration service.
|
||||||
*/
|
*/
|
||||||
protected void reloadConfig() {
|
protected void reloadConfig() {
|
||||||
// Reload caching configurations, but have sane default values if unspecified in configs
|
// Reload caching configurations, but have sane default values if unspecified in configs
|
||||||
@@ -160,7 +156,7 @@ public final class CachingServiceImpl
|
|||||||
* WARNING: Do not change the order of these! <br/>
|
* WARNING: Do not change the order of these! <br/>
|
||||||
* If you do, you have to fix the {@link #reloadConfig()} method -AZ
|
* If you do, you have to fix the {@link #reloadConfig()} method -AZ
|
||||||
*/
|
*/
|
||||||
private String[] knownConfigNames = {
|
private final String[] knownConfigNames = {
|
||||||
"caching.use.clustering", // bool - whether to use clustering
|
"caching.use.clustering", // bool - whether to use clustering
|
||||||
"caching.default.use.disk.store", // whether to use the disk store
|
"caching.default.use.disk.store", // whether to use the disk store
|
||||||
"caching.default.max.elements", // the maximum number of elements in memory, before they are evicted
|
"caching.default.max.elements", // the maximum number of elements in memory, before they are evicted
|
||||||
@@ -172,13 +168,15 @@ public final class CachingServiceImpl
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.ConfigChangeListener#notifyForConfigNames()
|
* @see org.dspace.kernel.mixins.ConfigChangeListener#notifyForConfigNames()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String[] notifyForConfigNames() {
|
public String[] notifyForConfigNames() {
|
||||||
return knownConfigNames == null ? null : knownConfigNames.clone();
|
return knownConfigNames.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.ConfigChangeListener#configurationChanged(java.util.List, java.util.Map)
|
* @see org.dspace.kernel.mixins.ConfigChangeListener#configurationChanged(java.util.List, java.util.Map)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void configurationChanged(List<String> changedSettingNames, Map<String, String> changedSettings) {
|
public void configurationChanged(List<String> changedSettingNames, Map<String, String> changedSettings) {
|
||||||
reloadConfig();
|
reloadConfig();
|
||||||
}
|
}
|
||||||
@@ -187,7 +185,7 @@ public final class CachingServiceImpl
|
|||||||
* This will make it easier to handle a provider which might go away
|
* This will make it easier to handle a provider which might go away
|
||||||
* because the classloader is gone.
|
* because the classloader is gone.
|
||||||
*/
|
*/
|
||||||
private ProviderHolder<CacheProvider> provider = new ProviderHolder<CacheProvider>();
|
private final ProviderHolder<CacheProvider> provider = new ProviderHolder<>();
|
||||||
|
|
||||||
public CacheProvider getCacheProvider() {
|
public CacheProvider getCacheProvider() {
|
||||||
return provider.getProvider();
|
return provider.getProvider();
|
||||||
@@ -211,6 +209,7 @@ public final class CachingServiceImpl
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.ServiceChangeListener#notifyForTypes()
|
* @see org.dspace.kernel.mixins.ServiceChangeListener#notifyForTypes()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Class<?>[] notifyForTypes() {
|
public Class<?>[] notifyForTypes() {
|
||||||
return new Class<?>[] {CacheProvider.class};
|
return new Class<?>[] {CacheProvider.class};
|
||||||
}
|
}
|
||||||
@@ -219,6 +218,7 @@ public final class CachingServiceImpl
|
|||||||
* @see org.dspace.kernel.mixins.ServiceChangeListener#serviceRegistered(java.lang.String, java.lang.Object, java
|
* @see org.dspace.kernel.mixins.ServiceChangeListener#serviceRegistered(java.lang.String, java.lang.Object, java
|
||||||
* .util.List)
|
* .util.List)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void serviceRegistered(String serviceName, Object service, List<Class<?>> implementedTypes) {
|
public void serviceRegistered(String serviceName, Object service, List<Class<?>> implementedTypes) {
|
||||||
provider.setProvider((CacheProvider) service);
|
provider.setProvider((CacheProvider) service);
|
||||||
}
|
}
|
||||||
@@ -226,14 +226,12 @@ public final class CachingServiceImpl
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.ServiceChangeListener#serviceUnregistered(java.lang.String, java.lang.Object)
|
* @see org.dspace.kernel.mixins.ServiceChangeListener#serviceUnregistered(java.lang.String, java.lang.Object)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void serviceUnregistered(String serviceName, Object service) {
|
public void serviceUnregistered(String serviceName, Object service) {
|
||||||
provider.setProvider(null);
|
provider.setProvider(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
@PostConstruct
|
||||||
* @see org.dspace.kernel.mixins.InitializedService#init()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void init() {
|
public void init() {
|
||||||
log.info("init()");
|
log.info("init()");
|
||||||
// get settings
|
// get settings
|
||||||
@@ -256,17 +254,13 @@ public final class CachingServiceImpl
|
|||||||
log.info("Caching service initialized:\n" + getStatus(null));
|
log.info("Caching service initialized:\n" + getStatus(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
@PreDestroy
|
||||||
* @see org.dspace.kernel.mixins.ShutdownService#shutdown()
|
|
||||||
*/
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
log.info("destroy()");
|
log.info("destroy()");
|
||||||
// for some reason this causes lots of errors so not using it for now -AZ
|
// for some reason this causes lots of errors so not using it for now -AZ
|
||||||
//ehCacheManagementService.dispose();
|
//ehCacheManagementService.dispose();
|
||||||
try {
|
try {
|
||||||
if (cacheRecord != null) {
|
cacheRecord.clear();
|
||||||
cacheRecord.clear();
|
|
||||||
}
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// whatever
|
// whatever
|
||||||
}
|
}
|
||||||
@@ -290,6 +284,7 @@ public final class CachingServiceImpl
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.CachingService#destroyCache(java.lang.String)
|
* @see org.dspace.services.CachingService#destroyCache(java.lang.String)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void destroyCache(String cacheName) {
|
public void destroyCache(String cacheName) {
|
||||||
if (cacheName == null || "".equals(cacheName)) {
|
if (cacheName == null || "".equals(cacheName)) {
|
||||||
throw new IllegalArgumentException("cacheName cannot be null or empty string");
|
throw new IllegalArgumentException("cacheName cannot be null or empty string");
|
||||||
@@ -319,6 +314,7 @@ public final class CachingServiceImpl
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.CachingService#getCache(java.lang.String, org.dspace.services.model.CacheConfig)
|
* @see org.dspace.services.CachingService#getCache(java.lang.String, org.dspace.services.model.CacheConfig)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Cache getCache(String cacheName, CacheConfig cacheConfig) {
|
public Cache getCache(String cacheName, CacheConfig cacheConfig) {
|
||||||
Cache cache = null;
|
Cache cache = null;
|
||||||
|
|
||||||
@@ -359,8 +355,9 @@ public final class CachingServiceImpl
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.CachingService#getCaches()
|
* @see org.dspace.services.CachingService#getCaches()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public List<Cache> getCaches() {
|
public List<Cache> getCaches() {
|
||||||
List<Cache> caches = new ArrayList<Cache>(this.cacheRecord.values());
|
List<Cache> caches = new ArrayList<>(this.cacheRecord.values());
|
||||||
if (getCacheProvider() != null) {
|
if (getCacheProvider() != null) {
|
||||||
try {
|
try {
|
||||||
caches.addAll(getCacheProvider().getCaches());
|
caches.addAll(getCacheProvider().getCaches());
|
||||||
@@ -377,6 +374,7 @@ public final class CachingServiceImpl
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.CachingService#getStatus(java.lang.String)
|
* @see org.dspace.services.CachingService#getStatus(java.lang.String)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getStatus(String cacheName) {
|
public String getStatus(String cacheName) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
@@ -433,6 +431,7 @@ public final class CachingServiceImpl
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.CachingService#resetCaches()
|
* @see org.dspace.services.CachingService#resetCaches()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void resetCaches() {
|
public void resetCaches() {
|
||||||
log.debug("resetCaches()");
|
log.debug("resetCaches()");
|
||||||
|
|
||||||
@@ -468,7 +467,7 @@ public final class CachingServiceImpl
|
|||||||
if (sorted) {
|
if (sorted) {
|
||||||
Arrays.sort(cacheNames);
|
Arrays.sort(cacheNames);
|
||||||
}
|
}
|
||||||
final List<Ehcache> caches = new ArrayList<Ehcache>(cacheNames.length);
|
final List<Ehcache> caches = new ArrayList<>(cacheNames.length);
|
||||||
for (String cacheName : cacheNames) {
|
for (String cacheName : cacheNames) {
|
||||||
caches.add(cacheManager.getEhcache(cacheName));
|
caches.add(cacheManager.getEhcache(cacheName));
|
||||||
}
|
}
|
||||||
@@ -612,6 +611,7 @@ public final class CachingServiceImpl
|
|||||||
public static final class NameComparator implements Comparator<Cache>, Serializable {
|
public static final class NameComparator implements Comparator<Cache>, Serializable {
|
||||||
public static final long serialVersionUID = 1l;
|
public static final long serialVersionUID = 1l;
|
||||||
|
|
||||||
|
@Override
|
||||||
public int compare(Cache o1, Cache o2) {
|
public int compare(Cache o1, Cache o2) {
|
||||||
return o1.getName().compareTo(o2.getName());
|
return o1.getName().compareTo(o2.getName());
|
||||||
}
|
}
|
||||||
@@ -619,22 +619,25 @@ public final class CachingServiceImpl
|
|||||||
|
|
||||||
private class CachingServiceRequestInterceptor implements RequestInterceptor {
|
private class CachingServiceRequestInterceptor implements RequestInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onStart(String requestId) {
|
public void onStart(String requestId) {
|
||||||
if (requestId != null) {
|
if (requestId != null) {
|
||||||
Map<String, MapCache> requestCaches = requestCachesMap.get(requestId);
|
Map<String, MapCache> requestCaches = requestCachesMap.get(requestId);
|
||||||
if (requestCaches == null) {
|
if (requestCaches == null) {
|
||||||
requestCaches = new HashMap<String, MapCache>();
|
requestCaches = new HashMap<>();
|
||||||
requestCachesMap.put(requestId, requestCaches);
|
requestCachesMap.put(requestId, requestCaches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onEnd(String requestId, boolean succeeded, Exception failure) {
|
public void onEnd(String requestId, boolean succeeded, Exception failure) {
|
||||||
if (requestId != null) {
|
if (requestId != null) {
|
||||||
requestCachesMap.remove(requestId);
|
requestCachesMap.remove(requestId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getOrder() {
|
public int getOrder() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.services.email;
|
package org.dspace.services.email;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
import javax.mail.Authenticator;
|
import javax.mail.Authenticator;
|
||||||
import javax.mail.PasswordAuthentication;
|
import javax.mail.PasswordAuthentication;
|
||||||
import javax.mail.Session;
|
import javax.mail.Session;
|
||||||
@@ -17,14 +18,12 @@ import javax.naming.NamingException;
|
|||||||
import javax.naming.NoInitialContextException;
|
import javax.naming.NoInitialContextException;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.kernel.mixins.InitializedService;
|
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.dspace.services.EmailService;
|
import org.dspace.services.EmailService;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Required;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides mail sending services through JavaMail. If a {@link javax.mail.Session}
|
* Provides mail sending services through JavaMail. If a {@link javax.mail.Session}
|
||||||
@@ -35,7 +34,7 @@ import org.springframework.beans.factory.annotation.Required;
|
|||||||
*/
|
*/
|
||||||
public class EmailServiceImpl
|
public class EmailServiceImpl
|
||||||
extends Authenticator
|
extends Authenticator
|
||||||
implements EmailService, InitializedService {
|
implements EmailService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(EmailServiceImpl.class);
|
private static final Logger logger = LoggerFactory.getLogger(EmailServiceImpl.class);
|
||||||
|
|
||||||
private Session session = null;
|
private Session session = null;
|
||||||
@@ -47,8 +46,7 @@ public class EmailServiceImpl
|
|||||||
*
|
*
|
||||||
* @param cfg the configurationService object
|
* @param cfg the configurationService object
|
||||||
*/
|
*/
|
||||||
@Autowired
|
@Autowired(required = true)
|
||||||
@Required
|
|
||||||
public void setCfg(ConfigurationService cfg) {
|
public void setCfg(ConfigurationService cfg) {
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
||||||
}
|
}
|
||||||
@@ -63,7 +61,7 @@ public class EmailServiceImpl
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
// See if there is already a Session in our environment
|
// See if there is already a Session in our environment
|
||||||
String sessionName = cfg.getProperty("mail.session.name");
|
String sessionName = cfg.getProperty("mail.session.name");
|
||||||
|
@@ -12,9 +12,9 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.dspace.kernel.mixins.ShutdownService;
|
|
||||||
import org.dspace.services.CachingService;
|
import org.dspace.services.CachingService;
|
||||||
import org.dspace.services.EventService;
|
import org.dspace.services.EventService;
|
||||||
import org.dspace.services.RequestService;
|
import org.dspace.services.RequestService;
|
||||||
@@ -36,7 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
*
|
*
|
||||||
* @author Aaron Zeckoski (azeckoski@gmail.com) - azeckoski - 4:02:31 PM Nov 19, 2008
|
* @author Aaron Zeckoski (azeckoski@gmail.com) - azeckoski - 4:02:31 PM Nov 19, 2008
|
||||||
*/
|
*/
|
||||||
public final class SystemEventService implements EventService, ShutdownService {
|
public final class SystemEventService implements EventService {
|
||||||
|
|
||||||
private final Logger log = LoggerFactory.getLogger(SystemEventService.class);
|
private final Logger log = LoggerFactory.getLogger(SystemEventService.class);
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
/**
|
/**
|
||||||
* Map for holding onto the listeners which is ClassLoader safe.
|
* Map for holding onto the listeners which is ClassLoader safe.
|
||||||
*/
|
*/
|
||||||
private Map<String, EventListener> listenersMap = new ConcurrentHashMap<String, EventListener>();
|
private final Map<String, EventListener> listenersMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final RequestService requestService;
|
private final RequestService requestService;
|
||||||
private final CachingService cachingService;
|
private final CachingService cachingService;
|
||||||
@@ -64,9 +64,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
this.requestService.registerRequestInterceptor(this.requestInterceptor);
|
this.requestService.registerRequestInterceptor(this.requestInterceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
@PreDestroy
|
||||||
* @see org.dspace.kernel.mixins.ShutdownService#shutdown()
|
|
||||||
*/
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
this.requestInterceptor = null; // clear the interceptor
|
this.requestInterceptor = null; // clear the interceptor
|
||||||
this.listenersMap.clear();
|
this.listenersMap.clear();
|
||||||
@@ -76,6 +74,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.EventService#fireEvent(org.dspace.services.model.Event)
|
* @see org.dspace.services.EventService#fireEvent(org.dspace.services.model.Event)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void fireEvent(Event event) {
|
public void fireEvent(Event event) {
|
||||||
validateEvent(event);
|
validateEvent(event);
|
||||||
// check scopes for this event
|
// check scopes for this event
|
||||||
@@ -97,6 +96,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.EventService#queueEvent(org.dspace.services.model.Event)
|
* @see org.dspace.services.EventService#queueEvent(org.dspace.services.model.Event)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void queueEvent(Event event) {
|
public void queueEvent(Event event) {
|
||||||
validateEvent(event);
|
validateEvent(event);
|
||||||
|
|
||||||
@@ -118,6 +118,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.EventService#registerEventListener(org.dspace.services.model.EventListener)
|
* @see org.dspace.services.EventService#registerEventListener(org.dspace.services.model.EventListener)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void registerEventListener(EventListener listener) {
|
public void registerEventListener(EventListener listener) {
|
||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
throw new IllegalArgumentException("Cannot register a listener that is null");
|
throw new IllegalArgumentException("Cannot register a listener that is null");
|
||||||
@@ -293,7 +294,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
return allowName && allowResource;
|
return allowName && allowResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Random random = new Random();
|
private final Random random = new Random();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate an event ID used to identify and track this event uniquely.
|
* Generate an event ID used to identify and track this event uniquely.
|
||||||
@@ -316,6 +317,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
* @see org.dspace.services.model.RequestInterceptor#onStart(java.lang.String, org.dspace.services.model
|
* @see org.dspace.services.model.RequestInterceptor#onStart(java.lang.String, org.dspace.services.model
|
||||||
* .Session)
|
* .Session)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onStart(String requestId) {
|
public void onStart(String requestId) {
|
||||||
// nothing to really do here unless we decide we should purge out any existing events? -AZ
|
// nothing to really do here unless we decide we should purge out any existing events? -AZ
|
||||||
}
|
}
|
||||||
@@ -324,6 +326,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
* @see org.dspace.services.model.RequestInterceptor#onEnd(java.lang.String, org.dspace.services.model
|
* @see org.dspace.services.model.RequestInterceptor#onEnd(java.lang.String, org.dspace.services.model
|
||||||
* .Session, boolean, java.lang.Exception)
|
* .Session, boolean, java.lang.Exception)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onEnd(String requestId, boolean succeeded, Exception failure) {
|
public void onEnd(String requestId, boolean succeeded, Exception failure) {
|
||||||
if (succeeded) {
|
if (succeeded) {
|
||||||
int fired = fireQueuedEvents();
|
int fired = fireQueuedEvents();
|
||||||
@@ -338,6 +341,7 @@ public final class SystemEventService implements EventService, ShutdownService {
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.OrderedService#getOrder()
|
* @see org.dspace.kernel.mixins.OrderedService#getOrder()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int getOrder() {
|
public int getOrder() {
|
||||||
return 20; // this should fire pretty late
|
return 20; // this should fire pretty late
|
||||||
}
|
}
|
||||||
|
@@ -15,12 +15,12 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.kernel.mixins.InitializedService;
|
|
||||||
import org.dspace.kernel.mixins.ShutdownService;
|
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.dspace.services.RequestService;
|
import org.dspace.services.RequestService;
|
||||||
import org.dspace.services.model.Request;
|
import org.dspace.services.model.Request;
|
||||||
@@ -32,7 +32,6 @@ import org.dspace.utils.servicemanager.OrderedServiceComparator;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Required;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,14 +44,13 @@ import org.springframework.beans.factory.annotation.Required;
|
|||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||||
* @author Tom Desair (tom dot desair at atmire dot com)
|
* @author Tom Desair (tom dot desair at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public final class StatelessRequestServiceImpl implements RequestService, InitializedService, ShutdownService {
|
public final class StatelessRequestServiceImpl implements RequestService {
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(StatelessRequestServiceImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(StatelessRequestServiceImpl.class);
|
||||||
|
|
||||||
private ConfigurationService configurationService;
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired(required = true)
|
||||||
@Required
|
|
||||||
public void setConfigurationService(ConfigurationService configurationService) {
|
public void setConfigurationService(ConfigurationService configurationService) {
|
||||||
this.configurationService = configurationService;
|
this.configurationService = configurationService;
|
||||||
}
|
}
|
||||||
@@ -60,18 +58,14 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
/**
|
/**
|
||||||
* map for holding onto the request interceptors which is classloader safe.
|
* map for holding onto the request interceptors which is classloader safe.
|
||||||
*/
|
*/
|
||||||
private Map<String, RequestInterceptor> interceptorsMap = new HashMap<String, RequestInterceptor>();
|
private final Map<String, RequestInterceptor> interceptorsMap = new HashMap<>();
|
||||||
|
|
||||||
/* (non-Javadoc)
|
@PostConstruct
|
||||||
* @see org.dspace.kernel.mixins.InitializedService#init()
|
|
||||||
*/
|
|
||||||
public void init() {
|
public void init() {
|
||||||
log.info("init");
|
log.info("init");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
@PreDestroy
|
||||||
* @see org.dspace.kernel.mixins.ShutdownService#shutdown()
|
|
||||||
*/
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
log.info("shutdown");
|
log.info("shutdown");
|
||||||
clear();
|
clear();
|
||||||
@@ -90,6 +84,7 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.RequestService#startRequest()
|
* @see org.dspace.services.RequestService#startRequest()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String startRequest() {
|
public String startRequest() {
|
||||||
return startRequest(new InternalRequestImpl());
|
return startRequest(new InternalRequestImpl());
|
||||||
}
|
}
|
||||||
@@ -97,6 +92,7 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.RequestService#startRequest()
|
* @see org.dspace.services.RequestService#startRequest()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String startRequest(ServletRequest request, ServletResponse response) {
|
public String startRequest(ServletRequest request, ServletResponse response) {
|
||||||
return startRequest(new HttpRequestImpl(request, response));
|
return startRequest(new HttpRequestImpl(request, response));
|
||||||
}
|
}
|
||||||
@@ -128,6 +124,7 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.RequestService#endRequest(java.lang.Exception)
|
* @see org.dspace.services.RequestService#endRequest(java.lang.Exception)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String endRequest(Exception failure) {
|
public String endRequest(Exception failure) {
|
||||||
String requestId = null;
|
String requestId = null;
|
||||||
try {
|
try {
|
||||||
@@ -175,7 +172,7 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
* @return the current list of interceptors in the correct order
|
* @return the current list of interceptors in the correct order
|
||||||
*/
|
*/
|
||||||
private List<RequestInterceptor> getInterceptors(boolean reverse) {
|
private List<RequestInterceptor> getInterceptors(boolean reverse) {
|
||||||
ArrayList<RequestInterceptor> l = new ArrayList<RequestInterceptor>(this.interceptorsMap.values());
|
ArrayList<RequestInterceptor> l = new ArrayList<>(this.interceptorsMap.values());
|
||||||
OrderedServiceComparator comparator = new OrderedServiceComparator();
|
OrderedServiceComparator comparator = new OrderedServiceComparator();
|
||||||
Collections.sort(l, comparator);
|
Collections.sort(l, comparator);
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
@@ -187,6 +184,7 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.RequestService#registerRequestListener(org.dspace.services.model.RequestInterceptor)
|
* @see org.dspace.services.RequestService#registerRequestListener(org.dspace.services.model.RequestInterceptor)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void registerRequestInterceptor(RequestInterceptor interceptor) {
|
public void registerRequestInterceptor(RequestInterceptor interceptor) {
|
||||||
if (interceptor == null) {
|
if (interceptor == null) {
|
||||||
throw new IllegalArgumentException("Cannot register an interceptor that is null");
|
throw new IllegalArgumentException("Cannot register an interceptor that is null");
|
||||||
@@ -198,11 +196,12 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
this.interceptorsMap.put(key, interceptor);
|
this.interceptorsMap.put(key, interceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see org.dspace.services.RequestService#getCurrentUserId()
|
* @see org.dspace.services.RequestService#getCurrentUserId()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getCurrentUserId() {
|
public String getCurrentUserId() {
|
||||||
Request currentRequest = getCurrentRequest();
|
Request currentRequest = getCurrentRequest();
|
||||||
if (currentRequest == null) {
|
if (currentRequest == null) {
|
||||||
@@ -212,11 +211,12 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see org.dspace.services.RequestService#setCurrentUserId()
|
* @see org.dspace.services.RequestService#setCurrentUserId()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void setCurrentUserId(UUID epersonId) {
|
public void setCurrentUserId(UUID epersonId) {
|
||||||
Request currentRequest = getCurrentRequest();
|
Request currentRequest = getCurrentRequest();
|
||||||
if (currentRequest != null) {
|
if (currentRequest != null) {
|
||||||
@@ -227,6 +227,7 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.RequestService#getCurrentRequestId()
|
* @see org.dspace.services.RequestService#getCurrentRequestId()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getCurrentRequestId() {
|
public String getCurrentRequestId() {
|
||||||
Request req = requests.getCurrent();
|
Request req = requests.getCurrent();
|
||||||
if (req != null) {
|
if (req != null) {
|
||||||
@@ -239,6 +240,7 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.services.RequestService#getCurrentRequest()
|
* @see org.dspace.services.RequestService#getCurrentRequest()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Request getCurrentRequest() {
|
public Request getCurrentRequest() {
|
||||||
return requests.getCurrent();
|
return requests.getCurrent();
|
||||||
}
|
}
|
||||||
@@ -247,7 +249,7 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
* Class to hold the current request. Uses Map keyed on current thread id.
|
* Class to hold the current request. Uses Map keyed on current thread id.
|
||||||
*/
|
*/
|
||||||
private class RequestHolder {
|
private class RequestHolder {
|
||||||
Map<Long, Request> requestMap = new ConcurrentHashMap<Long, Request>();
|
Map<Long, Request> requestMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
Request getCurrent() {
|
Request getCurrent() {
|
||||||
return requestMap.get(Thread.currentThread().getId());
|
return requestMap.get(Thread.currentThread().getId());
|
||||||
@@ -298,5 +300,5 @@ public final class StatelessRequestServiceImpl implements RequestService, Initia
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RequestHolder requests = new RequestHolder();
|
private final RequestHolder requests = new RequestHolder();
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,4 @@
|
|||||||
|
|
||||||
<context:annotation-config/> <!-- allows us to use spring annotations in beans -->
|
<context:annotation-config/> <!-- allows us to use spring annotations in beans -->
|
||||||
|
|
||||||
<!-- the bean processor interceptor -->
|
|
||||||
<bean class="org.dspace.servicemanager.spring.DSpaceBeanPostProcessor"/>
|
|
||||||
|
|
||||||
</beans>
|
</beans>
|
@@ -16,9 +16,9 @@ import static org.junit.Assert.fail;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import org.dspace.kernel.mixins.InitializedService;
|
|
||||||
import org.dspace.kernel.mixins.ShutdownService;
|
|
||||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||||
import org.dspace.servicemanager.example.ConcreteExample;
|
import org.dspace.servicemanager.example.ConcreteExample;
|
||||||
import org.dspace.servicemanager.fakeservices.FakeService1;
|
import org.dspace.servicemanager.fakeservices.FakeService1;
|
||||||
@@ -28,7 +28,7 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* testing the main dspace service manager
|
* Testing the main DSpace service manager.
|
||||||
*
|
*
|
||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||||
*/
|
*/
|
||||||
@@ -42,10 +42,6 @@ public class DSpaceServiceManagerTest {
|
|||||||
public void init() {
|
public void init() {
|
||||||
configurationService = new DSpaceConfigurationService();
|
configurationService = new DSpaceConfigurationService();
|
||||||
|
|
||||||
// Set some sample configurations relating to services/beans
|
|
||||||
configurationService.loadConfig(SampleAnnotationBean.class.getName() + ".sampleValue", "beckyz");
|
|
||||||
configurationService.loadConfig("fakeBean.fakeParam", "beckyz");
|
|
||||||
|
|
||||||
dsm = new DSpaceServiceManager(configurationService, SPRING_TEST_CONFIG_FILE);
|
dsm = new DSpaceServiceManager(configurationService, SPRING_TEST_CONFIG_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,16 +171,6 @@ public class DSpaceServiceManagerTest {
|
|||||||
ConcreteExample concrete = dsm.getServiceByName(ConcreteExample.class.getName(), ConcreteExample.class);
|
ConcreteExample concrete = dsm.getServiceByName(ConcreteExample.class.getName(), ConcreteExample.class);
|
||||||
assertNotNull(concrete);
|
assertNotNull(concrete);
|
||||||
assertEquals("azeckoski", concrete.getName());
|
assertEquals("azeckoski", concrete.getName());
|
||||||
concrete = null;
|
|
||||||
|
|
||||||
// initialize a SampleAnnotationBean
|
|
||||||
SampleAnnotationBean sab = dsm
|
|
||||||
.getServiceByName(SampleAnnotationBean.class.getName(), SampleAnnotationBean.class);
|
|
||||||
assertNotNull(sab);
|
|
||||||
// Based on the configuration for "sampleValue" in the init() method above,
|
|
||||||
// a value should be pre-set!
|
|
||||||
assertEquals("beckyz", sab.getSampleValue());
|
|
||||||
sab = null;
|
|
||||||
|
|
||||||
SpringAnnotationBean spr = dsm.getServiceByName(
|
SpringAnnotationBean spr = dsm.getServiceByName(
|
||||||
SpringAnnotationBean.class.getName(), SpringAnnotationBean.class);
|
SpringAnnotationBean.class.getName(), SpringAnnotationBean.class);
|
||||||
@@ -192,7 +178,6 @@ public class DSpaceServiceManagerTest {
|
|||||||
assertEquals("azeckoski", spr.getConcreteName());
|
assertEquals("azeckoski", spr.getConcreteName());
|
||||||
assertEquals("aaronz", spr.getExampleName());
|
assertEquals("aaronz", spr.getExampleName());
|
||||||
assertEquals(null, spr.getSampleValue());
|
assertEquals(null, spr.getSampleValue());
|
||||||
spr = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,25 +256,6 @@ public class DSpaceServiceManagerTest {
|
|||||||
// TODO need to do a better test here
|
// TODO need to do a better test here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInitAndShutdown() {
|
|
||||||
dsm.startup();
|
|
||||||
|
|
||||||
SampleAnnotationBean sab = dsm
|
|
||||||
.getServiceByName(SampleAnnotationBean.class.getName(), SampleAnnotationBean.class);
|
|
||||||
assertNotNull(sab);
|
|
||||||
assertEquals(1, sab.initCounter);
|
|
||||||
sab = null;
|
|
||||||
|
|
||||||
TestService ts = new TestService();
|
|
||||||
assertEquals(0, ts.value);
|
|
||||||
dsm.registerService(TestService.class.getName(), ts);
|
|
||||||
assertEquals(1, ts.value);
|
|
||||||
dsm.unregisterService(TestService.class.getName());
|
|
||||||
assertEquals(2, ts.value);
|
|
||||||
ts = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRegisterProviderLifecycle() {
|
public void testRegisterProviderLifecycle() {
|
||||||
dsm.startup();
|
dsm.startup();
|
||||||
@@ -321,16 +287,16 @@ public class DSpaceServiceManagerTest {
|
|||||||
properties = null;
|
properties = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TestService implements InitializedService, ShutdownService {
|
public static class TestService {
|
||||||
|
|
||||||
public int value = 0;
|
public int value = 0;
|
||||||
|
|
||||||
@Override
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
value++;
|
value++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@PreDestroy
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
value++;
|
value++;
|
||||||
}
|
}
|
||||||
|
@@ -7,44 +7,45 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.servicemanager;
|
package org.dspace.servicemanager;
|
||||||
|
|
||||||
import org.dspace.kernel.mixins.InitializedService;
|
import javax.annotation.PostConstruct;
|
||||||
import org.dspace.kernel.mixins.ShutdownService;
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import org.dspace.servicemanager.example.ConcreteExample;
|
import org.dspace.servicemanager.example.ConcreteExample;
|
||||||
import org.dspace.servicemanager.example.ServiceExample;
|
import org.dspace.servicemanager.example.ServiceExample;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Required;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This bean is a simple example of a bean which is annotated as a spring bean and should be found when the AC starts up
|
* This bean is a simple example of a bean which is annotated as a Spring Bean
|
||||||
|
* and should be found when the AC starts up.
|
||||||
*
|
*
|
||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class SampleAnnotationBean implements InitializedService, ShutdownService {
|
public class SampleAnnotationBean {
|
||||||
|
|
||||||
public int initCounter = 0;
|
public int initCounter = 0;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
initCounter++;
|
initCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
initCounter++;
|
initCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceExample serviceExample;
|
private ServiceExample serviceExample;
|
||||||
|
|
||||||
@Autowired
|
@Autowired(required = true)
|
||||||
@Required
|
|
||||||
public void setServiceExample(ServiceExample serviceExample) {
|
public void setServiceExample(ServiceExample serviceExample) {
|
||||||
this.serviceExample = serviceExample;
|
this.serviceExample = serviceExample;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConcreteExample concreteExample;
|
private ConcreteExample concreteExample;
|
||||||
|
|
||||||
@Autowired
|
@Autowired(required = true)
|
||||||
@Required
|
|
||||||
public void setConcreteExample(ConcreteExample concreteExample) {
|
public void setConcreteExample(ConcreteExample concreteExample) {
|
||||||
this.concreteExample = concreteExample;
|
this.concreteExample = concreteExample;
|
||||||
}
|
}
|
||||||
|
@@ -10,23 +10,23 @@ package org.dspace.servicemanager.fakeservices;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import org.dspace.kernel.mixins.ConfigChangeListener;
|
import org.dspace.kernel.mixins.ConfigChangeListener;
|
||||||
import org.dspace.kernel.mixins.InitializedService;
|
|
||||||
import org.dspace.kernel.mixins.ServiceChangeListener;
|
import org.dspace.kernel.mixins.ServiceChangeListener;
|
||||||
import org.dspace.kernel.mixins.ShutdownService;
|
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Required;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is just testing a fake service and running it through some paces to see if the lifecycles work
|
* This is just testing a fake service and running it through some paces to see
|
||||||
|
* if the lifecycles work.
|
||||||
*
|
*
|
||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||||
*/
|
*/
|
||||||
public class FakeService1 implements ConfigChangeListener, ServiceChangeListener,
|
public class FakeService1 implements ConfigChangeListener, ServiceChangeListener,
|
||||||
InitializedService, ShutdownService, Serializable {
|
Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public int triggers = 0;
|
public int triggers = 0;
|
||||||
@@ -56,8 +56,7 @@ public class FakeService1 implements ConfigChangeListener, ServiceChangeListener
|
|||||||
|
|
||||||
private ConfigurationService configurationService;
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired(required = true)
|
||||||
@Required
|
|
||||||
public void setConfigurationService(ConfigurationService configurationService) {
|
public void setConfigurationService(ConfigurationService configurationService) {
|
||||||
this.configurationService = configurationService;
|
this.configurationService = configurationService;
|
||||||
}
|
}
|
||||||
@@ -69,6 +68,7 @@ public class FakeService1 implements ConfigChangeListener, ServiceChangeListener
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.ConfigChangeListener#configurationChanged(java.util.List, java.util.Map)
|
* @see org.dspace.kernel.mixins.ConfigChangeListener#configurationChanged(java.util.List, java.util.Map)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void configurationChanged(List<String> changedSettingNames,
|
public void configurationChanged(List<String> changedSettingNames,
|
||||||
Map<String, String> changedSettings) {
|
Map<String, String> changedSettings) {
|
||||||
something = "config:" + changedSettings.get("azeckoski.FakeService1.something");
|
something = "config:" + changedSettings.get("azeckoski.FakeService1.something");
|
||||||
@@ -79,6 +79,7 @@ public class FakeService1 implements ConfigChangeListener, ServiceChangeListener
|
|||||||
* @see org.dspace.kernel.mixins.ServiceChangeListener#serviceRegistered(java.lang.String, java.lang.Object, java
|
* @see org.dspace.kernel.mixins.ServiceChangeListener#serviceRegistered(java.lang.String, java.lang.Object, java
|
||||||
* .util.List)
|
* .util.List)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void serviceRegistered(String serviceName, Object service,
|
public void serviceRegistered(String serviceName, Object service,
|
||||||
List<Class<?>> implementedTypes) {
|
List<Class<?>> implementedTypes) {
|
||||||
something = "registered:" + serviceName;
|
something = "registered:" + serviceName;
|
||||||
@@ -88,22 +89,19 @@ public class FakeService1 implements ConfigChangeListener, ServiceChangeListener
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.ServiceChangeListener#serviceUnregistered(java.lang.String, java.lang.Object)
|
* @see org.dspace.kernel.mixins.ServiceChangeListener#serviceUnregistered(java.lang.String, java.lang.Object)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void serviceUnregistered(String serviceName, Object service) {
|
public void serviceUnregistered(String serviceName, Object service) {
|
||||||
something = "unregistered:" + serviceName;
|
something = "unregistered:" + serviceName;
|
||||||
triggers++;
|
triggers++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
@PostConstruct
|
||||||
* @see org.dspace.kernel.mixins.InitializedService#init()
|
|
||||||
*/
|
|
||||||
public void init() {
|
public void init() {
|
||||||
something = "init";
|
something = "init";
|
||||||
triggers = 1; // RESET to 1
|
triggers = 1; // RESET to 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
@PreDestroy
|
||||||
* @see org.dspace.kernel.mixins.ShutdownService#shutdown()
|
|
||||||
*/
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
something = "shutdown";
|
something = "shutdown";
|
||||||
triggers++;
|
triggers++;
|
||||||
@@ -112,6 +110,7 @@ public class FakeService1 implements ConfigChangeListener, ServiceChangeListener
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.ConfigChangeListener#notifyForConfigNames()
|
* @see org.dspace.kernel.mixins.ConfigChangeListener#notifyForConfigNames()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String[] notifyForConfigNames() {
|
public String[] notifyForConfigNames() {
|
||||||
return null; // ALL
|
return null; // ALL
|
||||||
}
|
}
|
||||||
@@ -119,6 +118,7 @@ public class FakeService1 implements ConfigChangeListener, ServiceChangeListener
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.dspace.kernel.mixins.ServiceChangeListener#notifyForTypes()
|
* @see org.dspace.kernel.mixins.ServiceChangeListener#notifyForTypes()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Class<?>[] notifyForTypes() {
|
public Class<?>[] notifyForTypes() {
|
||||||
return null; // ALL
|
return null; // ALL
|
||||||
}
|
}
|
||||||
|
@@ -8,16 +8,14 @@
|
|||||||
package org.dspace.servicemanager.fakeservices;
|
package org.dspace.servicemanager.fakeservices;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
import org.dspace.kernel.mixins.InitializedService;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple fake service 2
|
* Simple fake service 2
|
||||||
*
|
*
|
||||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||||
*/
|
*/
|
||||||
public class FakeService2 implements InitializedService, Comparable<FakeService2>, Serializable {
|
public class FakeService2 implements Comparable<FakeService2>, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public String data = "data";
|
public String data = "data";
|
||||||
@@ -30,13 +28,12 @@ public class FakeService2 implements InitializedService, Comparable<FakeService2
|
|||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
@PostConstruct
|
||||||
* @see org.dspace.kernel.mixins.InitializedService#init()
|
|
||||||
*/
|
|
||||||
public void init() {
|
public void init() {
|
||||||
data = "initData";
|
data = "initData";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int compareTo(FakeService2 o) {
|
public int compareTo(FakeService2 o) {
|
||||||
return data.compareTo(o.data);
|
return data.compareTo(o.data);
|
||||||
}
|
}
|
||||||
|
@@ -2026,3 +2026,4 @@ include = ${module_dir}/translator.cfg
|
|||||||
include = ${module_dir}/usage-statistics.cfg
|
include = ${module_dir}/usage-statistics.cfg
|
||||||
include = ${module_dir}/versioning.cfg
|
include = ${module_dir}/versioning.cfg
|
||||||
include = ${module_dir}/workflow.cfg
|
include = ${module_dir}/workflow.cfg
|
||||||
|
include = ${module_dir}/irus-statistics.cfg
|
||||||
|
@@ -82,5 +82,7 @@
|
|||||||
<mapping class="org.dspace.xmlworkflow.storedcomponents.WorkflowItemRole"/>
|
<mapping class="org.dspace.xmlworkflow.storedcomponents.WorkflowItemRole"/>
|
||||||
<mapping class="org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem"/>
|
<mapping class="org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem"/>
|
||||||
|
|
||||||
|
<mapping class="org.dspace.statistics.export.OpenURLTracker"/>
|
||||||
|
|
||||||
</session-factory>
|
</session-factory>
|
||||||
</hibernate-configuration>
|
</hibernate-configuration>
|
||||||
|
@@ -187,6 +187,13 @@
|
|||||||
<class>org.dspace.administer.RegistryLoader</class>
|
<class>org.dspace.administer.RegistryLoader</class>
|
||||||
</step>
|
</step>
|
||||||
</command>
|
</command>
|
||||||
|
<command>
|
||||||
|
<name>retry-tracker</name>
|
||||||
|
<description>Retry all failed commits to the OpenURLTracker</description>
|
||||||
|
<step>
|
||||||
|
<class>org.dspace.statistics.export.RetryFailedOpenUrlTracker</class>
|
||||||
|
</step>
|
||||||
|
</command>
|
||||||
<command>
|
<command>
|
||||||
<name>solr-export-statistics</name>
|
<name>solr-export-statistics</name>
|
||||||
<description>Export usage statistics data from Solr for back-up purposes</description>
|
<description>Export usage statistics data from Solr for back-up purposes</description>
|
||||||
|
35
dspace/config/modules/irus-statistics.cfg
Normal file
35
dspace/config/modules/irus-statistics.cfg
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Enable the IRUS tracker. By default or when omitted, the tracker will be disabled
|
||||||
|
irus.statistics.tracker.enabled = false
|
||||||
|
|
||||||
|
# OPTIONAL metadata field used for filtering.
|
||||||
|
# If items with specific values for the "dc.type" field should be excluded, "dc.type" should be placed here.
|
||||||
|
# This should comply to the syntax schema.element.qualified or schema.element if the qualifier is null.
|
||||||
|
# irus.statistics.tracker.type-field = dc.type
|
||||||
|
# If "tracker.type-field" is set, the list of values must be defined in "tracker.type-value".
|
||||||
|
# This lists a comma separated list of values that will be excluded for the given field.
|
||||||
|
# irus.statistics.tracker.type-value = Article, Postprint
|
||||||
|
|
||||||
|
# This lists a comma separated list of entities that will be included
|
||||||
|
# When no list is provided, the default value "Publication" will be used
|
||||||
|
# irus.statistics.tracker.entity-types = Publication
|
||||||
|
|
||||||
|
# Set the tracker environment to "test" or "production". Defaults to "test" if empty.
|
||||||
|
# The URL used by the test environment can be configured in property tracker.testurl
|
||||||
|
# The URL used by the production environment can be configured in property tracker.produrl
|
||||||
|
irus.statistics.tracker.environment = test
|
||||||
|
# The url used to test the submission of tracking info to.
|
||||||
|
irus.statistics.tracker.testurl = https://irus.jisc.ac.uk/counter/test/
|
||||||
|
# The base url for submitting the tracking info to.
|
||||||
|
irus.statistics.tracker.produrl = https://irus.jisc.ac.uk/counter/
|
||||||
|
# Identifies data as OpenURL 1.0
|
||||||
|
irus.statistics.tracker.urlversion = Z39.88-2004
|
||||||
|
|
||||||
|
# Add the agentregex configuration below uncommented to local.cfg to include the bot agents list by
|
||||||
|
# Project COUNTER when filtering bots in DSpace. The agents file is downloaded by the Apache ant
|
||||||
|
# stage of the build process.
|
||||||
|
|
||||||
|
# Location of the COUNTER agents file
|
||||||
|
# irus.statistics.spider.agentregex.regexfile = ${dspace.dir}/config/spiders/agents/COUNTER_Robots_list.txt
|
||||||
|
|
||||||
|
# External URL to COUNTER the agents file
|
||||||
|
# irus.statistics.spider.agentregex.url = https://raw.githubusercontent.com/atmire/COUNTER-Robots/master/generated/COUNTER_Robots_list.txt
|
@@ -62,6 +62,7 @@
|
|||||||
<bean class="org.dspace.xmlworkflow.storedcomponents.dao.impl.PoolTaskDAOImpl"/>
|
<bean class="org.dspace.xmlworkflow.storedcomponents.dao.impl.PoolTaskDAOImpl"/>
|
||||||
<bean class="org.dspace.xmlworkflow.storedcomponents.dao.impl.WorkflowItemRoleDAOImpl"/>
|
<bean class="org.dspace.xmlworkflow.storedcomponents.dao.impl.WorkflowItemRoleDAOImpl"/>
|
||||||
<bean class="org.dspace.xmlworkflow.storedcomponents.dao.impl.XmlWorkflowItemDAOImpl"/>
|
<bean class="org.dspace.xmlworkflow.storedcomponents.dao.impl.XmlWorkflowItemDAOImpl"/>
|
||||||
|
<bean class="org.dspace.statistics.export.dao.impl.OpenURLTrackerDAOImpl"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -49,4 +49,6 @@
|
|||||||
|
|
||||||
<bean id="indexObjectFactoryFactory" class="org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactoryImpl"/>
|
<bean id="indexObjectFactoryFactory" class="org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactoryImpl"/>
|
||||||
|
|
||||||
|
<bean id="openURLTrackerLoggerServiceFactory" class="org.dspace.statistics.export.factory.OpenURLTrackerLoggerServiceFactoryImpl"/>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
10
dspace/config/spring/api/openurltracker.xml
Normal file
10
dspace/config/spring/api/openurltracker.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
|
||||||
|
default-lazy-init="true">
|
||||||
|
|
||||||
|
|
||||||
|
<bean class="org.dspace.statistics.export.FailedOpenURLTrackerServiceImpl"/>
|
||||||
|
<bean class="org.dspace.statistics.export.service.OpenUrlServiceImpl"/>
|
||||||
|
|
||||||
|
</beans>
|
@@ -18,6 +18,11 @@
|
|||||||
<property name="dspaceRunnableClass" value="org.dspace.app.bulkedit.MetadataExportCli"/>
|
<property name="dspaceRunnableClass" value="org.dspace.app.bulkedit.MetadataExportCli"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="retry-tracker" class="org.dspace.statistics.export.RetryFailedOpenUrlTrackerScriptConfiguration" scope="prototype">
|
||||||
|
<property name="description" value="Retry all failed commits to the OpenURLTracker"/>
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.statistics.export.RetryFailedOpenUrlTracker"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="curate" class="org.dspace.curate.CurationCliScriptConfiguration">
|
<bean id="curate" class="org.dspace.curate.CurationCliScriptConfiguration">
|
||||||
<property name="description" value="Curation tasks"/>
|
<property name="description" value="Curation tasks"/>
|
||||||
<property name="dspaceRunnableClass" value="org.dspace.curate.CurationCli"/>
|
<property name="dspaceRunnableClass" value="org.dspace.curate.CurationCli"/>
|
||||||
|
@@ -21,4 +21,9 @@
|
|||||||
<property name="eventService" ref="org.dspace.services.EventService"/>
|
<property name="eventService" ref="org.dspace.services.EventService"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- Irus statistics tracking -->
|
||||||
|
<bean class="org.dspace.statistics.export.IrusExportUsageEventListener">
|
||||||
|
<property name="eventService" ref="org.dspace.services.EventService"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
@@ -26,6 +26,40 @@
|
|||||||
<root.basedir>${basedir}/../../..</root.basedir>
|
<root.basedir>${basedir}/../../..</root.basedir>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
||||||
|
(see: https://groovy.github.io/gmaven/groovy-maven-plugin/execute.html )
|
||||||
|
We are generating a OS-agnostic version (agnostic.build.dir) of
|
||||||
|
the ${project.build.directory} property (full path of target dir).
|
||||||
|
This is needed by the Surefire & Failsafe plugins (see below)
|
||||||
|
to initialize the Unit Test environment's dspace.cfg file.
|
||||||
|
Otherwise, the Unit Test Framework will not work on Windows OS.
|
||||||
|
This Groovy code was mostly borrowed from:
|
||||||
|
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
||||||
|
-->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.gmaven</groupId>
|
||||||
|
<artifactId>groovy-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setproperty</id>
|
||||||
|
<phase>initialize</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>execute</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<source>
|
||||||
|
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
||||||
|
log.info("Initializing Maven property 'agnostic.build.dir' to: {}", project.properties['agnostic.build.dir']);
|
||||||
|
</source>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>oracle-support</id>
|
<id>oracle-support</id>
|
||||||
@@ -42,20 +76,20 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
<!-- If Unit Testing is enabled, then setup the Unit Test Environment.
|
|
||||||
See also the 'skiptests' profile in Parent POM. -->
|
<!-- Setup the Unit Test Environment (when -DskipUnitTests=false) -->
|
||||||
<profile>
|
<profile>
|
||||||
<id>test-environment</id>
|
<id>unit-test-environment</id>
|
||||||
<activation>
|
<activation>
|
||||||
<activeByDefault>false</activeByDefault>
|
<activeByDefault>false</activeByDefault>
|
||||||
<property>
|
<property>
|
||||||
<name>skipTests</name>
|
<name>skipUnitTests</name>
|
||||||
<value>false</value>
|
<value>false</value>
|
||||||
</property>
|
</property>
|
||||||
</activation>
|
</activation>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- Unit/Integration Testing setup: This plugin unzips the
|
<!-- Unit Testing setup: This plugin unzips the
|
||||||
'testEnvironment.zip' file (created by dspace-parent POM), into
|
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||||
the 'target/testing/' folder, to essentially create a test
|
the 'target/testing/' folder, to essentially create a test
|
||||||
install of DSpace, against which Tests can be run. -->
|
install of DSpace, against which Tests can be run. -->
|
||||||
@@ -75,50 +109,12 @@
|
|||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>setupTestEnvironment</id>
|
<id>setupUnitTestEnvironment</id>
|
||||||
<phase>generate-test-resources</phase>
|
<phase>generate-test-resources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>unpack</goal>
|
<goal>unpack</goal>
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
|
||||||
<id>setupIntegrationTestEnvironment</id>
|
|
||||||
<phase>pre-integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>unpack</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
|
||||||
(see: http://gmaven.codehaus.org/Executing+Groovy+Code )
|
|
||||||
We are generating a OS-agnostic version (agnostic.build.dir) of
|
|
||||||
the ${project.build.directory} property (full path of target dir).
|
|
||||||
This is needed by the FileWeaver & Surefire plugins (see below)
|
|
||||||
to initialize the Unit Test environment's dspace.cfg file.
|
|
||||||
Otherwise, the Unit Test Framework will not work on Windows OS.
|
|
||||||
This Groovy code was mostly borrowed from:
|
|
||||||
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
|
||||||
-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.gmaven</groupId>
|
|
||||||
<artifactId>groovy-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>setproperty</id>
|
|
||||||
<phase>generate-test-resources
|
|
||||||
</phase> <!-- XXX I think this should be 'initialize' - MHW -->
|
|
||||||
<goals>
|
|
||||||
<goal>execute</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<source>
|
|
||||||
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
|
||||||
println("Initializing Maven property 'agnostic.build.dir' to: " + project.properties['agnostic.build.dir']);
|
|
||||||
</source>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
@@ -136,6 +132,60 @@
|
|||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<!-- When running tests, also include test classes from dspace-api
|
||||||
|
(this test-jar is only built when tests are enabled). -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dspace</groupId>
|
||||||
|
<artifactId>dspace-api</artifactId>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<!-- Setup the Integration Test Environment (when -DskipIntegrationTests=false) -->
|
||||||
|
<profile>
|
||||||
|
<id>integration-test-environment</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
<property>
|
||||||
|
<name>skipIntegrationTests</name>
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Integration Testing setup: This plugin unzips the
|
||||||
|
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||||
|
the 'target/testing/' folder, to essentially create a test
|
||||||
|
install of DSpace, against which Tests can be run. -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/testing</outputDirectory>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.dspace</groupId>
|
||||||
|
<artifactId>dspace-parent</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<classifier>testEnvironment</classifier>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setupIntegrationTestEnvironment</id>
|
||||||
|
<phase>pre-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>unpack</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -163,6 +213,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
@@ -73,24 +73,52 @@ just adding new jar in the classloader</description>
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
||||||
|
(see: https://groovy.github.io/gmaven/groovy-maven-plugin/execute.html )
|
||||||
|
We are generating a OS-agnostic version (agnostic.build.dir) of
|
||||||
|
the ${project.build.directory} property (full path of target dir).
|
||||||
|
This is needed by the Surefire & Failsafe plugins (see below)
|
||||||
|
to initialize the Unit Test environment's dspace.cfg file.
|
||||||
|
Otherwise, the Unit Test Framework will not work on Windows OS.
|
||||||
|
This Groovy code was mostly borrowed from:
|
||||||
|
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
||||||
|
-->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.gmaven</groupId>
|
||||||
|
<artifactId>groovy-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setproperty</id>
|
||||||
|
<phase>initialize</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>execute</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<source>
|
||||||
|
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
||||||
|
log.info("Initializing Maven property 'agnostic.build.dir' to: {}", project.properties['agnostic.build.dir']);
|
||||||
|
</source>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<!-- If Unit Testing is enabled, then setup the Unit Test Environment.
|
<!-- Setup the Unit Test Environment (when -DskipUnitTests=false) -->
|
||||||
See also the 'skiptests' profile in Parent POM. -->
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>test-environment</id>
|
<id>unit-test-environment</id>
|
||||||
<activation>
|
<activation>
|
||||||
<activeByDefault>false</activeByDefault>
|
<activeByDefault>false</activeByDefault>
|
||||||
<property>
|
<property>
|
||||||
<name>skipTests</name>
|
<name>skipUnitTests</name>
|
||||||
<value>false</value>
|
<value>false</value>
|
||||||
</property>
|
</property>
|
||||||
</activation>
|
</activation>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- Unit/Integration Testing setup: This plugin unzips the
|
<!-- Unit Testing setup: This plugin unzips the
|
||||||
'testEnvironment.zip' file (created by dspace-parent POM), into
|
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||||
the 'target/testing/' folder, to essentially create a test
|
the 'target/testing/' folder, to essentially create a test
|
||||||
install of DSpace, against which Tests can be run. -->
|
install of DSpace, against which Tests can be run. -->
|
||||||
@@ -110,49 +138,12 @@ just adding new jar in the classloader</description>
|
|||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>setupTestEnvironment</id>
|
<id>setupUnitTestEnvironment</id>
|
||||||
<phase>generate-test-resources</phase>
|
<phase>generate-test-resources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>unpack</goal>
|
<goal>unpack</goal>
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
|
||||||
<id>setupIntegrationTestEnvironment</id>
|
|
||||||
<phase>pre-integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>unpack</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
|
||||||
(see: http://gmaven.codehaus.org/Executing+Groovy+Code )
|
|
||||||
We are generating a OS-agnostic version (agnostic.build.dir) of
|
|
||||||
the ${project.build.directory} property (full path of target dir).
|
|
||||||
This is needed by the FileWeaver & Surefire plugins (see below)
|
|
||||||
to initialize the Unit Test environment's dspace.cfg file.
|
|
||||||
Otherwise, the Unit Test Framework will not work on Windows OS.
|
|
||||||
This Groovy code was mostly borrowed from:
|
|
||||||
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
|
||||||
-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.gmaven</groupId>
|
|
||||||
<artifactId>groovy-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>setproperty</id>
|
|
||||||
<phase>initialize</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>execute</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<source>
|
|
||||||
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
|
||||||
log.info("Initializing Maven property 'agnostic.build.dir' to: {}", project.properties['agnostic.build.dir']);
|
|
||||||
</source>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
@@ -171,6 +162,60 @@ just adding new jar in the classloader</description>
|
|||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<!-- When running tests, also include test classes from dspace-server-webapp
|
||||||
|
(this test-jar is only built when tests are enabled). -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dspace</groupId>
|
||||||
|
<artifactId>dspace-server-webapp</artifactId>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<!-- Setup the Integration Test Environment (when -DskipIntegrationTests=false) -->
|
||||||
|
<profile>
|
||||||
|
<id>integration-test-environment</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
<property>
|
||||||
|
<name>skipIntegrationTests</name>
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Integration Testing setup: This plugin unzips the
|
||||||
|
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||||
|
the 'target/testing/' folder, to essentially create a test
|
||||||
|
install of DSpace, against which Tests can be run. -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/testing</outputDirectory>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.dspace</groupId>
|
||||||
|
<artifactId>dspace-parent</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<classifier>testEnvironment</classifier>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>setupIntegrationTestEnvironment</id>
|
||||||
|
<phase>pre-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>unpack</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -199,6 +244,7 @@ just adding new jar in the classloader</description>
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>oracle-support</id>
|
<id>oracle-support</id>
|
||||||
<activation>
|
<activation>
|
||||||
|
@@ -148,30 +148,28 @@
|
|||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<!-- Profile to aggregate (local) code coverage reports via JaCoCo
|
<!-- Profile to aggregate (local) code coverage reports created by JaCoCo (jacoco.org)
|
||||||
(jacoco.org) during the Unit and Integration testing process.
|
during the Unit and Integration testing processes.
|
||||||
This profile is only enabled when tests are (skipTests=false).
|
This plugin is disabled by default, as it is triggered by name in [src]/.travis.yml
|
||||||
See also jacoco-maven-plugin settings in Parent POM, as those
|
See also jacoco-maven-plugin settings in Parent POM, as those
|
||||||
settings generate the reports aggregated here. -->
|
settings generate the module-specific reports that are aggregated here. -->
|
||||||
<profile>
|
<profile>
|
||||||
<id>test-coverage-report</id>
|
<id>coverage-report</id>
|
||||||
<activation>
|
<activation>
|
||||||
<activeByDefault>false</activeByDefault>
|
<activeByDefault>false</activeByDefault>
|
||||||
<property>
|
|
||||||
<name>skipTests</name>
|
|
||||||
<value>false</value>
|
|
||||||
</property>
|
|
||||||
</activation>
|
</activation>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- Aggregate unit test code coverage reports -->
|
<!-- Aggregate all test code coverage reports from the individual module coverage reports
|
||||||
|
that are generated during unit & integration testing.
|
||||||
|
Results (HTML and XML) are written to ./target/site/jacoco-aggregate/ -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.jacoco</groupId>
|
<groupId>org.jacoco</groupId>
|
||||||
<artifactId>jacoco-maven-plugin</artifactId>
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>aggregate-test-report</id>
|
<id>aggregate-test-report</id>
|
||||||
<phase>post-integration-test</phase>
|
<phase>verify</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>report-aggregate</goal>
|
<goal>report-aggregate</goal>
|
||||||
</goals>
|
</goals>
|
||||||
@@ -182,8 +180,6 @@
|
|||||||
<dataFileInclude>**/jacoco-ut.exec</dataFileInclude>
|
<dataFileInclude>**/jacoco-ut.exec</dataFileInclude>
|
||||||
<dataFileInclude>**/jacoco-it.exec</dataFileInclude>
|
<dataFileInclude>**/jacoco-it.exec</dataFileInclude>
|
||||||
</dataFileIncludes>
|
</dataFileIncludes>
|
||||||
<!-- Sets the output directory for the code coverage report. -->
|
|
||||||
<outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregated</outputDirectory>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -231,50 +227,6 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<!-- Send coverage reports (generated by jacoco-maven-plugin) to coveralls.io. See 'test-coverage-report'
|
|
||||||
profile above for more details on aggregating of code coverage reports.
|
|
||||||
This plugin is disabled by default, as it is triggered by name in [src]/.travis.yml -->
|
|
||||||
<profile>
|
|
||||||
<id>coveralls</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
</activation>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.eluder.coveralls</groupId>
|
|
||||||
<artifactId>coveralls-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>report-test-coverage</id>
|
|
||||||
<phase>verify</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>report</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<failOnServiceError>false</failOnServiceError>
|
|
||||||
<jacocoReports>
|
|
||||||
<jacocoReport>${project.reporting.outputDirectory}/jacoco-aggregated/jacoco.xml</jacocoReport>
|
|
||||||
</jacocoReports>
|
|
||||||
<sourceDirectories>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-api/src/main/java</sourceDirectory>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-api/target/generated-sources/annotations</sourceDirectory>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-oai/src/main/java</sourceDirectory>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-rdf/src/main/java</sourceDirectory>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-rest/src/main/java</sourceDirectory>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-services/src/main/java</sourceDirectory>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-server-webapp/src/main/java</sourceDirectory>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-sword/src/main/java</sourceDirectory>
|
|
||||||
<sourceDirectory>${project.parent.basedir}/dspace-swordv2/src/main/java</sourceDirectory>
|
|
||||||
</sourceDirectories>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -114,6 +114,7 @@ Common usage:
|
|||||||
<echo message="update --> Update ${dspace.dir} config, etc, lib and web applications without " />
|
<echo message="update --> Update ${dspace.dir} config, etc, lib and web applications without " />
|
||||||
<echo message=" touching your data" />
|
<echo message=" touching your data" />
|
||||||
<echo message="update_configs --> Update your configs directory with new configuration files"/>
|
<echo message="update_configs --> Update your configs directory with new configuration files"/>
|
||||||
|
<echo message="update_spiders --> Dowload and install Spider Robots database into ${dspace.dir}/config" />
|
||||||
<echo message="update_code --> Update compiled code (bin, lib, and etc directories)" />
|
<echo message="update_code --> Update compiled code (bin, lib, and etc directories)" />
|
||||||
<echo message="update_webapps --> Update web applications" />
|
<echo message="update_webapps --> Update web applications" />
|
||||||
<echo message="" />
|
<echo message="" />
|
||||||
@@ -177,6 +178,7 @@ Common usage:
|
|||||||
<target name="update_configs"
|
<target name="update_configs"
|
||||||
depends="overwrite_configs,overwrite_solr_configs"
|
depends="overwrite_configs,overwrite_solr_configs"
|
||||||
description="Updates the Configuration Directory">
|
description="Updates the Configuration Directory">
|
||||||
|
<antcall target="init_spiders" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="overwrite_configs" description="Overwrites a configuration directory." if="${overwrite}" depends="copy_configs_keep">
|
<target name="overwrite_configs" description="Overwrites a configuration directory." if="${overwrite}" depends="copy_configs_keep">
|
||||||
@@ -827,6 +829,8 @@ Common usage:
|
|||||||
|
|
||||||
<antcall target="copy_webapps" />
|
<antcall target="copy_webapps" />
|
||||||
|
|
||||||
|
<antcall target="init_spiders" />
|
||||||
|
|
||||||
<echo>
|
<echo>
|
||||||
====================================================================
|
====================================================================
|
||||||
The DSpace code has been installed.
|
The DSpace code has been installed.
|
||||||
@@ -856,4 +860,27 @@ Common usage:
|
|||||||
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<!-- installs and/or updates Project Counter Robot List resolution database -->
|
||||||
|
<target name="update_spiders">
|
||||||
|
<echo>Downloading: ${irus.statistics.spider.agentregex.url}</echo>
|
||||||
|
<get src="${irus.statistics.spider.agentregex.url}" dest="${irus.statistics.spider.agentregex.regexfile}" verbose="true" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="check_spiders">
|
||||||
|
<condition property="need.spiders">
|
||||||
|
<and>
|
||||||
|
<not>
|
||||||
|
<available file="${irus.statistics.spider.agentregex.regexfile}" />
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<contains string="${irus.statistics.spider.agentregex.url}" substring="irus.statistics.spider.agentregex.url"/>
|
||||||
|
</not>
|
||||||
|
</and>
|
||||||
|
</condition>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="init_spiders" depends="check_spiders" if="need.spiders">
|
||||||
|
<antcall target="update_spiders" />
|
||||||
|
</target>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@@ -13,6 +13,6 @@ export const environment = {
|
|||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
port: 8080,
|
port: 8080,
|
||||||
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
|
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
|
||||||
nameSpace: '/server/api'
|
nameSpace: '/server'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user