diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2d638151f5..3926433b33 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -44,14 +44,14 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- id: changed-files
- uses: Alfresco/alfresco-build-tools/.github/actions/github-list-changes@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/github-list-changes@v8.13.0
with:
write-list-to-env: true
- - uses: Alfresco/alfresco-build-tools/.github/actions/pre-commit@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/pre-commit@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Prepare maven cache and check compilation"
@@ -69,12 +69,12 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- - uses: Alfresco/alfresco-build-tools/.github/actions/veracode@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/veracode@v8.13.0
continue-on-error: true
with:
srcclr-api-token: ${{ secrets.SRCCLR_API_TOKEN }}
@@ -92,10 +92,10 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/github-download-file@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/github-download-file@v8.13.0
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
repository: "Alfresco/veracode-baseline-archive"
@@ -148,9 +148,9 @@ jobs:
!contains(github.event.head_commit.message, '[skip tests]') &&
!contains(github.event.head_commit.message, '[force]')
steps:
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- uses: Alfresco/ya-pmd-scan@v4.1.0
with:
classpath-build-command: "mvn test-compile -ntp -Pags -pl \"-:alfresco-community-repo-docker\""
@@ -181,14 +181,14 @@ jobs:
testAttributes: "-Dtest=AllMmtUnitTestSuite"
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testModule }}
@@ -219,7 +219,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -261,9 +261,9 @@ jobs:
REQUIRES_INSTALLED_ARTIFACTS: true
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
@@ -276,7 +276,7 @@ jobs:
run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile ${{ matrix.compose-profile }} up -d
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testSuite }}
@@ -307,7 +307,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -340,9 +340,9 @@ jobs:
version: ['10.5', '10.6']
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: Run MariaDB ${{ matrix.version }} database
@@ -351,7 +351,7 @@ jobs:
MARIADB_VERSION: ${{ matrix.version }}
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.version }}
@@ -382,7 +382,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -411,9 +411,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run MariaDB 10.11 database"
@@ -422,7 +422,7 @@ jobs:
MARIADB_VERSION: 10.11
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
@@ -453,7 +453,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -482,9 +482,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run MySQL 8 database"
@@ -493,7 +493,7 @@ jobs:
MYSQL_VERSION: 8
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
@@ -515,7 +515,7 @@ jobs:
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
- mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=com.mysql.jdbc.Driver -Ddb.name=alfresco -Ddb.url=jdbc:mysql://localhost:3307/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}"
+ mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=com.mysql.cj.jdbc.Driver -Ddb.name=alfresco -Ddb.url=jdbc:mysql://localhost:3307/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
@@ -524,7 +524,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -552,9 +552,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run PostgreSQL 14.15 database"
@@ -563,7 +563,7 @@ jobs:
POSTGRES_VERSION: 14.15
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
@@ -594,7 +594,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -622,9 +622,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run PostgreSQL 15.10 database"
@@ -633,7 +633,7 @@ jobs:
POSTGRES_VERSION: 15.10
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
@@ -664,7 +664,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -692,9 +692,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run PostgreSQL 16.6 database"
@@ -703,7 +703,7 @@ jobs:
POSTGRES_VERSION: 16.6
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
@@ -734,7 +734,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -760,16 +760,16 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run ActiveMQ"
run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile activemq up -d
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
@@ -800,7 +800,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -860,9 +860,9 @@ jobs:
mvn-options: '-Dencryption.ssl.keystore.location=${CI_WORKSPACE}/keystores/alfresco/alfresco.keystore -Dencryption.ssl.truststore.location=${CI_WORKSPACE}/keystores/alfresco/alfresco.truststore'
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Set transformers tag"
@@ -885,7 +885,7 @@ jobs:
run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile ${{ matrix.compose-profile }} up -d
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testSuite }} ${{ matrix.idp }}
@@ -916,7 +916,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -974,9 +974,9 @@ jobs:
REQUIRES_LOCAL_IMAGES: true
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
@@ -992,7 +992,7 @@ jobs:
run: mvn install -pl :alfresco-community-repo-integration-test -am -DskipTests -Pall-tas-tests
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.test-name }}
@@ -1030,7 +1030,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.tests.outcome }}
@@ -1056,16 +1056,16 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run Postgres 16.6 database"
run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile postgres up -d
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
@@ -1096,7 +1096,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -1130,9 +1130,9 @@ jobs:
REQUIRES_INSTALLED_ARTIFACTS: true
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
@@ -1140,7 +1140,7 @@ jobs:
bash ./scripts/ci/build.sh
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} 0${{ matrix.part }} - (PostgreSQL) ${{ matrix.test-name }}
@@ -1176,9 +1176,9 @@ jobs:
REQUIRES_INSTALLED_ARTIFACTS: true
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
@@ -1186,7 +1186,7 @@ jobs:
bash ./scripts/ci/build.sh
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} 0${{ matrix.part }} - (MySQL) ${{ matrix.test-name }}
@@ -1218,9 +1218,9 @@ jobs:
REQUIRES_LOCAL_IMAGES: true
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
@@ -1234,7 +1234,7 @@ jobs:
mvn -B install -pl :alfresco-governance-services-automation-community-rest-api -am -Pags -Pall-tas-tests -DskipTests
- name: "Prepare Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.13.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
@@ -1266,7 +1266,7 @@ jobs:
continue-on-error: true
- name: "Summarize Report Portal"
if: github.ref_name == 'master'
- uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.2.0
+ uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.13.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
@@ -1308,9 +1308,9 @@ jobs:
!contains(github.event.head_commit.message, '[force]')
steps:
- uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
diff --git a/.github/workflows/master_release.yml b/.github/workflows/master_release.yml
index 35f15f9646..89d60e46eb 100644
--- a/.github/workflows/master_release.yml
+++ b/.github/workflows/master_release.yml
@@ -34,12 +34,12 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.13.0
with:
username: ${{ env.GIT_USERNAME }}
email: ${{ env.GIT_EMAIL }}
@@ -63,12 +63,12 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.13.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.13.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.2.0
+ - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.13.0
with:
username: ${{ env.GIT_USERNAME }}
email: ${{ env.GIT_EMAIL }}
diff --git a/.secrets.baseline b/.secrets.baseline
index 0b3be8cdb8..b160381264 100644
--- a/.secrets.baseline
+++ b/.secrets.baseline
@@ -1377,7 +1377,7 @@
"filename": "repository/src/test/java/org/alfresco/repo/imap/ImapMessageTest.java",
"hashed_secret": "d033e22ae348aeb5660fc2140aec35850c4da997",
"is_verified": false,
- "line_number": 118,
+ "line_number": 116,
"is_secret": false
}
],
@@ -1431,26 +1431,6 @@
"is_secret": false
}
],
- "repository/src/test/java/org/alfresco/repo/lock/LockBehaviourImplTest.java": [
- {
- "type": "Secret Keyword",
- "filename": "repository/src/test/java/org/alfresco/repo/lock/LockBehaviourImplTest.java",
- "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
- "is_verified": false,
- "line_number": 112,
- "is_secret": false
- }
- ],
- "repository/src/test/java/org/alfresco/repo/lock/LockServiceImplTest.java": [
- {
- "type": "Secret Keyword",
- "filename": "repository/src/test/java/org/alfresco/repo/lock/LockServiceImplTest.java",
- "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
- "is_verified": false,
- "line_number": 103,
- "is_secret": false
- }
- ],
"repository/src/test/java/org/alfresco/repo/management/JmxDumpUtilTest.java": [
{
"type": "Secret Keyword",
@@ -1888,5 +1868,5 @@
}
]
},
- "generated_at": "2024-12-19T08:58:42Z"
+ "generated_at": "2025-02-26T15:13:52Z"
}
diff --git a/amps/ags/pom.xml b/amps/ags/pom.xml
index 5c7216b7f6..141fd41d81 100644
--- a/amps/ags/pom.xml
+++ b/amps/ags/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo-amps
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/amps/ags/rm-automation/pom.xml b/amps/ags/rm-automation/pom.xml
index 100fb43c0c..090c1b8bba 100644
--- a/amps/ags/rm-automation/pom.xml
+++ b/amps/ags/rm-automation/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-governance-services-community-parent
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml b/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
index d4410c3126..691fae9704 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-governance-services-automation-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/amps/ags/rm-community/pom.xml b/amps/ags/rm-community/pom.xml
index d6e104d886..2a8e19f5fa 100644
--- a/amps/ags/rm-community/pom.xml
+++ b/amps/ags/rm-community/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-governance-services-community-parent
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/amps/ags/rm-community/rm-community-repo/pom.xml b/amps/ags/rm-community/rm-community-repo/pom.xml
index 21dbe38f08..e33e379e04 100644
--- a/amps/ags/rm-community/rm-community-repo/pom.xml
+++ b/amps/ags/rm-community/rm-community-repo/pom.xml
@@ -8,7 +8,7 @@
org.alfresco
alfresco-governance-services-community-repo-parent
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/amps/ags/rm-community/rm-community-rest-api-explorer/pom.xml b/amps/ags/rm-community/rm-community-rest-api-explorer/pom.xml
index 82fc4b38e9..730e9a42e7 100644
--- a/amps/ags/rm-community/rm-community-rest-api-explorer/pom.xml
+++ b/amps/ags/rm-community/rm-community-rest-api-explorer/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-governance-services-community-repo-parent
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/amps/pom.xml b/amps/pom.xml
index f1fcad5202..8f58fe3618 100644
--- a/amps/pom.xml
+++ b/amps/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/amps/share-services/pom.xml b/amps/share-services/pom.xml
index 6f64654e87..4c5441cbcb 100644
--- a/amps/share-services/pom.xml
+++ b/amps/share-services/pom.xml
@@ -8,7 +8,7 @@
org.alfresco
alfresco-community-repo-amps
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/core/pom.xml b/core/pom.xml
index e78fda0676..2c6fd6bddb 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
@@ -145,6 +145,12 @@
org.apache.httpcomponents
httpclient
+
+ org.awaitility
+ awaitility
+ ${dependency.awaitility.version}
+ test
+
diff --git a/core/src/test/java/org/alfresco/util/DynamicallySizedThreadPoolExecutorTest.java b/core/src/test/java/org/alfresco/util/DynamicallySizedThreadPoolExecutorTest.java
index c5ace65cdf..07cc1e3b4e 100644
--- a/core/src/test/java/org/alfresco/util/DynamicallySizedThreadPoolExecutorTest.java
+++ b/core/src/test/java/org/alfresco/util/DynamicallySizedThreadPoolExecutorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2014 Alfresco Software Limited.
+ * Copyright (C) 2005-2025 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -18,6 +18,9 @@
*/
package org.alfresco.util;
+import static org.awaitility.Awaitility.await;
+
+import java.time.Duration;
import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
@@ -26,20 +29,20 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import junit.framework.TestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import junit.framework.TestCase;
-
/**
* Tests for our instance of {@link java.util.concurrent.ThreadPoolExecutor}
- *
+ *
* @author Nick Burch
*/
public class DynamicallySizedThreadPoolExecutorTest extends TestCase
{
- private static Log logger = LogFactory.getLog(DynamicallySizedThreadPoolExecutorTest.class);
+ private static final Duration MAX_WAIT_TIMEOUT = Duration.ofSeconds(1);
+ private static final Log logger = LogFactory.getLog(DynamicallySizedThreadPoolExecutorTest.class);
private static final int DEFAULT_KEEP_ALIVE_TIME = 90;
@Override
@@ -48,9 +51,9 @@ public class DynamicallySizedThreadPoolExecutorTest extends TestCase
SleepUntilAllWake.reset();
}
- public void testUpToCore() throws Exception
+ public void testUpToCore()
{
- DynamicallySizedThreadPoolExecutor exec = createInstance(5,10, DEFAULT_KEEP_ALIVE_TIME);
+ DynamicallySizedThreadPoolExecutor exec = createInstance(5, 10, DEFAULT_KEEP_ALIVE_TIME);
assertEquals(0, exec.getPoolSize());
exec.execute(new SleepUntilAllWake());
@@ -61,15 +64,15 @@ public class DynamicallySizedThreadPoolExecutorTest extends TestCase
assertEquals(4, exec.getPoolSize());
exec.execute(new SleepUntilAllWake());
assertEquals(5, exec.getPoolSize());
-
+
SleepUntilAllWake.wakeAll();
- Thread.sleep(100);
+ waitForPoolSizeEquals(exec, 5);
assertEquals(5, exec.getPoolSize());
}
- public void testPastCoreButNotHugeQueue() throws Exception
+ public void testPastCoreButNotHugeQueue()
{
- DynamicallySizedThreadPoolExecutor exec = createInstance(5,10, DEFAULT_KEEP_ALIVE_TIME);
+ DynamicallySizedThreadPoolExecutor exec = createInstance(5, 10, DEFAULT_KEEP_ALIVE_TIME);
assertEquals(0, exec.getPoolSize());
assertEquals(0, exec.getQueue().size());
@@ -80,7 +83,7 @@ public class DynamicallySizedThreadPoolExecutorTest extends TestCase
exec.execute(new SleepUntilAllWake());
assertEquals(5, exec.getPoolSize());
assertEquals(0, exec.getQueue().size());
-
+
// Need to hit max pool size before it adds more
exec.execute(new SleepUntilAllWake());
exec.execute(new SleepUntilAllWake());
@@ -89,20 +92,20 @@ public class DynamicallySizedThreadPoolExecutorTest extends TestCase
exec.execute(new SleepUntilAllWake());
assertEquals(5, exec.getPoolSize());
assertEquals(5, exec.getQueue().size());
-
+
exec.execute(new SleepUntilAllWake());
exec.execute(new SleepUntilAllWake());
assertEquals(5, exec.getPoolSize());
assertEquals(7, exec.getQueue().size());
-
+
SleepUntilAllWake.wakeAll();
- Thread.sleep(100);
+ waitForPoolSizeEquals(exec, 5);
assertEquals(5, exec.getPoolSize());
}
-
+
public void testToExpandQueue() throws Exception
{
- DynamicallySizedThreadPoolExecutor exec = createInstance(2,4,1);
+ DynamicallySizedThreadPoolExecutor exec = createInstance(2, 4, 5);
assertEquals(0, exec.getPoolSize());
assertEquals(0, exec.getQueue().size());
@@ -110,166 +113,37 @@ public class DynamicallySizedThreadPoolExecutorTest extends TestCase
exec.execute(new SleepUntilAllWake());
assertEquals(2, exec.getPoolSize());
assertEquals(0, exec.getQueue().size());
-
+
exec.execute(new SleepUntilAllWake());
exec.execute(new SleepUntilAllWake());
exec.execute(new SleepUntilAllWake());
assertEquals(2, exec.getPoolSize());
assertEquals(3, exec.getQueue().size());
-
+
// Next should add one
exec.execute(new SleepUntilAllWake());
- Thread.sleep(20); // Let the new thread spin up
+ waitForPoolSizeEquals(exec, 3); // Let the new thread spin up
assertEquals(3, exec.getPoolSize());
assertEquals(3, exec.getQueue().size());
// And again
exec.execute(new SleepUntilAllWake());
- Thread.sleep(20); // Let the new thread spin up
+ waitForPoolSizeEquals(exec, 4); // Let the new thread spin up
assertEquals(4, exec.getPoolSize());
assertEquals(3, exec.getQueue().size());
-
+
// But no more will be added, as we're at max
exec.execute(new SleepUntilAllWake());
exec.execute(new SleepUntilAllWake());
exec.execute(new SleepUntilAllWake());
assertEquals(4, exec.getPoolSize());
assertEquals(6, exec.getQueue().size());
-
- SleepUntilAllWake.wakeAll();
- Thread.sleep(100);
-
- // All threads still running, as 1 second timeout
- assertEquals(4, exec.getPoolSize());
- }
- public void offTestToExpandThenContract() throws Exception
- {
- DynamicallySizedThreadPoolExecutor exec = createInstance(2,4,1);
- exec.setKeepAliveTime(30, TimeUnit.MILLISECONDS);
-
- assertEquals(0, exec.getPoolSize());
- assertEquals(0, exec.getQueue().size());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- assertEquals(2, exec.getPoolSize());
- assertEquals(0, exec.getQueue().size());
-
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- assertEquals(2, exec.getPoolSize());
- assertEquals(3, exec.getQueue().size());
-
- // Next should add one
- exec.execute(new SleepUntilAllWake());
- Thread.sleep(20); // Let the new thread spin up
- assertEquals(3, exec.getPoolSize());
- assertEquals(3, exec.getQueue().size());
+ SleepUntilAllWake.wakeAll();
+ Thread.sleep(100);
- // And again
- exec.execute(new SleepUntilAllWake());
- Thread.sleep(20); // Let the new thread spin up
+ // All threads still running, as 5 second timeout
assertEquals(4, exec.getPoolSize());
- assertEquals(3, exec.getQueue().size());
-
- // But no more will be added, as we're at max
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- assertEquals(4, exec.getPoolSize());
- assertEquals(6, exec.getQueue().size());
-
- SleepUntilAllWake.wakeAll();
- Thread.sleep(100);
-
- // Wait longer than the timeout without any work, which should
- // let all the extra threads go away
- // (Depending on how closely your JVM follows the specification,
- // we may fall back to the core size which is correct, or we
- // may go to zero which is wrong, but hey, it's the JVM...)
- logger.debug("Core pool size is " + exec.getCorePoolSize());
- logger.debug("Current pool size is " + exec.getPoolSize());
- logger.debug("Queue size is " + exec.getQueue().size());
- assertTrue(
- "Pool size should be 0-2 as everything is idle, was " + exec.getPoolSize(),
- exec.getPoolSize() >= 0
- );
- assertTrue(
- "Pool size should be 0-2 as everything is idle, was " + exec.getPoolSize(),
- exec.getPoolSize() <= 2
- );
-
- SleepUntilAllWake.reset();
-
- // Add 2 new jobs, will stay/ go to at 2 threads
- assertEquals(0, exec.getQueue().size());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
-
- // Let the idle threads grab them, then check
- Thread.sleep(20);
- assertEquals(2, exec.getPoolSize());
- assertEquals(0, exec.getQueue().size());
-
- // 3 more, still at 2 threads
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- assertEquals(2, exec.getPoolSize());
- assertEquals(3, exec.getQueue().size());
-
- // And again wait for it all
- SleepUntilAllWake.wakeAll();
- Thread.sleep(100);
- assertEquals(2, exec.getPoolSize());
-
-
- // Now decrease the overall pool size
- // Will rise and fall to there now
- exec.setCorePoolSize(1);
-
- // Run a quick job, to ensure that the
- // "can I kill one yet" logic is applied
- SleepUntilAllWake.reset();
- exec.execute(new SleepUntilAllWake());
- SleepUntilAllWake.wakeAll();
-
- Thread.sleep(100);
- assertEquals(1, exec.getPoolSize());
- assertEquals(0, exec.getQueue().size());
-
- SleepUntilAllWake.reset();
-
-
- // Push enough on to go up to 4 active threads
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
- exec.execute(new SleepUntilAllWake());
-
- Thread.sleep(20); // Let the new threads spin up
- assertEquals(4, exec.getPoolSize());
- assertEquals(6, exec.getQueue().size());
-
- // Wait for them all to finish, should drop back to 1 now
- // (Or zero, if your JVM can't read the specification...)
- SleepUntilAllWake.wakeAll();
- Thread.sleep(100);
- assertTrue(
- "Pool size should be 0 or 1 as everything is idle, was " + exec.getPoolSize(),
- exec.getPoolSize() >= 0
- );
- assertTrue(
- "Pool size should be 0 or 1 as everything is idle, was " + exec.getPoolSize(),
- exec.getPoolSize() <= 1
- );
}
private DynamicallySizedThreadPoolExecutor createInstance(int corePoolSize, int maximumPoolSize, int keepAliveTime)
@@ -291,6 +165,11 @@ public class DynamicallySizedThreadPoolExecutorTest extends TestCase
new ThreadPoolExecutor.CallerRunsPolicy());
}
+ private void waitForPoolSizeEquals(DynamicallySizedThreadPoolExecutor exec, int expectedSize)
+ {
+ await().atMost(MAX_WAIT_TIMEOUT).until(() -> exec.getPoolSize() == expectedSize);
+ }
+
public static class SleepUntilAllWake implements Runnable
{
private static ConcurrentMap sleeping = new ConcurrentHashMap();
@@ -299,31 +178,33 @@ public class DynamicallySizedThreadPoolExecutorTest extends TestCase
@Override
public void run()
{
- if(allAwake) return;
-
+ if (allAwake)
+ return;
+
// Track us, and wait for the bang
logger.debug("Adding thread: " + Thread.currentThread().getName());
sleeping.put(Thread.currentThread().getName(), Thread.currentThread());
try
{
- Thread.sleep(30*1000);
+ Thread.sleep(30 * 1000);
System.err.println("Warning - Thread finished sleeping without wake!");
}
- catch(InterruptedException e)
+ catch (InterruptedException e)
{
logger.debug("Interrupted thread: " + Thread.currentThread().getName());
}
}
-
+
public static void wakeAll()
{
allAwake = true;
- for(Entry t : sleeping.entrySet())
+ for (Entry t : sleeping.entrySet())
{
logger.debug("Interrupting thread: " + t.getKey());
t.getValue().interrupt();
}
}
+
public static void reset()
{
logger.debug("Resetting.");
diff --git a/core/src/test/java/org/alfresco/util/transaction/SpringAwareUserTransactionTest.java b/core/src/test/java/org/alfresco/util/transaction/SpringAwareUserTransactionTest.java
index 00855942f8..be3c08ba23 100644
--- a/core/src/test/java/org/alfresco/util/transaction/SpringAwareUserTransactionTest.java
+++ b/core/src/test/java/org/alfresco/util/transaction/SpringAwareUserTransactionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2023 Alfresco Software Limited.
+ * Copyright (C) 2005-2025 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -20,13 +20,11 @@ package org.alfresco.util.transaction;
import java.util.NoSuchElementException;
import java.util.Objects;
-
import jakarta.transaction.RollbackException;
import jakarta.transaction.Status;
import jakarta.transaction.UserTransaction;
import junit.framework.TestCase;
-
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.NoTransactionException;
import org.springframework.transaction.TransactionDefinition;
@@ -35,21 +33,20 @@ import org.springframework.transaction.support.AbstractPlatformTransactionManage
import org.springframework.transaction.support.DefaultTransactionStatus;
/**
- * @see org.alfresco.util.transaction.SpringAwareUserTransaction
- *
* @author Derek Hulley
+ * @see org.alfresco.util.transaction.SpringAwareUserTransaction
*/
public class SpringAwareUserTransactionTest extends TestCase
{
private DummyTransactionManager transactionManager;
private FailingTransactionManager failingTransactionManager;
private UserTransaction txn;
-
+
public SpringAwareUserTransactionTest()
{
super();
}
-
+
@Override
protected void setUp() throws Exception
{
@@ -57,7 +54,7 @@ public class SpringAwareUserTransactionTest extends TestCase
failingTransactionManager = new FailingTransactionManager();
txn = getTxn();
}
-
+
private UserTransaction getTxn()
{
return new SpringAwareUserTransaction(
@@ -67,13 +64,13 @@ public class SpringAwareUserTransactionTest extends TestCase
TransactionDefinition.PROPAGATION_REQUIRED,
TransactionDefinition.TIMEOUT_DEFAULT);
}
-
+
public void testSetUp() throws Exception
{
assertNotNull(transactionManager);
assertNotNull(txn);
}
-
+
private void checkNoStatusOnThread()
{
try
@@ -86,7 +83,7 @@ public class SpringAwareUserTransactionTest extends TestCase
// expected
}
}
-
+
public void testNoTxnStatus() throws Exception
{
checkNoStatusOnThread();
@@ -134,7 +131,7 @@ public class SpringAwareUserTransactionTest extends TestCase
}
checkNoStatusOnThread();
}
-
+
public void testSimpleTxnWithRollback() throws Exception
{
testNoTxnStatus();
@@ -156,7 +153,7 @@ public class SpringAwareUserTransactionTest extends TestCase
transactionManager.getStatus());
checkNoStatusOnThread();
}
-
+
public void testNoBeginCommit() throws Exception
{
testNoTxnStatus();
@@ -171,7 +168,7 @@ public class SpringAwareUserTransactionTest extends TestCase
}
checkNoStatusOnThread();
}
-
+
public void testPostRollbackCommitDetection() throws Exception
{
testNoTxnStatus();
@@ -189,7 +186,7 @@ public class SpringAwareUserTransactionTest extends TestCase
}
checkNoStatusOnThread();
}
-
+
public void testPostSetRollbackOnlyCommitDetection() throws Exception
{
testNoTxnStatus();
@@ -208,7 +205,7 @@ public class SpringAwareUserTransactionTest extends TestCase
}
checkNoStatusOnThread();
}
-
+
public void testMismatchedBeginCommit() throws Exception
{
UserTransaction txn1 = getTxn();
@@ -218,18 +215,18 @@ public class SpringAwareUserTransactionTest extends TestCase
txn1.begin();
txn2.begin();
-
+
txn2.commit();
txn1.commit();
-
+
checkNoStatusOnThread();
-
+
txn1 = getTxn();
txn2 = getTxn();
-
+
txn1.begin();
txn2.begin();
-
+
try
{
txn1.commit();
@@ -245,58 +242,6 @@ public class SpringAwareUserTransactionTest extends TestCase
checkNoStatusOnThread();
}
- /**
- * Test for leaked transactions (no guarantee it will succeed due to reliance
- * on garbage collector), so disabled by default.
- *
- * Also, if it succeeds, transaction call stack tracing will be enabled
- * potentially hitting the performance of all subsequent tests.
- *
- * @throws Exception
- */
- public void xtestLeakedTransactionLogging() throws Exception
- {
- assertFalse(SpringAwareUserTransaction.isCallStackTraced());
-
- TrxThread t1 = new TrxThread();
- t1.start();
- System.gc();
- Thread.sleep(1000);
-
- TrxThread t2 = new TrxThread();
- t2.start();
- System.gc();
- Thread.sleep(1000);
-
- assertTrue(SpringAwareUserTransaction.isCallStackTraced());
-
- TrxThread t3 = new TrxThread();
- t3.start();
- System.gc();
- Thread.sleep(3000);
- System.gc();
- Thread.sleep(3000);
- }
-
- private class TrxThread extends Thread
- {
- public void run()
- {
- try
- {
- getTrx();
- }
- catch (Exception e) {}
- }
-
- public void getTrx() throws Exception
- {
- UserTransaction txn = getTxn();
- txn.begin();
- txn = null;
- }
- }
-
public void testConnectionPoolException() throws Exception
{
testNoTxnStatus();
@@ -311,7 +256,7 @@ public class SpringAwareUserTransactionTest extends TestCase
// Expected fail
}
}
-
+
private UserTransaction getFailingTxn()
{
return new SpringAwareUserTransaction(
@@ -321,7 +266,7 @@ public class SpringAwareUserTransactionTest extends TestCase
TransactionDefinition.PROPAGATION_REQUIRED,
TransactionDefinition.TIMEOUT_DEFAULT);
}
-
+
public void testTransactionListenerOrder() throws Throwable
{
testNoTxnStatus();
@@ -360,12 +305,12 @@ public class SpringAwareUserTransactionTest extends TestCase
}
checkNoStatusOnThread();
}
-
+
private static class TestTransactionListener extends TransactionListenerAdapter
{
private final String name;
private final StringBuffer buffer;
-
+
public TestTransactionListener(String name, StringBuffer buffer)
{
Objects.requireNonNull(name);
@@ -373,18 +318,18 @@ public class SpringAwareUserTransactionTest extends TestCase
this.name = name;
this.buffer = buffer;
}
-
+
@Override
public void beforeCommit(boolean readOnly)
{
buffer.append(name);
}
-
+
public String getName()
{
return name;
}
-
+
@Override
public boolean equals(Object obj)
{
@@ -394,17 +339,17 @@ public class SpringAwareUserTransactionTest extends TestCase
}
return false;
}
-
+
@Override
public int hashCode()
{
return name.hashCode();
}
}
-
+
/**
* Used to check that the transaction manager is being called correctly
- *
+ *
* @author Derek Hulley
*/
@SuppressWarnings("serial")
@@ -412,7 +357,7 @@ public class SpringAwareUserTransactionTest extends TestCase
{
private int status = Status.STATUS_NO_TRANSACTION;
private Object txn = new Object();
-
+
/**
* @return Returns one of the {@link Status Status.STATUS_XXX} constants
*/
@@ -441,10 +386,10 @@ public class SpringAwareUserTransactionTest extends TestCase
status = Status.STATUS_ROLLEDBACK;
}
}
-
+
/**
* Throws {@link NoSuchElementException} on begin()
- *
+ *
* @author alex.mukha
*/
private static class FailingTransactionManager extends AbstractPlatformTransactionManager
@@ -452,7 +397,7 @@ public class SpringAwareUserTransactionTest extends TestCase
private static final long serialVersionUID = 1L;
private int status = Status.STATUS_NO_TRANSACTION;
private Object txn = new Object();
-
+
/**
* @return Returns one of the {@link Status Status.STATUS_XXX} constants
*/
diff --git a/data-model/pom.xml b/data-model/pom.xml
index 985c9af20e..2e6970001e 100644
--- a/data-model/pom.xml
+++ b/data-model/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/mmt/pom.xml b/mmt/pom.xml
index 0fbf094a15..ccc2e911d4 100644
--- a/mmt/pom.xml
+++ b/mmt/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/distribution/pom.xml b/packaging/distribution/pom.xml
index 692a86844c..86e563d230 100644
--- a/packaging/distribution/pom.xml
+++ b/packaging/distribution/pom.xml
@@ -9,6 +9,6 @@
org.alfresco
alfresco-community-repo-packaging
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/docker-alfresco/Dockerfile b/packaging/docker-alfresco/Dockerfile
index 51538fc5a3..209dc88a9d 100644
--- a/packaging/docker-alfresco/Dockerfile
+++ b/packaging/docker-alfresco/Dockerfile
@@ -1,5 +1,5 @@
# More infos about this image: https://github.com/Alfresco/alfresco-docker-base-tomcat
-FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux9@sha256:395664f9d9be0c9f73d3b722a58fd559ee7231609b263dfe19502617652740e3
+FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux9@sha256:9622418e142fb4fe1c5320666ad61ea292bc5c98f3dd0b550b6add33d18f659f
# Set default docker_context.
ARG resource_path=target
diff --git a/packaging/docker-alfresco/pom.xml b/packaging/docker-alfresco/pom.xml
index c4208ee192..26fff79e35 100644
--- a/packaging/docker-alfresco/pom.xml
+++ b/packaging/docker-alfresco/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo-packaging
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/pom.xml b/packaging/pom.xml
index b2f58e3e58..b010f42adb 100644
--- a/packaging/pom.xml
+++ b/packaging/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/tests/pom.xml b/packaging/tests/pom.xml
index 3a888db37b..ba59f7322e 100644
--- a/packaging/tests/pom.xml
+++ b/packaging/tests/pom.xml
@@ -6,7 +6,7 @@
org.alfresco
alfresco-community-repo-packaging
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/tests/tas-cmis/pom.xml b/packaging/tests/tas-cmis/pom.xml
index 65a9f2cfa3..20d37ebf7b 100644
--- a/packaging/tests/tas-cmis/pom.xml
+++ b/packaging/tests/tas-cmis/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo-tests
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/tests/tas-email/pom.xml b/packaging/tests/tas-email/pom.xml
index 3cd6615e21..ec3f68d2ee 100644
--- a/packaging/tests/tas-email/pom.xml
+++ b/packaging/tests/tas-email/pom.xml
@@ -9,7 +9,7 @@
org.alfresco
alfresco-community-repo-tests
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/tests/tas-integration/pom.xml b/packaging/tests/tas-integration/pom.xml
index b1aa08caff..015e2149ff 100644
--- a/packaging/tests/tas-integration/pom.xml
+++ b/packaging/tests/tas-integration/pom.xml
@@ -9,7 +9,7 @@
org.alfresco
alfresco-community-repo-tests
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/tests/tas-restapi/pom.xml b/packaging/tests/tas-restapi/pom.xml
index 8dbd74408c..73c125f226 100644
--- a/packaging/tests/tas-restapi/pom.xml
+++ b/packaging/tests/tas-restapi/pom.xml
@@ -8,7 +8,7 @@
org.alfresco
alfresco-community-repo-tests
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/tests/tas-webdav/pom.xml b/packaging/tests/tas-webdav/pom.xml
index 3cd197251c..dee3e38e6d 100644
--- a/packaging/tests/tas-webdav/pom.xml
+++ b/packaging/tests/tas-webdav/pom.xml
@@ -9,7 +9,7 @@
org.alfresco
alfresco-community-repo-tests
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/packaging/war/pom.xml b/packaging/war/pom.xml
index e156deb88e..3cea4e4a84 100644
--- a/packaging/war/pom.xml
+++ b/packaging/war/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo-packaging
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/pom.xml b/pom.xml
index b90e7a460e..4d0c3457b3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
alfresco-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
pom
Alfresco Community Repo Parent
@@ -51,14 +51,14 @@
7.0.1
5.23.0
5.23.0
- 5.1.6
- 4.1.6
+ 5.1.7-A.3
+ 4.1.7-A.1
7.1
1.0.2
1.9.22.1
6.2.2
- 6.3.4
+ 6.3.7
3.5.3
2.17.2
4.1.0
@@ -86,7 +86,7 @@
5.3.0
3.5.0.Final
4.6.0
- 4.1.117.Final
+ 4.1.118.Final
5.18.6
1.27.1
4.2.2
diff --git a/remote-api/pom.xml b/remote-api/pom.xml
index fa77a597be..873b1c30e1 100644
--- a/remote-api/pom.xml
+++ b/remote-api/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/repository/pom.xml b/repository/pom.xml
index 44f7c0f7be..f0b3f3ab08 100644
--- a/repository/pom.xml
+++ b/repository/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 25.1.0.49-SNAPSHOT
+ 25.1.0.61-SNAPSHOT
diff --git a/repository/src/test/java/org/alfresco/email/server/EmailServiceImplTest.java b/repository/src/test/java/org/alfresco/email/server/EmailServiceImplTest.java
index 3536da694b..916b78d325 100644
--- a/repository/src/test/java/org/alfresco/email/server/EmailServiceImplTest.java
+++ b/repository/src/test/java/org/alfresco/email/server/EmailServiceImplTest.java
@@ -1,1220 +1,1190 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
-package org.alfresco.email.server;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.Vector;
-import java.util.concurrent.CountDownLatch;
-
-import jakarta.mail.Message;
-import jakarta.mail.Session;
-import jakarta.mail.internet.InternetAddress;
-
-import junit.framework.TestCase;
-
-import org.alfresco.email.server.handler.FolderEmailMessageHandler;
-import org.alfresco.email.server.impl.subetha.SubethaEmailMessage;
-import org.alfresco.model.ContentModel;
-import org.alfresco.model.ForumModel;
-import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.transfer.TransferModel;
-import org.alfresco.repo.transaction.RetryingTransactionHelper;
-import org.alfresco.service.cmr.email.EmailDelivery;
-import org.alfresco.service.cmr.email.EmailMessageException;
-import org.alfresco.service.cmr.email.EmailService;
-import org.alfresco.service.cmr.repository.ChildAssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.repository.StoreRef;
-import org.alfresco.service.cmr.search.SearchService;
-import org.alfresco.service.cmr.security.AuthorityService;
-import org.alfresco.service.cmr.security.PersonService;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.service.namespace.RegexQNamePattern;
-import org.alfresco.test_category.OwnJVMTestsCategory;
-import org.alfresco.util.ApplicationContextHelper;
-import org.alfresco.util.testing.category.LuceneTests;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.experimental.categories.Category;
-import org.springframework.context.ApplicationContext;
-
-import com.sun.mail.smtp.SMTPMessage;
-
-/**
- * Unit test of EmailServiceImplTest
- * @author mrogers
- *
- */
-@Category({OwnJVMTestsCategory.class})
-public class EmailServiceImplTest extends TestCase
-{
- /**
- * Services used by the tests
- */
- private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
-
- private static Log logger = LogFactory.getLog(EmailServiceImplTest.class);
-
- private NodeService nodeService;
- private EmailService emailService;
- private PersonService personService;
- private AuthorityService authorityService;
- private SearchService searchService;
- private NamespaceService namespaceService;
- private FolderEmailMessageHandler folderEmailMessageHandler;
- private RetryingTransactionHelper transactionHelper;
-
- String TEST_USER="EmailServiceImplTestUser";
-
- @Override
- public void setUp() throws Exception
- {
- AuthenticationUtil.setRunAsUserSystem();
- nodeService = (NodeService)ctx.getBean("NodeService");
- assertNotNull("nodeService", nodeService);
- authorityService = (AuthorityService)ctx.getBean("AuthorityService");
- assertNotNull("authorityService", authorityService);
- ChildApplicationContextFactory emailSubsystem = (ChildApplicationContextFactory) ctx.getBean("InboundSMTP");
- assertNotNull("emailSubsystem", emailSubsystem);
- ApplicationContext emailCtx = emailSubsystem.getApplicationContext();
- emailService = (EmailService)emailCtx.getBean("emailService");
- assertNotNull("emailService", emailService);
- personService = (PersonService)emailCtx.getBean("PersonService");
- assertNotNull("personService", personService);
- namespaceService = (NamespaceService)emailCtx.getBean("NamespaceService");
- assertNotNull("namespaceService", namespaceService);
- searchService = (SearchService)emailCtx.getBean("SearchService");
- assertNotNull("searchService", searchService);
- folderEmailMessageHandler = (FolderEmailMessageHandler) emailCtx.getBean("folderEmailMessageHandler");
- assertNotNull("folderEmailMessageHandler", folderEmailMessageHandler);
- transactionHelper = (RetryingTransactionHelper) emailCtx.getBean("retryingTransactionHelper");
- assertNotNull("transactionHelper", transactionHelper);
- }
-
- public void tearDown() throws Exception
- {
- AuthenticationUtil.setRunAsUserSystem();
- try
- {
- personService.deletePerson(TEST_USER);
- }
- catch (Exception e)
- {
- }
- }
-
- /**
- * Test the from name.
- *
- * Step 1:
- * User admin will map to the "unknownUser" which out of the box is "anonymous"
- * Sending email From "admin" will fail.
- *
- * Step 2:
- * Send from the test user to the test' user's home folder.
- */
- public void testFromName() throws Exception
- {
-
- folderEmailMessageHandler.setOverwriteDuplicates(true);
-
- logger.debug("Start testFromName");
-
- String TEST_EMAIL="buffy@sunnydale.high";
-
- // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
- NodeRef person = personService.getPerson(TEST_USER);
- if(person == null)
- {
- logger.debug("new person created");
- Map props = new HashMap();
- props.put(ContentModel.PROP_USERNAME, TEST_USER);
- props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
- person = personService.createPerson(props);
- }
- nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
-
- Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
- if(!auths.contains(TEST_USER))
- {
- authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
- }
-
- String companyHomePathInStore = "/app:company_home";
- String storePath = "workspace://SpacesStore";
- StoreRef storeRef = new StoreRef(storePath);
-
- NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
- List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
- NodeRef companyHomeNodeRef = nodeRefs.get(0);
- assertNotNull("company home is null", companyHomeNodeRef);
- String companyHomeDBID = ((Long)nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- NodeRef testUserHomeFolder = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
- assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
- String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
-
- /**
- * Step 1
- * Negative test - send from "Bert" who does not exist.
- * User will be mapped to anonymous who is not an email contributor.
- */
- try
- {
- String from = "admin";
- String to = "bertie";
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress("Bert"));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("JavaMail APIs transport.java Test");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
-
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- fail("anonymous user not rejected");
- }
- catch (EmailMessageException e)
- {
- // Check the exception is for the anonymous user.
- assertTrue("Message is not for anonymous", e.getMessage().contains("anonymous"));
- }
-
- /**
- * Step 2
- *
- * Send From the test user TEST_EMAIL to the test user's home
- */
- {
- logger.debug("Step 2");
-
- String from = TEST_EMAIL;
- String to = testUserHomeDBID;
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("JavaMail APIs transport.java Test");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
-
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- }
-
- /**
- * Step 3
- *
- * message.from From with "name" < name@ domain > format
- * SMTP.FROM="dummy"
- *
- * Send From the test user to the test user's home
- */
- {
- logger.debug("Step 3");
-
- String from = " \"Joe Bloggs\" <" + TEST_EMAIL + ">";
- String to = testUserHomeDBID;
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(from));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("JavaMail APIs transport.java Test");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(System.out);
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
-
- EmailDelivery delivery = new EmailDelivery(to, "dummy", null);
-
- emailService.importMessage(delivery,m);
- }
-
- /**
- * Step 4
- *
- * From with "name" < name@ domain > format
- *
- * Send From the test user to the test user's home
- */
- {
- logger.debug("Step 4");
-
- String from = " \"Joe Bloggs\" <" + TEST_EMAIL + ">";
- String to = testUserHomeDBID;
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(from));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("JavaMail APIs transport.java Test");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(System.out);
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
-
- InternetAddress a = new InternetAddress(from);
- String x = a.getAddress();
-
- EmailDelivery delivery = new EmailDelivery(to, x, null);
-
- emailService.importMessage(delivery,m);
- }
-
-// /**
-// * Step 5
-// *
-// * From with format
-// *
-// * RFC3696
-// *
-// * Send From the test user to the test user's home
-// */
-// {
-// logger.debug("Step 4 format");
-//
-// String from = "\"Joe Bloggs\" ";
-// String to = testUserHomeDBID;
-// String content = "hello world";
-//
-// Session sess = Session.getDefaultInstance(new Properties());
-// assertNotNull("sess is null", sess);
-// SMTPMessage msg = new SMTPMessage(sess);
-// InternetAddress[] toa = { new InternetAddress(to) };
-//
-// msg.setFrom(new InternetAddress(from));
-// msg.setRecipients(Message.RecipientType.TO, toa);
-// msg.setSubject("JavaMail APIs transport.java Test");
-// msg.setContent(content, "text/plain");
-//
-// StringBuffer sb = new StringBuffer();
-// ByteArrayOutputStream bos = new ByteArrayOutputStream();
-// msg.writeTo(System.out);
-// msg.writeTo(bos);
-// InputStream is = IOUtils.toInputStream(bos.toString());
-// assertNotNull("is is null", is);
-//
-// SubethaEmailMessage m = new SubethaEmailMessage(is);
-//
-// emailService.importMessage(m);
-// }
- }
-
-
- /**
- * ALF-9544
- * ALF-751
- *
- * Inbound email to a folder restricts file name to 86 characters or less.
- *
- * Also has tests for other variations of subject
- */
- public void testFolderSubject() throws Exception
- {
- logger.debug("Start testFromName");
-
- String TEST_EMAIL="buffy@sunnydale.high";
-
- folderEmailMessageHandler.setOverwriteDuplicates(true);
-
- // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
- NodeRef person = personService.getPerson(TEST_USER);
- if(person == null)
- {
- logger.debug("new person created");
- Map props = new HashMap();
- props.put(ContentModel.PROP_USERNAME, TEST_USER);
- props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
- person = personService.createPerson(props);
- }
- nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
-
- Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
- if(!auths.contains(TEST_USER))
- {
- authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
- }
-
- String companyHomePathInStore = "/app:company_home";
- String storePath = "workspace://SpacesStore";
- StoreRef storeRef = new StoreRef(storePath);
-
- NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
- List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
- NodeRef companyHomeNodeRef = nodeRefs.get(0);
- assertNotNull("company home is null", companyHomeNodeRef);
- String companyHomeDBID = ((Long)nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- NodeRef testUserHomeFolder = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
- assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
- String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
-
- /**
- * Send From the test user TEST_EMAIL to the test user's home
- */
- String from = TEST_EMAIL;
- String to = testUserHomeDBID;
- String content = "hello world";
-
- {
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- }
-
- // Check import with subject containing some "illegal chars"
- {
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("Illegal<>!*/\\.txt");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- }
-
- // Check with null subject
- {
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- //msg.setSubject();
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- }
-
-
- // ALF-751 Email ends with period
- {
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("Foobar.");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- }
-
- // ALF-751 Email ends with ...
- {
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("Foobar...");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- }
-
- // ALF-751 Email subject is blank " ... "
- {
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject(" ... ");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- }
-
- // ALF-751 Email subject is a single .
- {
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject(".");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- }
-
- }
-
- /**
- * ALF-1878
- *
- * Duplicate incoming email Subjects over-write each other
- */
- public void testMultipleMessagesToFolder() throws Exception
- {
- logger.debug("Start testFromName");
-
- String TEST_EMAIL="buffy@sunnydale.high";
-
- String TEST_SUBJECT="Practical Bee Keeping";
-
- String TEST_LONG_SUBJECT = "This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544";
-
-
- // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
- NodeRef person = personService.getPerson(TEST_USER);
- if(person == null)
- {
- logger.debug("new person created");
- Map props = new HashMap();
- props.put(ContentModel.PROP_USERNAME, TEST_USER);
- props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
- person = personService.createPerson(props);
- }
- nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
-
- Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
- if(!auths.contains(TEST_USER))
- {
- authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
- }
-
- String companyHomePathInStore = "/app:company_home";
- String storePath = "workspace://SpacesStore";
- StoreRef storeRef = new StoreRef(storePath);
-
- NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
- List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
- NodeRef companyHomeNodeRef = nodeRefs.get(0);
- assertNotNull("company home is null", companyHomeNodeRef);
- String companyHomeDBID = ((Long)nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- NodeRef testUserHomeFolder = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
- assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
- String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
-
- // Clean up old messages in test folder
- List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- for(ChildAssociationRef assoc : assocs)
- {
- nodeService.deleteNode(assoc.getChildRef());
- }
-
- /**
- * Send From the test user TEST_EMAIL to the test user's home
- */
- String from = TEST_EMAIL;
- String to = testUserHomeDBID;
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject(TEST_SUBJECT);
- msg.setContent(content, "text/plain");
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
-
- /**
- * Turn on overwriteDuplicates
- */
- logger.debug("Step 1: turn on Overwite Duplicates");
- folderEmailMessageHandler.setOverwriteDuplicates(true);
-
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- assertEquals("assocs not 1", 1, assocs.size());
- assertEquals("name of link not as expected", assocs.get(0).getQName(), QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_SUBJECT));
- emailService.importMessage(delivery, m);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- assertEquals("assocs not 1", 1, assocs.size());
-
- /**
- * Turn off overwrite Duplicates
- */
- logger.debug("Step 2: turn off Overwite Duplicates");
- folderEmailMessageHandler.setOverwriteDuplicates(false);
- emailService.importMessage(delivery, m);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- assertEquals("assocs not 2", 2, assocs.size());
- emailService.importMessage(delivery, m);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- assertEquals("assocs not 3", 3, assocs.size());
-
- /**
- * Check assoc rename with long names. So truncation and rename need to work together.
- */
- logger.debug("Step 3: turn off Overwite Duplicates with long subject name");
- msg.setSubject(TEST_LONG_SUBJECT);
- ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
- msg.writeTo(bos2);
- is = IOUtils.toInputStream(bos2.toString());
- assertNotNull("is is null", is);
- m = new SubethaEmailMessage(is);
-
- folderEmailMessageHandler.setOverwriteDuplicates(false);
- emailService.importMessage(delivery, m);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- assertEquals("assocs not 4", 4, assocs.size());
- emailService.importMessage(delivery, m);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- assertEquals("assocs not 5", 5, assocs.size());
-
- /**
- * Check assoc rename with long names and an extension. So truncation and rename need to
- * work together and not muck up a .extension.
- */
- logger.debug("Step 4: turn off Overwite Duplicates with long subject name with extension");
- String EXT_NAME = "Blob.xls";
-
- msg.setSubject(EXT_NAME);
- ByteArrayOutputStream bos3 = new ByteArrayOutputStream();
- msg.writeTo(bos3);
- is = IOUtils.toInputStream(bos3.toString());
- assertNotNull("is is null", is);
- m = new SubethaEmailMessage(is);
- folderEmailMessageHandler.setOverwriteDuplicates(false);
- emailService.importMessage(delivery, m);
- emailService.importMessage(delivery, m);
- emailService.importMessage(delivery, m);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
-
- List assocNames = new Vector();
- for(ChildAssociationRef assoc : assocs)
- {
- logger.debug("assocName: " + assoc.getQName());
- System.out.println(assoc.getQName());
- assocNames.add(assoc.getQName());
- }
- assertTrue(EXT_NAME + "not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Blob.xls")));
- assertTrue("Blob(1).xls not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Blob(1).xls")));
- assertTrue("Blob(2).xls not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Blob(2).xls")));
- assertTrue(TEST_SUBJECT + "not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_SUBJECT)));
- assertTrue(TEST_SUBJECT+"(1) not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Practical Bee Keeping(1)")));
-
- /**
- * Check concurrent deliver of the same message. Reuse message from the previous test.
- */
- logger.debug("Step 5: turn off Overwite Duplicates and check concurrent deliver of the same message");
- folderEmailMessageHandler.setOverwriteDuplicates(false);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- int numBeforeConcurrentDeliver = assocs.size();
- deliverConcurrently(delivery, m);
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- int numAfterConcurrentDeliver = assocs.size();
- assertEquals("Two messages must be added", numBeforeConcurrentDeliver + 2, numAfterConcurrentDeliver);
- }
-
- private void deliverConcurrently(final EmailDelivery delivery, final SubethaEmailMessage m) throws Exception
- {
- final CountDownLatch cdl = new CountDownLatch(1);
- class ConcurrentMessageImporter implements Runnable
- {
- private Throwable throwable;
- @Override
- public void run()
- {
- try
- {
- transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- cdl.countDown();
- emailService.importMessage(delivery, m);
- return null;
- }
- }, false, true);
- }
- catch (Throwable t)
- {
- throwable = t;
- }
- }
- }
- ConcurrentMessageImporter messageImporter = new ConcurrentMessageImporter();
- final Thread messageImporterThread = new Thread(messageImporter);
- transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- emailService.importMessage(delivery, m);
- messageImporterThread.start();
- // wait until concurrent transaction has started
- cdl.await();
- return null;
- }
- }, false, true);
- messageImporterThread.join();
- if (null != messageImporter.throwable)
- {
- fail(messageImporter.throwable.getMessage());
- }
- }
-
- /**
- * MNT-9289
- *
- * Change in case in email Subject causes DuplicateChildNodeNameException
- */
- public void testCaseSensitivity() throws Exception
- {
- NodeRef person = personService.getPerson(TEST_USER);
- String TEST_EMAIL="buffy@sunnydale.high";
- NodeRef testUserHomeFolder = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
- if(person == null)
- {
- logger.debug("new person created");
- Map props = new HashMap();
- props.put(ContentModel.PROP_USERNAME, TEST_USER);
- props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
- person = personService.createPerson(props);
- }
-
- nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
-
- Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
- if(!auths.contains(TEST_USER))
- {
- authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
- }
-
- String companyHomePathInStore = "/app:company_home";
- String storePath = "workspace://SpacesStore";
- StoreRef storeRef = new StoreRef(storePath);
-
- NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
- List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
- NodeRef companyHomeNodeRef = nodeRefs.get(0);
- assertNotNull("company home is null", companyHomeNodeRef);
-
- String TEST_CASE_SENSITIVITY_SUBJECT = "Test (Mail)";
- String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
-
- String from = TEST_EMAIL;
- String to = testUserHomeDBID;
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setContent(content, "text/plain");
-
- msg.setSubject(TEST_CASE_SENSITIVITY_SUBJECT);
- ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
- msg.writeTo(bos1);
- InputStream is = IOUtils.toInputStream(bos1.toString());
- assertNotNull("is is null", is);
- SubethaEmailMessage m = new SubethaEmailMessage(is);
- folderEmailMessageHandler.setOverwriteDuplicates(false);
- emailService.importMessage(delivery, m);
-
- QName safeQName = QName.createQNameWithValidLocalName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_CASE_SENSITIVITY_SUBJECT);
- List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, safeQName);
- assertEquals(1, assocs.size());
-
- msg.setSubject(TEST_CASE_SENSITIVITY_SUBJECT.toUpperCase());
- ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
- msg.writeTo(bos2);
- is = IOUtils.toInputStream(bos2.toString());
- assertNotNull("is is null", is);
- m = new SubethaEmailMessage(is);
- folderEmailMessageHandler.setOverwriteDuplicates(false);
- emailService.importMessage(delivery, m);
-
- safeQName = QName.createQNameWithValidLocalName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_CASE_SENSITIVITY_SUBJECT.toUpperCase() + "(1)");
- assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, safeQName);
- assertEquals(1, assocs.size());
- }
-
-
- /**
- * ALF-12297
- *
- * Test messages being sent to a cm:content node
- */
- public void testMessagesToDocument() throws Exception
- {
- logger.debug("Start testMessagesToDocument");
-
- String TEST_EMAIL="buffy@sunnydale.high";
-
- String TEST_SUBJECT="Practical Bee Keeping";
-
- String TEST_LONG_SUBJECT = "This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544";
-
-
- // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
- NodeRef person = personService.getPerson(TEST_USER);
- if(person == null)
- {
- logger.debug("new person created");
- Map props = new HashMap();
- props.put(ContentModel.PROP_USERNAME, TEST_USER);
- props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
- person = personService.createPerson(props);
- }
- nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
-
- Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
- if(!auths.contains(TEST_USER))
- {
- authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
- }
-
- String companyHomePathInStore = "/app:company_home";
- String storePath = "workspace://SpacesStore";
- StoreRef storeRef = new StoreRef(storePath);
-
- NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
- List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
- NodeRef companyHomeNodeRef = nodeRefs.get(0);
- assertNotNull("company home is null", companyHomeNodeRef);
- String companyHomeDBID = ((Long)nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- // String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- NodeRef testUserHomeFolder = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
- assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
-// String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
-
- // Clean up old messages in test folder
- List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- for(ChildAssociationRef assoc : assocs)
- {
- nodeService.deleteNode(assoc.getChildRef());
- }
-
-
- Map properties = new HashMap();
- properties.put(ContentModel.PROP_NAME, "bees");
- properties.put(ContentModel.PROP_DESCRIPTION, "bees - test doc for email tests");
- ChildAssociationRef testDoc = nodeService.createNode(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "bees"), ContentModel.TYPE_CONTENT, properties);
- NodeRef testDocNodeRef = testDoc.getChildRef();
-
- String testDocDBID = ((Long)nodeService.getProperty(testDocNodeRef, ContentModel.PROP_NODE_DBID)).toString();
-
- /**
- * Send From the test user TEST_EMAIL to the test user's home
- */
- String from = TEST_EMAIL;
- String to = testDocDBID + "@alfresco.com";
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject(TEST_SUBJECT);
- msg.setContent(content, "text/plain");
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
-
- /**
- * Turn on overwriteDuplicates
- */
- logger.debug("Step 1: send an email to a doc");
-
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
-
- assertTrue(nodeService.hasAspect(testDocNodeRef, ForumModel.ASPECT_DISCUSSABLE));
-
-
-
- } // end of test sending to cm:content node
-
-
- /**
- * ENH-560 - Inbound email server not working with custom types
- */
- public void testMessagesToSubTypeOfDocument() throws Exception
- {
- logger.debug("Start testMessagesToSubTypesOfDocument");
-
- String TEST_EMAIL="buffy@sunnydale.high";
-
- String TEST_SUBJECT="Practical Bee Keeping";
-
- String TEST_LONG_SUBJECT = "This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544";
-
-
- // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
- NodeRef person = personService.getPerson(TEST_USER);
- if(person == null)
- {
- logger.debug("new person created");
- Map props = new HashMap();
- props.put(ContentModel.PROP_USERNAME, TEST_USER);
- props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
- person = personService.createPerson(props);
- }
- nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
-
- Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
- if(!auths.contains(TEST_USER))
- {
- authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
- }
-
- String companyHomePathInStore = "/app:company_home";
- String storePath = "workspace://SpacesStore";
- StoreRef storeRef = new StoreRef(storePath);
-
- NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
- List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
- NodeRef companyHomeNodeRef = nodeRefs.get(0);
- assertNotNull("company home is null", companyHomeNodeRef);
- String companyHomeDBID = ((Long)nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
-// String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- NodeRef testUserHomeFolder = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
- assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
-// String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
-
- // Clean up old messages in test folder
- List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- for(ChildAssociationRef assoc : assocs)
- {
- nodeService.deleteNode(assoc.getChildRef());
- }
-
-
- Map properties = new HashMap();
- properties.put(ContentModel.PROP_NAME, "hamster");
- properties.put(ContentModel.PROP_DESCRIPTION, "syrian hamsters - test doc for email tests, sending to a subtype of cm:content");
-
- // Transfer report is a subtype of cm:content
- ChildAssociationRef testDoc = nodeService.createNode(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "bees"), TransferModel.TYPE_TRANSFER_REPORT, properties);
- NodeRef testDocNodeRef = testDoc.getChildRef();
-
- String testDocDBID = ((Long)nodeService.getProperty(testDocNodeRef, ContentModel.PROP_NODE_DBID)).toString();
-
- /**
- * Send From the test user TEST_EMAIL to the test user's home
- */
- String from = TEST_EMAIL;
- String to = testDocDBID + "@alfresco.com";
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject(TEST_SUBJECT);
- msg.setContent(content, "text/plain");
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
-
- /**
- * Turn on overwriteDuplicates
- */
- logger.debug("Step 1: send an email to a transfer report");
-
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
-
- } // end of test sending to trx:transferReport
-
-
-
-
-
- /**
- * The Email contributors authority controls who can add email.
- *
- * This test switches between the EMAIL_CONTRIBUTORS group and EVERYONE
- */
- public void testEmailContributorsAuthority() throws Exception
- {
- EmailServiceImpl emailServiceImpl = (EmailServiceImpl)emailService;
-
- folderEmailMessageHandler.setOverwriteDuplicates(true);
-
- logger.debug("Start testEmailContributorsAuthority");
-
- String TEST_EMAIL="buffy@sunnydale.high";
-
- // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
- NodeRef person = personService.getPerson(TEST_USER);
- if(person == null)
- {
- logger.debug("new person created");
- Map props = new HashMap();
- props.put(ContentModel.PROP_USERNAME, TEST_USER);
- props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
- person = personService.createPerson(props);
- }
- nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
-
- Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
- if(auths.contains(TEST_USER))
- {
- authorityService.removeAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
- }
-
- String companyHomePathInStore = "/app:company_home";
- String storePath = "workspace://SpacesStore";
- StoreRef storeRef = new StoreRef(storePath);
-
- NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
- List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
- NodeRef companyHomeNodeRef = nodeRefs.get(0);
- assertNotNull("company home is null", companyHomeNodeRef);
- String companyHomeDBID = ((Long)nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
- NodeRef testUserHomeFolder = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
- assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
- String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
-
- /**
- * Step 1
- * Set the email contributors authority to EVERYONE
- *
- * Test that TEST_USER is allowed to send email - so even though TEST_USER is not
- * a contributor
- */
- emailServiceImpl.setEmailContributorsAuthority("EVERYONE");
-
- String from = "admin";
- String to = testUserHomeDBID;
- String content = "hello world";
-
- Session sess = Session.getDefaultInstance(new Properties());
- assertNotNull("sess is null", sess);
- SMTPMessage msg = new SMTPMessage(sess);
- InternetAddress[] toa = { new InternetAddress(to) };
-
- msg.setFrom(new InternetAddress(TEST_EMAIL));
- msg.setRecipients(Message.RecipientType.TO, toa);
- msg.setSubject("JavaMail APIs transport.java Test");
- msg.setContent(content, "text/plain");
-
- StringBuffer sb = new StringBuffer();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- msg.writeTo(bos);
- InputStream is = IOUtils.toInputStream(bos.toString());
- assertNotNull("is is null", is);
-
- SubethaEmailMessage m = new SubethaEmailMessage(is);
-
- EmailDelivery delivery = new EmailDelivery(to, from, null);
-
- emailService.importMessage(delivery, m);
-
- /**
- * Step 2
- * Negative test
- *
- * Send From the test user TEST_EMAIL to the test user's home
- */
- try
- {
- logger.debug("Step 2");
- emailServiceImpl.setEmailContributorsAuthority("EMAIL_CONTRIBUTORS");
- emailService.importMessage(delivery, m);
- fail("not thrown out");
- }
- catch (EmailMessageException e)
- {
- // Check the exception is for the anonymous user.
- // assertTrue(e.getMessage().contains("anonymous"));
- }
- }
-
-} // end of EmailServiceImplTest
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2025 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.email.server;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
+import jakarta.mail.Message;
+import jakarta.mail.Session;
+import jakarta.mail.internet.InternetAddress;
+
+import com.sun.mail.smtp.SMTPMessage;
+import junit.framework.TestCase;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.experimental.categories.Category;
+import org.springframework.context.ApplicationContext;
+
+import org.alfresco.email.server.handler.FolderEmailMessageHandler;
+import org.alfresco.email.server.impl.subetha.SubethaEmailMessage;
+import org.alfresco.model.ContentModel;
+import org.alfresco.model.ForumModel;
+import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transfer.TransferModel;
+import org.alfresco.service.cmr.email.EmailDelivery;
+import org.alfresco.service.cmr.email.EmailMessageException;
+import org.alfresco.service.cmr.email.EmailService;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.namespace.RegexQNamePattern;
+import org.alfresco.test_category.OwnJVMTestsCategory;
+import org.alfresco.util.ApplicationContextHelper;
+
+/**
+ * Unit test of EmailServiceImplTest
+ *
+ * @author mrogers
+ *
+ */
+@Category({OwnJVMTestsCategory.class})
+public class EmailServiceImplTest extends TestCase
+{
+ /**
+ * Services used by the tests
+ */
+ private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
+
+ private static Log logger = LogFactory.getLog(EmailServiceImplTest.class);
+
+ private NodeService nodeService;
+ private EmailService emailService;
+ private PersonService personService;
+ private AuthorityService authorityService;
+ private SearchService searchService;
+ private NamespaceService namespaceService;
+ private FolderEmailMessageHandler folderEmailMessageHandler;
+ private RetryingTransactionHelper transactionHelper;
+
+ String TEST_USER = "EmailServiceImplTestUser";
+
+ @Override
+ public void setUp() throws Exception
+ {
+ AuthenticationUtil.setRunAsUserSystem();
+ nodeService = (NodeService) ctx.getBean("NodeService");
+ assertNotNull("nodeService", nodeService);
+ authorityService = (AuthorityService) ctx.getBean("AuthorityService");
+ assertNotNull("authorityService", authorityService);
+ ChildApplicationContextFactory emailSubsystem = (ChildApplicationContextFactory) ctx.getBean("InboundSMTP");
+ assertNotNull("emailSubsystem", emailSubsystem);
+ ApplicationContext emailCtx = emailSubsystem.getApplicationContext();
+ emailService = (EmailService) emailCtx.getBean("emailService");
+ assertNotNull("emailService", emailService);
+ personService = (PersonService) emailCtx.getBean("PersonService");
+ assertNotNull("personService", personService);
+ namespaceService = (NamespaceService) emailCtx.getBean("NamespaceService");
+ assertNotNull("namespaceService", namespaceService);
+ searchService = (SearchService) emailCtx.getBean("SearchService");
+ assertNotNull("searchService", searchService);
+ folderEmailMessageHandler = (FolderEmailMessageHandler) emailCtx.getBean("folderEmailMessageHandler");
+ assertNotNull("folderEmailMessageHandler", folderEmailMessageHandler);
+ transactionHelper = (RetryingTransactionHelper) emailCtx.getBean("retryingTransactionHelper");
+ assertNotNull("transactionHelper", transactionHelper);
+ }
+
+ public void tearDown() throws Exception
+ {
+ AuthenticationUtil.setRunAsUserSystem();
+ try
+ {
+ personService.deletePerson(TEST_USER);
+ }
+ catch (Exception e)
+ {}
+ }
+
+ /**
+ * Test the from name.
+ *
+ * Step 1: User admin will map to the "unknownUser" which out of the box is "anonymous" Sending email From "admin" will fail.
+ *
+ * Step 2: Send from the test user to the test' user's home folder.
+ */
+ public void testFromName() throws Exception
+ {
+
+ folderEmailMessageHandler.setOverwriteDuplicates(true);
+
+ logger.debug("Start testFromName");
+
+ String TEST_EMAIL = "buffy@sunnydale.high";
+
+ // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
+ NodeRef person = personService.getPerson(TEST_USER);
+ if (person == null)
+ {
+ logger.debug("new person created");
+ Map props = new HashMap();
+ props.put(ContentModel.PROP_USERNAME, TEST_USER);
+ props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
+ person = personService.createPerson(props);
+ }
+ nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
+
+ Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
+ if (!auths.contains(TEST_USER))
+ {
+ authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
+ }
+
+ String companyHomePathInStore = "/app:company_home";
+ String storePath = "workspace://SpacesStore";
+ StoreRef storeRef = new StoreRef(storePath);
+
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+ List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
+ NodeRef companyHomeNodeRef = nodeRefs.get(0);
+ assertNotNull("company home is null", companyHomeNodeRef);
+ String companyHomeDBID = ((Long) nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ String testUserDBID = ((Long) nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ NodeRef testUserHomeFolder = (NodeRef) nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
+ assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
+ String testUserHomeDBID = ((Long) nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+
+ /**
+ * Step 1 Negative test - send from "Bert" who does not exist. User will be mapped to anonymous who is not an email contributor.
+ */
+ try
+ {
+ String from = "admin";
+ String to = "bertie";
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress("Bert"));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("JavaMail APIs transport.java Test");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ fail("anonymous user not rejected");
+ }
+ catch (EmailMessageException e)
+ {
+ // Check the exception is for the anonymous user.
+ assertTrue("Message is not for anonymous", e.getMessage().contains("anonymous"));
+ }
+
+ /**
+ * Step 2
+ *
+ * Send From the test user TEST_EMAIL to the test user's home
+ */
+ {
+ logger.debug("Step 2");
+
+ String from = TEST_EMAIL;
+ String to = testUserHomeDBID;
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("JavaMail APIs transport.java Test");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ /**
+ * Step 3
+ *
+ * message.from From with "name" < name@ domain > format SMTP.FROM="dummy"
+ *
+ * Send From the test user to the test user's home
+ */
+ {
+ logger.debug("Step 3");
+
+ String from = " \"Joe Bloggs\" <" + TEST_EMAIL + ">";
+ String to = testUserHomeDBID;
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(from));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("JavaMail APIs transport.java Test");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(System.out);
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+
+ EmailDelivery delivery = new EmailDelivery(to, "dummy", null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ /**
+ * Step 4
+ *
+ * From with "name" < name@ domain > format
+ *
+ * Send From the test user to the test user's home
+ */
+ {
+ logger.debug("Step 4");
+
+ String from = " \"Joe Bloggs\" <" + TEST_EMAIL + ">";
+ String to = testUserHomeDBID;
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(from));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("JavaMail APIs transport.java Test");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(System.out);
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+
+ InternetAddress a = new InternetAddress(from);
+ String x = a.getAddress();
+
+ EmailDelivery delivery = new EmailDelivery(to, x, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ // /**
+ // * Step 5
+ // *
+ // * From with format
+ // *
+ // * RFC3696
+ // *
+ // * Send From the test user to the test user's home
+ // */
+ // {
+ // logger.debug("Step 4 format");
+ //
+ // String from = "\"Joe Bloggs\" ";
+ // String to = testUserHomeDBID;
+ // String content = "hello world";
+ //
+ // Session sess = Session.getDefaultInstance(new Properties());
+ // assertNotNull("sess is null", sess);
+ // SMTPMessage msg = new SMTPMessage(sess);
+ // InternetAddress[] toa = { new InternetAddress(to) };
+ //
+ // msg.setFrom(new InternetAddress(from));
+ // msg.setRecipients(Message.RecipientType.TO, toa);
+ // msg.setSubject("JavaMail APIs transport.java Test");
+ // msg.setContent(content, "text/plain");
+ //
+ // StringBuffer sb = new StringBuffer();
+ // ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ // msg.writeTo(System.out);
+ // msg.writeTo(bos);
+ // InputStream is = IOUtils.toInputStream(bos.toString());
+ // assertNotNull("is is null", is);
+ //
+ // SubethaEmailMessage m = new SubethaEmailMessage(is);
+ //
+ // emailService.importMessage(m);
+ // }
+ }
+
+ /**
+ * ALF-9544 ALF-751
+ *
+ * Inbound email to a folder restricts file name to 86 characters or less.
+ *
+ * Also has tests for other variations of subject
+ */
+ public void testFolderSubject() throws Exception
+ {
+ logger.debug("Start testFromName");
+
+ String TEST_EMAIL = "buffy@sunnydale.high";
+
+ folderEmailMessageHandler.setOverwriteDuplicates(true);
+
+ // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
+ NodeRef person = personService.getPerson(TEST_USER);
+ if (person == null)
+ {
+ logger.debug("new person created");
+ Map props = new HashMap();
+ props.put(ContentModel.PROP_USERNAME, TEST_USER);
+ props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
+ person = personService.createPerson(props);
+ }
+ nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
+
+ Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
+ if (!auths.contains(TEST_USER))
+ {
+ authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
+ }
+
+ String companyHomePathInStore = "/app:company_home";
+ String storePath = "workspace://SpacesStore";
+ StoreRef storeRef = new StoreRef(storePath);
+
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+ List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
+ NodeRef companyHomeNodeRef = nodeRefs.get(0);
+ assertNotNull("company home is null", companyHomeNodeRef);
+ String companyHomeDBID = ((Long) nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ String testUserDBID = ((Long) nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ NodeRef testUserHomeFolder = (NodeRef) nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
+ assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
+ String testUserHomeDBID = ((Long) nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+
+ /**
+ * Send From the test user TEST_EMAIL to the test user's home
+ */
+ String from = TEST_EMAIL;
+ String to = testUserHomeDBID;
+ String content = "hello world";
+
+ {
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ // Check import with subject containing some "illegal chars"
+ {
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("Illegal<>!*/\\.txt");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ // Check with null subject
+ {
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ // msg.setSubject();
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ // ALF-751 Email ends with period
+ {
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("Foobar.");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ // ALF-751 Email ends with ...
+ {
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("Foobar...");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ // ALF-751 Email subject is blank " ... "
+ {
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject(" ... ");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ // ALF-751 Email subject is a single .
+ {
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject(".");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ }
+
+ }
+
+ /**
+ * ALF-1878
+ *
+ * Duplicate incoming email Subjects over-write each other
+ */
+ public void testMultipleMessagesToFolder() throws Exception
+ {
+ logger.debug("Start testFromName");
+
+ String TEST_EMAIL = "buffy@sunnydale.high";
+
+ String TEST_SUBJECT = "Practical Bee Keeping";
+
+ String TEST_LONG_SUBJECT = "This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544";
+
+ // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
+ NodeRef person = personService.getPerson(TEST_USER);
+ if (person == null)
+ {
+ logger.debug("new person created");
+ Map props = new HashMap();
+ props.put(ContentModel.PROP_USERNAME, TEST_USER);
+ props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
+ person = personService.createPerson(props);
+ }
+ nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
+
+ Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
+ if (!auths.contains(TEST_USER))
+ {
+ authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
+ }
+
+ String companyHomePathInStore = "/app:company_home";
+ String storePath = "workspace://SpacesStore";
+ StoreRef storeRef = new StoreRef(storePath);
+
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+ List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
+ NodeRef companyHomeNodeRef = nodeRefs.get(0);
+ assertNotNull("company home is null", companyHomeNodeRef);
+ String companyHomeDBID = ((Long) nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ String testUserDBID = ((Long) nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ NodeRef testUserHomeFolder = (NodeRef) nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
+ assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
+ String testUserHomeDBID = ((Long) nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+
+ // Clean up old messages in test folder
+ List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ for (ChildAssociationRef assoc : assocs)
+ {
+ nodeService.deleteNode(assoc.getChildRef());
+ }
+
+ /**
+ * Send From the test user TEST_EMAIL to the test user's home
+ */
+ String from = TEST_EMAIL;
+ String to = testUserHomeDBID;
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject(TEST_SUBJECT);
+ msg.setContent(content, "text/plain");
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+
+ /**
+ * Turn on overwriteDuplicates
+ */
+ logger.debug("Step 1: turn on Overwite Duplicates");
+ folderEmailMessageHandler.setOverwriteDuplicates(true);
+
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 1", 1, assocs.size());
+ assertEquals("name of link not as expected", assocs.get(0).getQName(), QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_SUBJECT));
+ emailService.importMessage(delivery, m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 1", 1, assocs.size());
+
+ /**
+ * Turn off overwrite Duplicates
+ */
+ logger.debug("Step 2: turn off Overwite Duplicates");
+ folderEmailMessageHandler.setOverwriteDuplicates(false);
+ emailService.importMessage(delivery, m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 2", 2, assocs.size());
+ emailService.importMessage(delivery, m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 3", 3, assocs.size());
+
+ /**
+ * Check assoc rename with long names. So truncation and rename need to work together.
+ */
+ logger.debug("Step 3: turn off Overwite Duplicates with long subject name");
+ msg.setSubject(TEST_LONG_SUBJECT);
+ ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
+ msg.writeTo(bos2);
+ is = IOUtils.toInputStream(bos2.toString());
+ assertNotNull("is is null", is);
+ m = new SubethaEmailMessage(is);
+
+ folderEmailMessageHandler.setOverwriteDuplicates(false);
+ emailService.importMessage(delivery, m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 4", 4, assocs.size());
+ emailService.importMessage(delivery, m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 5", 5, assocs.size());
+
+ /**
+ * Check assoc rename with long names and an extension. So truncation and rename need to work together and not muck up a .extension.
+ */
+ logger.debug("Step 4: turn off Overwite Duplicates with long subject name with extension");
+ String EXT_NAME = "Blob.xls";
+
+ msg.setSubject(EXT_NAME);
+ ByteArrayOutputStream bos3 = new ByteArrayOutputStream();
+ msg.writeTo(bos3);
+ is = IOUtils.toInputStream(bos3.toString());
+ assertNotNull("is is null", is);
+ m = new SubethaEmailMessage(is);
+ folderEmailMessageHandler.setOverwriteDuplicates(false);
+ emailService.importMessage(delivery, m);
+ emailService.importMessage(delivery, m);
+ emailService.importMessage(delivery, m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+
+ List assocNames = new Vector();
+ for (ChildAssociationRef assoc : assocs)
+ {
+ logger.debug("assocName: " + assoc.getQName());
+ System.out.println(assoc.getQName());
+ assocNames.add(assoc.getQName());
+ }
+ assertTrue(EXT_NAME + "not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Blob.xls")));
+ assertTrue("Blob(1).xls not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Blob(1).xls")));
+ assertTrue("Blob(2).xls not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Blob(2).xls")));
+ assertTrue(TEST_SUBJECT + "not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_SUBJECT)));
+ assertTrue(TEST_SUBJECT + "(1) not found", assocNames.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Practical Bee Keeping(1)")));
+
+ /**
+ * Check concurrent deliver of the same message. Reuse message from the previous test.
+ */
+ logger.debug("Step 5: turn off Overwite Duplicates and check concurrent deliver of the same message");
+ folderEmailMessageHandler.setOverwriteDuplicates(false);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ int numBeforeConcurrentDeliver = assocs.size();
+ deliverConcurrently(delivery, m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ int numAfterConcurrentDeliver = assocs.size();
+ assertEquals("Two messages must be added", numBeforeConcurrentDeliver + 2, numAfterConcurrentDeliver);
+ }
+
+ private void deliverConcurrently(final EmailDelivery delivery, final SubethaEmailMessage m) throws Exception
+ {
+ final CountDownLatch cdl = new CountDownLatch(1);
+ class ConcurrentMessageImporter implements Runnable
+ {
+ private Throwable throwable;
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ cdl.countDown();
+ emailService.importMessage(delivery, m);
+ return null;
+ }
+ }, false, true);
+ }
+ catch (Throwable t)
+ {
+ throwable = t;
+ }
+ }
+ }
+ ConcurrentMessageImporter messageImporter = new ConcurrentMessageImporter();
+ final Thread messageImporterThread = new Thread(messageImporter);
+ transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ emailService.importMessage(delivery, m);
+ messageImporterThread.start();
+ // wait until concurrent transaction has started
+ cdl.await();
+ return null;
+ }
+ }, false, true);
+ messageImporterThread.join();
+ if (null != messageImporter.throwable)
+ {
+ fail(messageImporter.throwable.getMessage());
+ }
+ }
+
+ /**
+ * MNT-9289
+ *
+ * Change in case in email Subject causes DuplicateChildNodeNameException
+ */
+ public void testCaseSensitivity() throws Exception
+ {
+ NodeRef person = personService.getPerson(TEST_USER);
+ String TEST_EMAIL = "buffy@sunnydale.high";
+ NodeRef testUserHomeFolder = (NodeRef) nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
+ if (person == null)
+ {
+ logger.debug("new person created");
+ Map props = new HashMap();
+ props.put(ContentModel.PROP_USERNAME, TEST_USER);
+ props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
+ person = personService.createPerson(props);
+ }
+
+ nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
+
+ Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
+ if (!auths.contains(TEST_USER))
+ {
+ authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
+ }
+
+ String companyHomePathInStore = "/app:company_home";
+ String storePath = "workspace://SpacesStore";
+ StoreRef storeRef = new StoreRef(storePath);
+
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+ List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
+ NodeRef companyHomeNodeRef = nodeRefs.get(0);
+ assertNotNull("company home is null", companyHomeNodeRef);
+
+ String TEST_CASE_SENSITIVITY_SUBJECT = "Test (Mail)";
+ String testUserHomeDBID = ((Long) nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+
+ String from = TEST_EMAIL;
+ String to = testUserHomeDBID;
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setContent(content, "text/plain");
+
+ msg.setSubject(TEST_CASE_SENSITIVITY_SUBJECT);
+ ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
+ msg.writeTo(bos1);
+ InputStream is = IOUtils.toInputStream(bos1.toString());
+ assertNotNull("is is null", is);
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+ folderEmailMessageHandler.setOverwriteDuplicates(false);
+ emailService.importMessage(delivery, m);
+
+ QName safeQName = QName.createQNameWithValidLocalName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_CASE_SENSITIVITY_SUBJECT);
+ List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, safeQName);
+ assertEquals(1, assocs.size());
+
+ msg.setSubject(TEST_CASE_SENSITIVITY_SUBJECT.toUpperCase());
+ ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
+ msg.writeTo(bos2);
+ is = IOUtils.toInputStream(bos2.toString());
+ assertNotNull("is is null", is);
+ m = new SubethaEmailMessage(is);
+ folderEmailMessageHandler.setOverwriteDuplicates(false);
+ emailService.importMessage(delivery, m);
+
+ safeQName = QName.createQNameWithValidLocalName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_CASE_SENSITIVITY_SUBJECT.toUpperCase() + "(1)");
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, safeQName);
+ assertEquals(1, assocs.size());
+ }
+
+ /**
+ * ALF-12297
+ *
+ * Test messages being sent to a cm:content node
+ */
+ public void testMessagesToDocument() throws Exception
+ {
+ logger.debug("Start testMessagesToDocument");
+
+ String TEST_EMAIL = "buffy@sunnydale.high";
+
+ String TEST_SUBJECT = "Practical Bee Keeping";
+
+ String TEST_LONG_SUBJECT = "This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544";
+
+ // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
+ NodeRef person = personService.getPerson(TEST_USER);
+ if (person == null)
+ {
+ logger.debug("new person created");
+ Map props = new HashMap();
+ props.put(ContentModel.PROP_USERNAME, TEST_USER);
+ props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
+ person = personService.createPerson(props);
+ }
+ nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
+
+ Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
+ if (!auths.contains(TEST_USER))
+ {
+ authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
+ }
+
+ String companyHomePathInStore = "/app:company_home";
+ String storePath = "workspace://SpacesStore";
+ StoreRef storeRef = new StoreRef(storePath);
+
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+ List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
+ NodeRef companyHomeNodeRef = nodeRefs.get(0);
+ assertNotNull("company home is null", companyHomeNodeRef);
+ String companyHomeDBID = ((Long) nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ // String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ NodeRef testUserHomeFolder = (NodeRef) nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
+ assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
+ // String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+
+ // Clean up old messages in test folder
+ List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ for (ChildAssociationRef assoc : assocs)
+ {
+ nodeService.deleteNode(assoc.getChildRef());
+ }
+
+ Map properties = new HashMap();
+ properties.put(ContentModel.PROP_NAME, "bees");
+ properties.put(ContentModel.PROP_DESCRIPTION, "bees - test doc for email tests");
+ ChildAssociationRef testDoc = nodeService.createNode(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "bees"), ContentModel.TYPE_CONTENT, properties);
+ NodeRef testDocNodeRef = testDoc.getChildRef();
+
+ String testDocDBID = ((Long) nodeService.getProperty(testDocNodeRef, ContentModel.PROP_NODE_DBID)).toString();
+
+ /**
+ * Send From the test user TEST_EMAIL to the test user's home
+ */
+ String from = TEST_EMAIL;
+ String to = testDocDBID + "@alfresco.com";
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject(TEST_SUBJECT);
+ msg.setContent(content, "text/plain");
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+
+ /**
+ * Turn on overwriteDuplicates
+ */
+ logger.debug("Step 1: send an email to a doc");
+
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+
+ assertTrue(nodeService.hasAspect(testDocNodeRef, ForumModel.ASPECT_DISCUSSABLE));
+
+ } // end of test sending to cm:content node
+
+ /**
+ * ENH-560 - Inbound email server not working with custom types
+ */
+ public void testMessagesToSubTypeOfDocument() throws Exception
+ {
+ logger.debug("Start testMessagesToSubTypesOfDocument");
+
+ String TEST_EMAIL = "buffy@sunnydale.high";
+
+ String TEST_SUBJECT = "Practical Bee Keeping";
+
+ String TEST_LONG_SUBJECT = "This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544";
+
+ // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
+ NodeRef person = personService.getPerson(TEST_USER);
+ if (person == null)
+ {
+ logger.debug("new person created");
+ Map props = new HashMap();
+ props.put(ContentModel.PROP_USERNAME, TEST_USER);
+ props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
+ person = personService.createPerson(props);
+ }
+ nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
+
+ Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
+ if (!auths.contains(TEST_USER))
+ {
+ authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
+ }
+
+ String companyHomePathInStore = "/app:company_home";
+ String storePath = "workspace://SpacesStore";
+ StoreRef storeRef = new StoreRef(storePath);
+
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+ List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
+ NodeRef companyHomeNodeRef = nodeRefs.get(0);
+ assertNotNull("company home is null", companyHomeNodeRef);
+ String companyHomeDBID = ((Long) nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ // String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ NodeRef testUserHomeFolder = (NodeRef) nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
+ assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
+ // String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+
+ // Clean up old messages in test folder
+ List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ for (ChildAssociationRef assoc : assocs)
+ {
+ nodeService.deleteNode(assoc.getChildRef());
+ }
+
+ Map properties = new HashMap();
+ properties.put(ContentModel.PROP_NAME, "hamster");
+ properties.put(ContentModel.PROP_DESCRIPTION, "syrian hamsters - test doc for email tests, sending to a subtype of cm:content");
+
+ // Transfer report is a subtype of cm:content
+ ChildAssociationRef testDoc = nodeService.createNode(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "bees"), TransferModel.TYPE_TRANSFER_REPORT, properties);
+ NodeRef testDocNodeRef = testDoc.getChildRef();
+
+ String testDocDBID = ((Long) nodeService.getProperty(testDocNodeRef, ContentModel.PROP_NODE_DBID)).toString();
+
+ /**
+ * Send From the test user TEST_EMAIL to the test user's home
+ */
+ String from = TEST_EMAIL;
+ String to = testDocDBID + "@alfresco.com";
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject(TEST_SUBJECT);
+ msg.setContent(content, "text/plain");
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+
+ /**
+ * Turn on overwriteDuplicates
+ */
+ logger.debug("Step 1: send an email to a transfer report");
+
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+
+ } // end of test sending to trx:transferReport
+
+ /**
+ * The Email contributors authority controls who can add email.
+ *
+ * This test switches between the EMAIL_CONTRIBUTORS group and EVERYONE
+ */
+ public void testEmailContributorsAuthority() throws Exception
+ {
+ EmailServiceImpl emailServiceImpl = (EmailServiceImpl) emailService;
+
+ folderEmailMessageHandler.setOverwriteDuplicates(true);
+
+ logger.debug("Start testEmailContributorsAuthority");
+
+ String TEST_EMAIL = "buffy@sunnydale.high";
+
+ // TODO Investigate why setting PROP_EMAIL on createPerson does not work.
+ NodeRef person = personService.getPerson(TEST_USER);
+ if (person == null)
+ {
+ logger.debug("new person created");
+ Map props = new HashMap();
+ props.put(ContentModel.PROP_USERNAME, TEST_USER);
+ props.put(ContentModel.PROP_EMAIL, TEST_EMAIL);
+ person = personService.createPerson(props);
+ }
+ nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL);
+
+ Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true);
+ if (auths.contains(TEST_USER))
+ {
+ authorityService.removeAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER);
+ }
+
+ String companyHomePathInStore = "/app:company_home";
+ String storePath = "workspace://SpacesStore";
+ StoreRef storeRef = new StoreRef(storePath);
+
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+ List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
+ NodeRef companyHomeNodeRef = nodeRefs.get(0);
+ assertNotNull("company home is null", companyHomeNodeRef);
+ String companyHomeDBID = ((Long) nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ String testUserDBID = ((Long) nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+ NodeRef testUserHomeFolder = (NodeRef) nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
+ assertNotNull("testUserHomeFolder is null", testUserHomeFolder);
+ String testUserHomeDBID = ((Long) nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com";
+
+ /**
+ * Step 1 Set the email contributors authority to EVERYONE
+ *
+ * Test that TEST_USER is allowed to send email - so even though TEST_USER is not a contributor
+ */
+ emailServiceImpl.setEmailContributorsAuthority("EVERYONE");
+
+ String from = "admin";
+ String to = testUserHomeDBID;
+ String content = "hello world";
+
+ Session sess = Session.getDefaultInstance(new Properties());
+ assertNotNull("sess is null", sess);
+ SMTPMessage msg = new SMTPMessage(sess);
+ InternetAddress[] toa = {new InternetAddress(to)};
+
+ msg.setFrom(new InternetAddress(TEST_EMAIL));
+ msg.setRecipients(Message.RecipientType.TO, toa);
+ msg.setSubject("JavaMail APIs transport.java Test");
+ msg.setContent(content, "text/plain");
+
+ StringBuffer sb = new StringBuffer();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ msg.writeTo(bos);
+ InputStream is = IOUtils.toInputStream(bos.toString());
+ assertNotNull("is is null", is);
+
+ SubethaEmailMessage m = new SubethaEmailMessage(is);
+
+ EmailDelivery delivery = new EmailDelivery(to, from, null);
+
+ emailService.importMessage(delivery, m);
+
+ /**
+ * Step 2 Negative test
+ *
+ * Send From the test user TEST_EMAIL to the test user's home
+ */
+ try
+ {
+ logger.debug("Step 2");
+ emailServiceImpl.setEmailContributorsAuthority("EMAIL_CONTRIBUTORS");
+ emailService.importMessage(delivery, m);
+ fail("not thrown out");
+ }
+ catch (EmailMessageException e)
+ {
+ // Check the exception is for the anonymous user.
+ // assertTrue(e.getMessage().contains("anonymous"));
+ }
+ }
+
+} // end of EmailServiceImplTest
diff --git a/repository/src/test/java/org/alfresco/repo/action/ActionServiceImpl2Test.java b/repository/src/test/java/org/alfresco/repo/action/ActionServiceImpl2Test.java
index 56076b1c05..bc27390f90 100644
--- a/repository/src/test/java/org/alfresco/repo/action/ActionServiceImpl2Test.java
+++ b/repository/src/test/java/org/alfresco/repo/action/ActionServiceImpl2Test.java
@@ -1,514 +1,506 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2020 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
-
-package org.alfresco.repo.action;
-
-import static junit.framework.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.action.executer.ActionExecuter;
-import org.alfresco.repo.action.executer.ContentMetadataExtracter;
-import org.alfresco.repo.action.executer.CounterIncrementActionExecuter;
-import org.alfresco.repo.action.executer.ScriptActionExecuter;
-import org.alfresco.repo.action.executer.TransformActionExecuter;
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.transaction.RetryingTransactionHelper;
-import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
-import org.alfresco.service.cmr.action.Action;
-import org.alfresco.service.cmr.action.ActionService;
-import org.alfresco.service.cmr.action.ParameterConstraint;
-import org.alfresco.service.cmr.repository.ContentService;
-import org.alfresco.service.cmr.repository.ContentWriter;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.site.SiteVisibility;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.util.test.junitrules.ApplicationContextInit;
-import org.alfresco.util.test.junitrules.TemporaryNodes;
-import org.alfresco.util.test.junitrules.TemporarySites;
-import org.alfresco.util.test.junitrules.TemporarySites.TestSiteAndMemberInfo;
-import org.alfresco.util.test.junitrules.WellKnownNodes;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-
-/**
- * @author Jamal Kaabi-Mofrad
- * @since Odin
- */
-public class ActionServiceImpl2Test
-{
- // Rule to initialise the default Alfresco spring configuration
- @ClassRule
- public static ApplicationContextInit APP_CONTEXT_INIT = new ApplicationContextInit();
-
- /**
- * This JUnit rule will allow us to create Share sites and users and have
- * them automatically cleaned up for us.
- */
- @Rule
- public TemporarySites temporarySites = new TemporarySites(APP_CONTEXT_INIT);
-
- @Rule
- public WellKnownNodes wellKnownNodes = new WellKnownNodes(APP_CONTEXT_INIT);
-
- @Rule
- public TemporaryNodes tempNodes = new TemporaryNodes(APP_CONTEXT_INIT);
-
- // Various services
- private static NodeService nodeService;
-
- private static ActionService actionService;
-
- private static ContentService contentService;
-
- private static RetryingTransactionHelper transactionHelper;
-
- private TestSiteAndMemberInfo testSiteAndMemberInfo;
-
- private NodeRef testNode;
-
-
-
- @BeforeClass
- public static void initStaticData() throws Exception
- {
- nodeService = (NodeService) APP_CONTEXT_INIT.getApplicationContext().getBean("nodeService");
- actionService = (ActionService) APP_CONTEXT_INIT.getApplicationContext().getBean("actionService");
- contentService = (ContentService) APP_CONTEXT_INIT.getApplicationContext().getBean("contentService");
- transactionHelper = (RetryingTransactionHelper) APP_CONTEXT_INIT.getApplicationContext().getBean(
- "retryingTransactionHelper");
- }
-
- @Before
- public void initTestSiteAndUsersAndSomeContent()
- {
- final String siteShortName = ActionServiceImpl2Test.class.getSimpleName() + "TestSite"
- + System.currentTimeMillis();
-
- // This will create a public Share site whose creator is the admin user.
- // It will create 4 users (one for each of the Share roles, and add them
- // to the site.
- testSiteAndMemberInfo = temporarySites.createTestSiteWithUserPerRole(siteShortName, "sitePreset",
- SiteVisibility.PUBLIC, AuthenticationUtil.getAdminUserName());
-
- AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
- testNode = transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public NodeRef execute() throws Throwable
- {
- // get the Document Library NodeRef
- final NodeRef docLibNodeRef = testSiteAndMemberInfo.doclib;
-
- // Create a test node. It doesn't need content.
- return nodeService.createNode(docLibNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
- ContentModel.TYPE_CONTENT).getChildRef();
- }
- });
- }
-
- // MNT-15365
- @Test
- public void testIncrementCounterOnDeletedNode() throws Exception
- {
- final NodeRef deletedNode = transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public NodeRef execute() throws Throwable
- {
- // get the Document Library NodeRef
- final NodeRef docLibNodeRef = testSiteAndMemberInfo.doclib;
-
- NodeRef result = nodeService.createNode(docLibNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
- ContentModel.TYPE_CONTENT).getChildRef();
- nodeService.deleteNode(result);
- return result;
- }
- });
-
- // before the fix that would thrown an error
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- Action incrementAction = actionService.createAction(CounterIncrementActionExecuter.NAME);
-
- actionService.executeAction(incrementAction, deletedNode);
- return null;
- }
- });
- }
-
- @Test
- public void testIncrementCounter() throws Exception
- {
- // Set authentication to SiteManager.
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- // add the cm:countable aspect and set the value to 1
- Map props = new HashMap(1);
- props.put(ContentModel.PROP_COUNTER, 1);
- nodeService.addAspect(testNode, ContentModel.ASPECT_COUNTABLE, props);
-
- return null;
- }
- });
- // check that the default counter value is set to 1
- int beforeIncrement = (Integer) nodeService.getProperty(testNode, ContentModel.PROP_COUNTER);
- assertEquals("Counter value incorrect", 1, beforeIncrement);
-
- // Set authentication to SiteConsumer.
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteConsumer);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- Action incrementAction = actionService.createAction(CounterIncrementActionExecuter.NAME);
-
- actionService.executeAction(incrementAction, testNode);
- return null;
- }
- });
-
- int afterIncrement = (Integer) nodeService.getProperty(testNode, ContentModel.PROP_COUNTER);
- // CounterIncrementActionExecuter is a sample action, therefore, the
- // permission is no checked.
- assertEquals(2, afterIncrement);
- }
-
- @Test//(expected = AccessDeniedException.class)
- public void testTransform() throws Exception
- {
- final File file = loadAndAddQuickFileAsManager(testNode, "quick.txt", MimetypeMap.MIMETYPE_TEXT_PLAIN);
- assertNotNull("Failed to load required test file.", file);
-
- // Set authentication to SiteConsumer.
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- Action action = actionService.createAction(TransformActionExecuter.NAME);
- Map map = new HashMap();
- map.put(TransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_HTML);
- map.put(TransformActionExecuter.PARAM_DESTINATION_FOLDER, nodeService.getPrimaryParent(testNode)
- .getParentRef());
- action.setParameterValues(map);
-
- actionService.executeAction(action, testNode);
-
- return null;
- }
- });
- }
-
- @Test
- public void testParameterConstraints() throws Exception
- {
- List constraints = actionService.getParameterConstraints();
- assertNotNull(constraints);
- if (constraints.size() > 0)
- {
- ParameterConstraint parameterConstraint = constraints.get(0);
- ParameterConstraint pConstraintAgain = actionService.getParameterConstraint(parameterConstraint.getName());
- Assert.assertEquals(parameterConstraint, pConstraintAgain);
- }
- }
-
- @Test
- public void testExecuteScript() throws Exception
- {
- final NodeRef scriptToBeExecuted = addTempScript("changeFileNameTest.js",
- "document.properties.name = \"Changed_\" + document.properties.name;\ndocument.save();");
- assertNotNull("Failed to add the test script.", scriptToBeExecuted);
-
- // add a test file to the Site in order to change its name
- final File file = loadAndAddQuickFileAsManager(testNode, "quick.pdf", MimetypeMap.MIMETYPE_PDF);
- assertNotNull("Failed to load required test file.", file);
-
- // Set authentication to SiteConsumer
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteConsumer);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- // Create the action
- Action action = actionService.createAction(ScriptActionExecuter.NAME);
- action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, scriptToBeExecuted);
-
- try
- {
- // Execute the action
- actionService.executeAction(action, testNode);
- }
- catch (Throwable th)
- {
- // do nothing
- }
- assertTrue("The consumer shouldn't be able to change the name of the file.",
- ("quick.pdf".equals(nodeService.getProperty(testNode, ContentModel.PROP_NAME))));
-
- return null;
- }
- });
-
- // Set authentication to SiteManager
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- // Create the action
- Action action = actionService.createAction(ScriptActionExecuter.NAME);
- action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, scriptToBeExecuted);
-
- // Execute the action
- actionService.executeAction(action, testNode);
-
- assertEquals("Changed_quick.pdf", nodeService.getProperty(testNode, ContentModel.PROP_NAME));
-
- return null;
- }
- });
-
- //Execute script not in Data Dictionary > Scripts
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
- NodeRef companyHomeRef = wellKnownNodes.getCompanyHome();
- NodeRef sharedFolderRef = nodeService.getChildByName(companyHomeRef, ContentModel.ASSOC_CONTAINS,
- "Shared");
- final NodeRef invalidScriptRef = addTempScript("changeFileNameTest.js",
- "document.properties.name = \"Invalid_Change.pdf\";\ndocument.save();",sharedFolderRef);
- assertNotNull("Failed to add the test script.", scriptToBeExecuted);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- // Create the action
- Action action = actionService.createAction(ScriptActionExecuter.NAME);
- action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, invalidScriptRef);
-
- try
- {
- // Execute the action
- actionService.executeAction(action, testNode);
- }
- catch (Throwable th)
- {
- // do nothing
- }
- assertFalse("Scripts outside of Data Dictionary Scripts folder should not be executed",
- ("Invalid_Change.pdf".equals(nodeService.getProperty(testNode, ContentModel.PROP_NAME))));
-
- return null;
- }
- });
- }
-
- @Test
- public void testActionResult() throws Exception
- {
- AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- try
- {
- // Create the script node reference
- NodeRef script = addTempScript("test-action-result-script.js", "\"VALUE\";");
-
- // Create the action
- Action action = actionService.createAction(ScriptActionExecuter.NAME);
- action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, script);
-
- // Execute the action
- actionService.executeAction(action, testNode);
-
- // Get the result
- String result = (String) action.getParameterValue(ActionExecuter.PARAM_RESULT);
- assertNotNull(result);
- assertEquals("VALUE", result);
- }
- finally
- {
- AuthenticationUtil.clearCurrentSecurityContext();
- }
-
- return null;
- }
- });
- }
-
- @Test
- public void testExtractMetedata() throws Exception
- {
- // add a test file to the Site in order to change its name
- final File file = loadAndAddQuickFileAsManager(testNode, "quick.pdf", MimetypeMap.MIMETYPE_PDF);
- assertNotNull("Failed to load required test file.", file);
-
- // Set authentication to SiteConsumer
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteConsumer);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- // Create the action
- Action action = actionService.createAction(ContentMetadataExtracter.EXECUTOR_NAME);
- try
- {
- actionService.executeAction(action, testNode);
- }
- catch (Throwable th)
- {
- // do nothing
- }
- assertTrue("The consumer shouldn't be able to perform Extract Metadata.",
- (nodeService.getProperty(testNode, ContentModel.PROP_DESCRIPTION) == null));
-
- return null;
- }
- });
-
- // Set authentication to SiteCollaborator
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteCollaborator);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- // Create the action
- Action action = actionService.createAction(ContentMetadataExtracter.EXECUTOR_NAME);
- // Execute the action
- actionService.executeAction(action, testNode);
- return null;
- }
- });
-
- Thread.sleep(3000); // Need to wait for the async extract
-
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- assertEquals("Pangram, fox, dog, Gym class featuring a brown fox and lazy dog",
- nodeService.getProperty(testNode, ContentModel.PROP_DESCRIPTION));
- return null;
- }
- });
- }
-
- private NodeRef addTempScript(final String scriptFileName, final String javaScript, final NodeRef parentRef)
- {
- AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
- return transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public NodeRef execute() throws Throwable
- {
-
- // Create the script node reference
- NodeRef script = nodeService.createNode(parentRef, ContentModel.ASSOC_CONTAINS,
- QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, scriptFileName),
- ContentModel.TYPE_CONTENT).getChildRef();
-
- nodeService.setProperty(script, ContentModel.PROP_NAME, scriptFileName);
-
- ContentWriter contentWriter = contentService.getWriter(script, ContentModel.PROP_CONTENT, true);
- contentWriter.setMimetype(MimetypeMap.MIMETYPE_JAVASCRIPT);
- contentWriter.setEncoding("UTF-8");
- contentWriter.putContent(javaScript);
-
- tempNodes.addNodeRef(script);
- return script;
- }
- });
- }
-
- private NodeRef addTempScript(final String scriptFileName, final String javaScript)
- {
- AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
- return transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public NodeRef execute() throws Throwable
- {
-
- // get the company_home
- NodeRef companyHomeRef = wellKnownNodes.getCompanyHome();
- // get the Data Dictionary
- NodeRef dataDictionaryRef = nodeService.getChildByName(companyHomeRef, ContentModel.ASSOC_CONTAINS,
- "Data Dictionary");
- // get the Scripts
- NodeRef scriptsRef = nodeService.getChildByName(dataDictionaryRef, ContentModel.ASSOC_CONTAINS,
- "Scripts");
-
- return addTempScript(scriptFileName, javaScript, scriptsRef);
- }
- });
- }
-
- private File loadAndAddQuickFileAsManager(final NodeRef nodeRef, final String quickFileName, final String mimeType)
- throws IOException
- {
- final File file = AbstractContentTransformerTest.loadNamedQuickTestFile(quickFileName);
-
- if (file == null) { return null; }
-
- // Set authentication to SiteManager and add a file
- AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
- transactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, quickFileName);
-
- ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
- writer.setMimetype(mimeType);
- writer.setEncoding("UTF-8");
- writer.putContent(file);
-
- return null;
- }
- });
-
- return file;
- }
-}
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2025 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.repo.action;
+
+import static java.time.Duration.ofSeconds;
+import static java.util.Objects.nonNull;
+
+import static junit.framework.Assert.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.action.executer.ActionExecuter;
+import org.alfresco.repo.action.executer.ContentMetadataExtracter;
+import org.alfresco.repo.action.executer.CounterIncrementActionExecuter;
+import org.alfresco.repo.action.executer.ScriptActionExecuter;
+import org.alfresco.repo.action.executer.TransformActionExecuter;
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.action.ActionService;
+import org.alfresco.service.cmr.action.ParameterConstraint;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.ContentWriter;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.site.SiteVisibility;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.test.junitrules.ApplicationContextInit;
+import org.alfresco.util.test.junitrules.TemporaryNodes;
+import org.alfresco.util.test.junitrules.TemporarySites;
+import org.alfresco.util.test.junitrules.TemporarySites.TestSiteAndMemberInfo;
+import org.alfresco.util.test.junitrules.WellKnownNodes;
+
+/**
+ * @author Jamal Kaabi-Mofrad
+ * @since Odin
+ */
+public class ActionServiceImpl2Test
+{
+ private static final int MAX_WAIT_TIMEOUT = 10;
+ // Rule to initialise the default Alfresco spring configuration
+ @ClassRule
+ public static ApplicationContextInit APP_CONTEXT_INIT = new ApplicationContextInit();
+
+ /**
+ * This JUnit rule will allow us to create Share sites and users and have them automatically cleaned up for us.
+ */
+ @Rule
+ public TemporarySites temporarySites = new TemporarySites(APP_CONTEXT_INIT);
+
+ @Rule
+ public WellKnownNodes wellKnownNodes = new WellKnownNodes(APP_CONTEXT_INIT);
+
+ @Rule
+ public TemporaryNodes tempNodes = new TemporaryNodes(APP_CONTEXT_INIT);
+
+ // Various services
+ private static NodeService nodeService;
+
+ private static ActionService actionService;
+
+ private static ContentService contentService;
+
+ private static RetryingTransactionHelper transactionHelper;
+
+ private TestSiteAndMemberInfo testSiteAndMemberInfo;
+
+ private NodeRef testNode;
+
+ @BeforeClass
+ public static void initStaticData() throws Exception
+ {
+ nodeService = (NodeService) APP_CONTEXT_INIT.getApplicationContext().getBean("nodeService");
+ actionService = (ActionService) APP_CONTEXT_INIT.getApplicationContext().getBean("actionService");
+ contentService = (ContentService) APP_CONTEXT_INIT.getApplicationContext().getBean("contentService");
+ transactionHelper = (RetryingTransactionHelper) APP_CONTEXT_INIT.getApplicationContext().getBean(
+ "retryingTransactionHelper");
+ }
+
+ @Before
+ public void initTestSiteAndUsersAndSomeContent()
+ {
+ final String siteShortName = ActionServiceImpl2Test.class.getSimpleName() + "TestSite"
+ + System.currentTimeMillis();
+
+ // This will create a public Share site whose creator is the admin user.
+ // It will create 4 users (one for each of the Share roles, and add them
+ // to the site.
+ testSiteAndMemberInfo = temporarySites.createTestSiteWithUserPerRole(siteShortName, "sitePreset",
+ SiteVisibility.PUBLIC, AuthenticationUtil.getAdminUserName());
+
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+ testNode = transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public NodeRef execute() throws Throwable
+ {
+ // get the Document Library NodeRef
+ final NodeRef docLibNodeRef = testSiteAndMemberInfo.doclib;
+
+ // Create a test node. It doesn't need content.
+ return nodeService.createNode(docLibNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
+ ContentModel.TYPE_CONTENT).getChildRef();
+ }
+ });
+ }
+
+ // MNT-15365
+ @Test
+ public void testIncrementCounterOnDeletedNode() throws Exception
+ {
+ final NodeRef deletedNode = transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public NodeRef execute() throws Throwable
+ {
+ // get the Document Library NodeRef
+ final NodeRef docLibNodeRef = testSiteAndMemberInfo.doclib;
+
+ NodeRef result = nodeService.createNode(docLibNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
+ ContentModel.TYPE_CONTENT).getChildRef();
+ nodeService.deleteNode(result);
+ return result;
+ }
+ });
+
+ // before the fix that would thrown an error
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ Action incrementAction = actionService.createAction(CounterIncrementActionExecuter.NAME);
+
+ actionService.executeAction(incrementAction, deletedNode);
+ return null;
+ }
+ });
+ }
+
+ @Test
+ public void testIncrementCounter() throws Exception
+ {
+ // Set authentication to SiteManager.
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ // add the cm:countable aspect and set the value to 1
+ Map props = new HashMap(1);
+ props.put(ContentModel.PROP_COUNTER, 1);
+ nodeService.addAspect(testNode, ContentModel.ASPECT_COUNTABLE, props);
+
+ return null;
+ }
+ });
+ // check that the default counter value is set to 1
+ int beforeIncrement = (Integer) nodeService.getProperty(testNode, ContentModel.PROP_COUNTER);
+ assertEquals("Counter value incorrect", 1, beforeIncrement);
+
+ // Set authentication to SiteConsumer.
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteConsumer);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ Action incrementAction = actionService.createAction(CounterIncrementActionExecuter.NAME);
+
+ actionService.executeAction(incrementAction, testNode);
+ return null;
+ }
+ });
+
+ int afterIncrement = (Integer) nodeService.getProperty(testNode, ContentModel.PROP_COUNTER);
+ // CounterIncrementActionExecuter is a sample action, therefore, the
+ // permission is no checked.
+ assertEquals(2, afterIncrement);
+ }
+
+ @Test // (expected = AccessDeniedException.class)
+ public void testTransform() throws Exception
+ {
+ final File file = loadAndAddQuickFileAsManager(testNode, "quick.txt", MimetypeMap.MIMETYPE_TEXT_PLAIN);
+ assertNotNull("Failed to load required test file.", file);
+
+ // Set authentication to SiteConsumer.
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ Action action = actionService.createAction(TransformActionExecuter.NAME);
+ Map map = new HashMap();
+ map.put(TransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_HTML);
+ map.put(TransformActionExecuter.PARAM_DESTINATION_FOLDER, nodeService.getPrimaryParent(testNode)
+ .getParentRef());
+ action.setParameterValues(map);
+
+ actionService.executeAction(action, testNode);
+
+ return null;
+ }
+ });
+ }
+
+ @Test
+ public void testParameterConstraints() throws Exception
+ {
+ List constraints = actionService.getParameterConstraints();
+ assertNotNull(constraints);
+ if (constraints.size() > 0)
+ {
+ ParameterConstraint parameterConstraint = constraints.get(0);
+ ParameterConstraint pConstraintAgain = actionService.getParameterConstraint(parameterConstraint.getName());
+ Assert.assertEquals(parameterConstraint, pConstraintAgain);
+ }
+ }
+
+ @Test
+ public void testExecuteScript() throws Exception
+ {
+ final NodeRef scriptToBeExecuted = addTempScript("changeFileNameTest.js",
+ "document.properties.name = \"Changed_\" + document.properties.name;\ndocument.save();");
+ assertNotNull("Failed to add the test script.", scriptToBeExecuted);
+
+ // add a test file to the Site in order to change its name
+ final File file = loadAndAddQuickFileAsManager(testNode, "quick.pdf", MimetypeMap.MIMETYPE_PDF);
+ assertNotNull("Failed to load required test file.", file);
+
+ // Set authentication to SiteConsumer
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteConsumer);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ // Create the action
+ Action action = actionService.createAction(ScriptActionExecuter.NAME);
+ action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, scriptToBeExecuted);
+
+ try
+ {
+ // Execute the action
+ actionService.executeAction(action, testNode);
+ }
+ catch (Throwable th)
+ {
+ // do nothing
+ }
+ assertTrue("The consumer shouldn't be able to change the name of the file.",
+ ("quick.pdf".equals(nodeService.getProperty(testNode, ContentModel.PROP_NAME))));
+
+ return null;
+ }
+ });
+
+ // Set authentication to SiteManager
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ // Create the action
+ Action action = actionService.createAction(ScriptActionExecuter.NAME);
+ action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, scriptToBeExecuted);
+
+ // Execute the action
+ actionService.executeAction(action, testNode);
+
+ assertEquals("Changed_quick.pdf", nodeService.getProperty(testNode, ContentModel.PROP_NAME));
+
+ return null;
+ }
+ });
+
+ // Execute script not in Data Dictionary > Scripts
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
+ NodeRef companyHomeRef = wellKnownNodes.getCompanyHome();
+ NodeRef sharedFolderRef = nodeService.getChildByName(companyHomeRef, ContentModel.ASSOC_CONTAINS,
+ "Shared");
+ final NodeRef invalidScriptRef = addTempScript("changeFileNameTest.js",
+ "document.properties.name = \"Invalid_Change.pdf\";\ndocument.save();", sharedFolderRef);
+ assertNotNull("Failed to add the test script.", scriptToBeExecuted);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ // Create the action
+ Action action = actionService.createAction(ScriptActionExecuter.NAME);
+ action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, invalidScriptRef);
+
+ try
+ {
+ // Execute the action
+ actionService.executeAction(action, testNode);
+ }
+ catch (Throwable th)
+ {
+ // do nothing
+ }
+ assertFalse("Scripts outside of Data Dictionary Scripts folder should not be executed",
+ ("Invalid_Change.pdf".equals(nodeService.getProperty(testNode, ContentModel.PROP_NAME))));
+
+ return null;
+ }
+ });
+ }
+
+ @Test
+ public void testActionResult() throws Exception
+ {
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ try
+ {
+ // Create the script node reference
+ NodeRef script = addTempScript("test-action-result-script.js", "\"VALUE\";");
+
+ // Create the action
+ Action action = actionService.createAction(ScriptActionExecuter.NAME);
+ action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, script);
+
+ // Execute the action
+ actionService.executeAction(action, testNode);
+
+ // Get the result
+ String result = (String) action.getParameterValue(ActionExecuter.PARAM_RESULT);
+ assertNotNull(result);
+ assertEquals("VALUE", result);
+ }
+ finally
+ {
+ AuthenticationUtil.clearCurrentSecurityContext();
+ }
+
+ return null;
+ }
+ });
+ }
+
+ @Test
+ public void testExtractMetedata() throws Exception
+ {
+ // add a test file to the Site in order to change its name
+ final File file = loadAndAddQuickFileAsManager(testNode, "quick.pdf", MimetypeMap.MIMETYPE_PDF);
+ assertNotNull("Failed to load required test file.", file);
+
+ // Set authentication to SiteConsumer
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteConsumer);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ // Create the action
+ Action action = actionService.createAction(ContentMetadataExtracter.EXECUTOR_NAME);
+ try
+ {
+ actionService.executeAction(action, testNode);
+ }
+ catch (Throwable th)
+ {
+ // do nothing
+ }
+ assertTrue("The consumer shouldn't be able to perform Extract Metadata.",
+ (nodeService.getProperty(testNode, ContentModel.PROP_DESCRIPTION) == null));
+
+ return null;
+ }
+ });
+
+ // Set authentication to SiteCollaborator
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteCollaborator);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ // Create the action
+ Action action = actionService.createAction(ContentMetadataExtracter.EXECUTOR_NAME);
+ // Execute the action
+ actionService.executeAction(action, testNode);
+ return null;
+ }
+ });
+
+ // Need to wait for the async extract
+ await().atMost(ofSeconds(MAX_WAIT_TIMEOUT))
+ .until(() -> nonNull(getProperty(testNode, ContentModel.PROP_DESCRIPTION)));
+
+ assertThat(getProperty(testNode, ContentModel.PROP_DESCRIPTION))
+ .isEqualTo("Pangram, fox, dog, Gym class featuring a brown fox and lazy dog");
+ }
+
+ private Serializable getProperty(NodeRef nodeRef, QName propertyName)
+ {
+ return transactionHelper.doInTransaction(() -> nodeService.getProperty(nodeRef, propertyName));
+ }
+
+ private NodeRef addTempScript(final String scriptFileName, final String javaScript, final NodeRef parentRef)
+ {
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+ return transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public NodeRef execute() throws Throwable
+ {
+
+ // Create the script node reference
+ NodeRef script = nodeService.createNode(parentRef, ContentModel.ASSOC_CONTAINS,
+ QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, scriptFileName),
+ ContentModel.TYPE_CONTENT).getChildRef();
+
+ nodeService.setProperty(script, ContentModel.PROP_NAME, scriptFileName);
+
+ ContentWriter contentWriter = contentService.getWriter(script, ContentModel.PROP_CONTENT, true);
+ contentWriter.setMimetype(MimetypeMap.MIMETYPE_JAVASCRIPT);
+ contentWriter.setEncoding("UTF-8");
+ contentWriter.putContent(javaScript);
+
+ tempNodes.addNodeRef(script);
+ return script;
+ }
+ });
+ }
+
+ private NodeRef addTempScript(final String scriptFileName, final String javaScript)
+ {
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+ return transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public NodeRef execute() throws Throwable
+ {
+
+ // get the company_home
+ NodeRef companyHomeRef = wellKnownNodes.getCompanyHome();
+ // get the Data Dictionary
+ NodeRef dataDictionaryRef = nodeService.getChildByName(companyHomeRef, ContentModel.ASSOC_CONTAINS,
+ "Data Dictionary");
+ // get the Scripts
+ NodeRef scriptsRef = nodeService.getChildByName(dataDictionaryRef, ContentModel.ASSOC_CONTAINS,
+ "Scripts");
+
+ return addTempScript(scriptFileName, javaScript, scriptsRef);
+ }
+ });
+ }
+
+ private File loadAndAddQuickFileAsManager(final NodeRef nodeRef, final String quickFileName, final String mimeType)
+ throws IOException
+ {
+ final File file = AbstractContentTransformerTest.loadNamedQuickTestFile(quickFileName);
+
+ if (file == null)
+ {
+ return null;
+ }
+
+ // Set authentication to SiteManager and add a file
+ AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
+ transactionHelper.doInTransaction(new RetryingTransactionCallback() {
+ public Void execute() throws Throwable
+ {
+ nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, quickFileName);
+
+ ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
+ writer.setMimetype(mimeType);
+ writer.setEncoding("UTF-8");
+ writer.putContent(file);
+
+ return null;
+ }
+ });
+
+ return file;
+ }
+}
diff --git a/repository/src/test/java/org/alfresco/repo/action/ActionServiceImplTest.java b/repository/src/test/java/org/alfresco/repo/action/ActionServiceImplTest.java
index f227199b14..be77d11e9e 100644
--- a/repository/src/test/java/org/alfresco/repo/action/ActionServiceImplTest.java
+++ b/repository/src/test/java/org/alfresco/repo/action/ActionServiceImplTest.java
@@ -1,1531 +1,1348 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
-package org.alfresco.repo.action;
-
-import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
-import org.alfresco.repo.action.evaluator.InCategoryEvaluator;
-import org.alfresco.repo.action.evaluator.NoConditionEvaluator;
-import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation;
-import org.alfresco.repo.action.executer.ActionExecuter;
-import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
-import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
-import org.alfresco.repo.action.executer.CheckInActionExecuter;
-import org.alfresco.repo.action.executer.CheckOutActionExecuter;
-import org.alfresco.repo.action.executer.CompositeActionExecuter;
-import org.alfresco.repo.action.executer.MoveActionExecuter;
-import org.alfresco.repo.action.executer.ScriptActionExecuter;
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.transaction.RetryingTransactionHelper;
-import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
-import org.alfresco.service.cmr.action.Action;
-import org.alfresco.service.cmr.action.ActionCondition;
-import org.alfresco.service.cmr.action.ActionConditionDefinition;
-import org.alfresco.service.cmr.action.ActionDefinition;
-import org.alfresco.service.cmr.action.ActionService;
-import org.alfresco.service.cmr.action.ActionServiceTransientException;
-import org.alfresco.service.cmr.action.ActionStatus;
-import org.alfresco.service.cmr.action.ActionTrackingService;
-import org.alfresco.service.cmr.action.CancellableAction;
-import org.alfresco.service.cmr.action.CompositeAction;
-import org.alfresco.service.cmr.action.CompositeActionCondition;
-import org.alfresco.service.cmr.action.ParameterDefinition;
-import org.alfresco.service.cmr.coci.CheckOutCheckInService;
-import org.alfresco.service.cmr.repository.ContentData;
-import org.alfresco.service.cmr.repository.ContentWriter;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.security.PermissionService;
-import org.alfresco.service.cmr.security.PersonService;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.service.transaction.TransactionService;
-import org.alfresco.test_category.BaseSpringTestsCategory;
-import org.alfresco.util.ApplicationContextHelper;
-import org.alfresco.util.BaseAlfrescoSpringTest;
-import org.alfresco.util.GUID;
-import org.alfresco.util.PropertyMap;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.transaction.TestTransaction;
-import org.springframework.transaction.annotation.Transactional;
-
-/**
- * Action service test
- *
- * @author Roy Wetherall
- */
-@Category(BaseSpringTestsCategory.class)
-@Transactional
-@ContextConfiguration({"classpath:alfresco/application-context.xml",
- "classpath:org/alfresco/repo/action/test-action-services-context.xml"})
-public class ActionServiceImplTest extends BaseAlfrescoSpringTest
-{
- private static final String BAD_NAME = "badName";
-
- private NodeRef nodeRef;
- private NodeRef folder;
- private RetryingTransactionHelper transactionHelper;
-
- @Before
- public void before() throws Exception
- {
- super.before();
-
- this.transactionHelper = (RetryingTransactionHelper)this.applicationContext.getBean("retryingTransactionHelper");
-
- // Create the node used for tests
- this.nodeRef = this.nodeService.createNode(
- this.rootNodeRef,
- ContentModel.ASSOC_CHILDREN,
- QName.createQName("{test}testnode"),
- ContentModel.TYPE_CONTENT).getChildRef();
- this.nodeService.setProperty(
- this.nodeRef,
- ContentModel.PROP_CONTENT,
- new ContentData(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, null));
- this.folder = this.nodeService.createNode(
- this.rootNodeRef,
- ContentModel.ASSOC_CHILDREN,
- QName.createQName("{test}testFolder"),
- ContentModel.TYPE_FOLDER).getChildRef();
-
- // Register the test executor, if needed
- SleepActionExecuter.registerIfNeeded(applicationContext);
- }
-
- /**
- * Test getActionDefinition
- */
- @Test
- public void testGetActionDefinition()
- {
- ActionDefinition action = actionService.getActionDefinition(AddFeaturesActionExecuter.NAME);
- assertNotNull(action);
- assertEquals(AddFeaturesActionExecuter.NAME, action.getName());
-
- ActionConditionDefinition nullCondition = this.actionService.getActionConditionDefinition(BAD_NAME);
- assertNull(nullCondition);
- }
-
- /**
- * Test getActionDefintions
- */
- @Test
- public void testGetActionDefinitions()
- {
- List defintions = this.actionService.getActionDefinitions();
- assertNotNull(defintions);
- assertFalse(defintions.isEmpty());
- int totalCount = defintions.size();
-
- for (ActionDefinition definition : defintions)
- {
- System.out.println(definition.getTitle());
- }
-
- // Get the action defintions for a folder type (there should be less than the total available)
- List definitions = this.actionService.getActionDefinitions(this.folder);
- assertNotNull(definitions);
- assertTrue(totalCount > definitions.size());
- }
-
- /**
- * Test getActionConditionDefinition
- */
- @Test
- public void testGetActionConditionDefinition()
- {
- ActionConditionDefinition condition = this.actionService.getActionConditionDefinition(NoConditionEvaluator.NAME);
- assertNotNull(condition);
- assertEquals(NoConditionEvaluator.NAME, condition.getName());
-
- ActionConditionDefinition nullCondition = this.actionService.getActionConditionDefinition(BAD_NAME);
- assertNull(nullCondition);
- }
-
- /**
- * Test getActionConditionDefinitions
- *
- */
- @Test
- public void testGetActionConditionDefinitions()
- {
- List defintions = this.actionService.getActionConditionDefinitions();
- assertNotNull(defintions);
- assertFalse(defintions.isEmpty());
-
- for (ActionConditionDefinition definition : defintions)
- {
- System.out.println(definition.getTitle());
- }
- }
-
- /**
- * Test create action condition
- */
- @Test
- public void testCreateActionCondition()
- {
- ActionCondition condition = this.actionService.createActionCondition(NoConditionEvaluator.NAME);
- assertNotNull(condition);
- assertEquals(NoConditionEvaluator.NAME, condition.getActionConditionDefinitionName());
-
- Map params = new HashMap<>(0);
- condition = this.actionService.createActionCondition(NoConditionEvaluator.NAME, params);
- assertNotNull(condition);
- assertEquals(NoConditionEvaluator.NAME, condition.getActionConditionDefinitionName());
-
- }
-
- /**
- * Test createCompositeAction
- */
- @Test
- public void testCreateCompositeActionCondition()
- {
- CompositeActionCondition action = this.actionService.createCompositeActionCondition();
- assertNotNull(action);
- assertEquals(CompositeActionCondition.COMPOSITE_CONDITION, action.getActionConditionDefinitionName());
- }
-
- /**
- * Test createAction
- */
- @Test
- public void testCreateAction()
- {
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- assertNotNull(action);
- assertEquals(AddFeaturesActionExecuter.NAME, action.getActionDefinitionName());
-
- Map params = new HashMap<>(0);
- action = this.actionService.createAction(AddFeaturesActionExecuter.NAME, params);
- assertNotNull(action);
- assertEquals(AddFeaturesActionExecuter.NAME, action.getActionDefinitionName());
- }
-
- /**
- * Test createCompositeAction
- */
- @Test
- public void testCreateCompositeAction()
- {
- CompositeAction action = this.actionService.createCompositeAction();
- assertNotNull(action);
- assertEquals(CompositeActionExecuter.NAME, action.getActionDefinitionName());
- }
-
- /**
- * Evaluate action
- */
- @Test
- public void testEvaluateAction()
- {
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- assertTrue(this.actionService.evaluateAction(action, this.nodeRef));
-
- ActionCondition condition = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
- condition.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "*.doc");
- action.addActionCondition(condition);
-
- assertFalse(this.actionService.evaluateAction(action, this.nodeRef));
- this.nodeService.setProperty(this.nodeRef, ContentModel.PROP_NAME, "myDocument.doc");
- assertTrue(this.actionService.evaluateAction(action, this.nodeRef));
-
- ActionCondition condition2 = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
- condition2.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "my");
- action.addActionCondition(condition2);
- assertTrue(this.actionService.evaluateAction(action, this.nodeRef));
-
- this.nodeService.setProperty(this.nodeRef, ContentModel.PROP_NAME, "document.doc");
- assertFalse(this.actionService.evaluateAction(action, this.nodeRef));
- }
-
- /**
- * Test evaluate action condition
- */
- @Test
- public void testEvaluateActionCondition()
- {
- ActionCondition condition = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
- condition.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "*.doc");
-
- assertFalse(this.actionService.evaluateActionCondition(condition, this.nodeRef));
- this.nodeService.setProperty(this.nodeRef, ContentModel.PROP_NAME, "myDocument.doc");
- assertTrue(this.actionService.evaluateActionCondition(condition, this.nodeRef));
-
- // Check that inverting the condition has the correct effect
- condition.setInvertCondition(true);
- assertFalse(this.actionService.evaluateActionCondition(condition, this.nodeRef));
- }
-
- /**
- * Test evaluate action condition
- */
- @Test
- public void testEvaluateCompositeActionConditionWith1SubCondition()
- {
- CompositeActionCondition compositeCondition = this.actionService.createCompositeActionCondition();
-
- ActionCondition condition = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
- condition.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "*.doc");
-
- compositeCondition.addActionCondition(condition);
-
- this.nodeService.setProperty(this.nodeRef, ContentModel.PROP_NAME, "myDocument.doc");
- assertTrue(this.actionService.evaluateActionCondition(compositeCondition, this.nodeRef));
-
- // Check that inverting the condition has the correct effect
- compositeCondition.setInvertCondition(true);
- assertFalse(this.actionService.evaluateActionCondition(compositeCondition, this.nodeRef));
- }
-
- /**
- * Test evaluate action condition
- */
- @Test
- public void testEvaluateCompositeActionConditionWith2SubConditions()
- {
- CompositeActionCondition compositeCondition = this.actionService.createCompositeActionCondition();
-
- ActionCondition condition = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
- condition.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "*.doc");
-
- compositeCondition.addActionCondition(condition);
-
- this.nodeService.setProperty(this.nodeRef, ContentModel.PROP_NAME, "myDocument.doc");
- assertTrue(this.actionService.evaluateActionCondition(compositeCondition, this.nodeRef));
-
- ActionCondition conditionTwo = this.actionService.createActionCondition("compare-text-property");
- conditionTwo.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "Doc");
- conditionTwo.setParameterValue(ComparePropertyValueEvaluator.PARAM_PROPERTY, QName.createQName(null, "name"));
- conditionTwo.setParameterValue(ComparePropertyValueEvaluator.PARAM_OPERATION, ComparePropertyValueOperation.CONTAINS.toString());
-
- compositeCondition.addActionCondition(conditionTwo);
- assertFalse(this.actionService.evaluateActionCondition(compositeCondition, this.nodeRef));
-
- compositeCondition.removeAllActionConditions();
- assertFalse(compositeCondition.hasActionConditions());
-
- compositeCondition.addActionCondition(condition);
- conditionTwo.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "NotFound");
- assertFalse(this.actionService.evaluateActionCondition(conditionTwo, this.nodeRef));
-
- compositeCondition.addActionCondition(conditionTwo);
- compositeCondition.setORCondition(true);
- assertTrue(this.actionService.evaluateActionCondition(compositeCondition, this.nodeRef));
-
- compositeCondition.setORCondition(false);
- assertFalse(this.actionService.evaluateActionCondition(compositeCondition, this.nodeRef));
-
- // Check that inverting the condition has the correct effect
- compositeCondition.setInvertCondition(true);
- assertTrue(this.actionService.evaluateActionCondition(compositeCondition, this.nodeRef));
- }
-
- /**
- * Test execute action
- */
- @Test
- public void testExecuteAction()
- {
- assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
-
- this.actionService.executeAction(action, this.nodeRef);
- assertTrue(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- this.nodeService.removeAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE);
- assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- ActionCondition condition = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
- condition.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "*.doc");
- action.addActionCondition(condition);
-
- this.actionService.executeAction(action, this.nodeRef);
- assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- this.actionService.executeAction(action, this.nodeRef, true);
- assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- this.actionService.executeAction(action, this.nodeRef, false);
- assertTrue(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- this.nodeService.removeAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE);
- assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- this.nodeService.setProperty(this.nodeRef, ContentModel.PROP_NAME, "myDocument.doc");
- this.actionService.executeAction(action, this.nodeRef);
- assertTrue(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- this.nodeService.removeAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE);
- assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- this.nodeService.removeAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE);
- assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- // Create the composite action
- Action action1 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action1.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_LOCKABLE);
- Action action2 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action2.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
- CompositeAction compAction = this.actionService.createCompositeAction();
- compAction.setTitle("title");
- compAction.setDescription("description");
- compAction.addAction(action1);
- compAction.addAction(action2);
-
- // Execute the composite action
- this.actionService.executeAction(compAction, this.nodeRef);
-
- assertTrue(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_LOCKABLE));
- assertTrue(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
- }
-
- @Test
- public void testGetAndGetAllWithNoActions()
- {
- assertNull(this.actionService.getAction(this.nodeRef, AddFeaturesActionExecuter.NAME));
- List actions = this.actionService.getActions(this.nodeRef);
- assertNotNull(actions);
- assertEquals(0, actions.size());
- }
-
- @Test
- public void testExecuteActionWithNoParameterDef()
- {
- Action action = this.actionService.createAction("empty-action");
- this.actionService.executeAction(action, this.nodeRef);
- assertTrue("If we got here then the test is successful", true);
- }
-
- /**
- * Test saving an action with no conditions. Includes testing storage and retrieval
- * of compensating actions.
- */
- @Test
- public void testSaveActionNoCondition()
- {
- // Create the action
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- String actionId = action.getId();
-
- // Set the parameters of the action
- action.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
-
- // Set the title and description of the action
- action.setTitle("title");
- action.setDescription("description");
- action.setExecuteAsynchronously(true);
-
- // Save the action
- this.actionService.saveAction(this.nodeRef, action);
-
- // Get the action
- Action savedAction = this.actionService.getAction(this.nodeRef, actionId);
-
- // Check the action
- assertEquals(action.getId(), savedAction.getId());
- assertEquals(action.getActionDefinitionName(), savedAction.getActionDefinitionName());
-
- // Check the properties
- assertEquals("title", savedAction.getTitle());
- assertEquals("description", savedAction.getDescription());
- assertTrue(savedAction.getExecuteAsychronously());
-
- // Check that the compensating action has not been set
- assertNull(savedAction.getCompensatingAction());
-
- // Check the properties
- assertEquals(1, savedAction.getParameterValues().size());
- assertEquals(ContentModel.ASPECT_VERSIONABLE, savedAction.getParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME));
-
- // Check the conditions
- assertNotNull(savedAction.getActionConditions());
- assertEquals(0, savedAction.getActionConditions().size());
-
- // Edit the properties of the action
- Map properties = new HashMap(1);
- properties.put(ContentModel.PROP_NAME, "testName");
- action.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_AUDITABLE);
-
- // Set the compensating action
- Action compensatingAction = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- compensatingAction.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
- action.setCompensatingAction(compensatingAction);
-
- this.actionService.saveAction(this.nodeRef, action);
- Action savedAction2 = this.actionService.getAction(this.nodeRef, actionId);
-
- // Check the updated properties
- assertEquals(1, savedAction2.getParameterValues().size());
- assertEquals(ContentModel.ASPECT_AUDITABLE, savedAction2.getParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME));
-
- // Check the compensating action
- Action savedCompensatingAction = savedAction2.getCompensatingAction();
- assertNotNull(savedCompensatingAction);
- assertEquals(compensatingAction, savedCompensatingAction);
- assertEquals(AddFeaturesActionExecuter.NAME, savedCompensatingAction.getActionDefinitionName());
- assertEquals(ContentModel.ASPECT_VERSIONABLE, savedCompensatingAction.getParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME));
-
- // Change the details of the compensating action (edit and remove)
- compensatingAction.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_CLASSIFIABLE);
- this.actionService.saveAction(this.nodeRef, action);
- Action savedAction3 = this.actionService.getAction(this.nodeRef, actionId);
- Action savedCompensatingAction2 = savedAction3.getCompensatingAction();
- assertNotNull(savedCompensatingAction2);
- assertEquals(compensatingAction, savedCompensatingAction2);
- assertEquals(AddFeaturesActionExecuter.NAME, savedCompensatingAction2.getActionDefinitionName());
- assertEquals(ContentModel.ASPECT_CLASSIFIABLE, savedCompensatingAction2.getParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME));
- action.setCompensatingAction(null);
- this.actionService.saveAction(this.nodeRef, action);
- Action savedAction4 = this.actionService.getAction(this.nodeRef, actionId);
- assertNull(savedAction4.getCompensatingAction());
-
- //System.out.println(NodeStoreInspector.dumpNodeStore(this.nodeService, this.testStoreRef));
- }
-
- @Test
- public void testOwningNodeRef()
- {
- // Create the action
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- String actionId = action.getId();
-
- // Set the parameters of the action
- action.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
-
- // Set the title and description of the action
- action.setTitle("title");
- action.setDescription("description");
- action.setExecuteAsynchronously(true);
-
- // Check the owning node ref
- //assertNull(action.getOwningNodeRef());
-
- // Save the action
- this.actionService.saveAction(this.nodeRef, action);
-
- // Get the action
- this.actionService.getAction(this.nodeRef, actionId);
- }
-
- /**
- * Test saving an action with conditions
- */
- @Test
- public void testSaveActionWithConditions()
- {
- // Create the action
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- String actionId = action.getId();
-
- // Set the parameters of the action
- action.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
-
- // Set the conditions of the action
- ActionCondition actionCondition = this.actionService.createActionCondition(NoConditionEvaluator.NAME);
- actionCondition.setInvertCondition(true);
- ActionCondition actionCondition2 = this.actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
- actionCondition2.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "*.doc");
- action.addActionCondition(actionCondition);
- action.addActionCondition(actionCondition2);
-
- // Save the action
- this.actionService.saveAction(this.nodeRef, action);
-
- // Get the action
- Action savedAction = this.actionService.getAction(this.nodeRef, actionId);
-
- // Check the action
- assertEquals(action.getId(), savedAction.getId());
- assertEquals(action.getActionDefinitionName(), savedAction.getActionDefinitionName());
-
- // Check the properties
- assertEquals(action.getParameterValues().size(), savedAction.getParameterValues().size());
- assertEquals(ContentModel.ASPECT_VERSIONABLE, savedAction.getParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME));
-
- // Check the conditions
- assertNotNull(savedAction.getActionConditions());
- assertEquals(2, savedAction.getActionConditions().size());
- for (ActionCondition savedCondition : savedAction.getActionConditions())
- {
- if (savedCondition.getActionConditionDefinitionName().equals(NoConditionEvaluator.NAME) == true)
- {
- assertEquals(0, savedCondition.getParameterValues().size());
- assertTrue(savedCondition.getInvertCondition());
- }
- else if (savedCondition.getActionConditionDefinitionName().equals(ComparePropertyValueEvaluator.NAME) == true)
- {
- assertEquals(1, savedCondition.getParameterValues().size());
- assertEquals("*.doc", savedCondition.getParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE));
- assertFalse(savedCondition.getInvertCondition());
- }
- else
- {
- fail("There is a condition here that we are not expecting.");
- }
- }
-
- // Modify the conditions of the action
- ActionCondition actionCondition3 = this.actionService.createActionCondition(InCategoryEvaluator.NAME);
- actionCondition3.setParameterValue(InCategoryEvaluator.PARAM_CATEGORY_ASPECT, ContentModel.ASPECT_OWNABLE);
- action.addActionCondition(actionCondition3);
- action.removeActionCondition(actionCondition);
- actionCondition2.setParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE, "*.exe");
- actionCondition2.setParameterValue(ComparePropertyValueEvaluator.PARAM_OPERATION, ComparePropertyValueOperation.EQUALS);
-
- this.actionService.saveAction(this.nodeRef, action);
- Action savedAction2 = this.actionService.getAction(this.nodeRef, actionId);
-
- // Check that the conditions have been updated correctly
- assertNotNull(savedAction2.getActionConditions());
- assertEquals(2, savedAction2.getActionConditions().size());
- for (ActionCondition savedCondition : savedAction2.getActionConditions())
- {
- if (savedCondition.getActionConditionDefinitionName().equals(InCategoryEvaluator.NAME) == true)
- {
- assertEquals(1, savedCondition.getParameterValues().size());
- assertEquals(ContentModel.ASPECT_OWNABLE, savedCondition.getParameterValue(InCategoryEvaluator.PARAM_CATEGORY_ASPECT));
- }
- else if (savedCondition.getActionConditionDefinitionName().equals(ComparePropertyValueEvaluator.NAME) == true)
- {
- assertEquals(2, savedCondition.getParameterValues().size());
- assertEquals("*.exe", savedCondition.getParameterValue(ComparePropertyValueEvaluator.PARAM_VALUE));
- assertEquals(ComparePropertyValueOperation.EQUALS, savedCondition.getParameterValue(ComparePropertyValueEvaluator.PARAM_OPERATION));
- }
- else
- {
- fail("There is a condition here that we are not expecting.");
- }
- }
-
- //System.out.println(NodeStoreInspector.dumpNodeStore(this.nodeService, this.testStoreRef));
- }
-
- /**
- * Test saving a composite action
- */
- @Test
- public void testSaveCompositeAction()
- {
- Action action1 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- Action action2 = this.actionService.createAction(CheckInActionExecuter.NAME);
-
- CompositeAction compositeAction = this.actionService.createCompositeAction();
- String actionId = compositeAction.getId();
- compositeAction.addAction(action1);
- compositeAction.addAction(action2);
-
- this.actionService.saveAction(this.nodeRef, compositeAction);
- assertEquals(1, this.actionService.getActions(this.nodeRef).size());
- CompositeAction savedCompositeAction = (CompositeAction)this.actionService.getAction(this.nodeRef, actionId);
-
- // Check the saved composite action
- assertEquals(2, savedCompositeAction.getActions().size());
- for (Action action : savedCompositeAction.getActions())
- {
- if (action.getActionDefinitionName().equals(AddFeaturesActionExecuter.NAME) == true)
- {
- assertEquals(action, action1);
- }
- else if (action.getActionDefinitionName().equals(CheckInActionExecuter.NAME) == true)
- {
- assertEquals(action, action2);
- }
- else
- {
- fail("We have an action here we are not expecting.");
- }
- }
-
- // Change the actions and re-save
- compositeAction.removeAction(action1);
- Action action3 = this.actionService.createAction(CheckOutActionExecuter.NAME);
- compositeAction.addAction(action3);
- action2.setParameterValue(CheckInActionExecuter.PARAM_DESCRIPTION, "description");
-
- this.actionService.saveAction(this.nodeRef, compositeAction);
- assertEquals(1, this.actionService.getActions(this.nodeRef).size());
- CompositeAction savedCompositeAction2 = (CompositeAction)this.actionService.getAction(this.nodeRef, actionId);
-
- assertEquals(2, savedCompositeAction2.getActions().size());
- for (Action action : savedCompositeAction2.getActions())
- {
- if (action.getActionDefinitionName().equals(CheckOutActionExecuter.NAME) == true)
- {
- assertEquals(action, action3);
- }
- else if (action.getActionDefinitionName().equals(CheckInActionExecuter.NAME) == true)
- {
- assertEquals(action, action2);
- assertEquals("description", action2.getParameterValue(CheckInActionExecuter.PARAM_DESCRIPTION));
- }
- else
- {
- fail("We have an action here we are not expecting.");
- }
- }
- }
-
- /**
- * Test remove action
- */
- @Test
- public void testRemove()
- {
- assertEquals(0, this.actionService.getActions(this.nodeRef).size());
-
- Action action1 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- this.actionService.saveAction(this.nodeRef, action1);
- Action action2 = this.actionService.createAction(CheckInActionExecuter.NAME);
- this.actionService.saveAction(this.nodeRef, action2);
- assertEquals(2, this.actionService.getActions(this.nodeRef).size());
-
- this.actionService.removeAction(this.nodeRef, action1);
- assertEquals(1, this.actionService.getActions(this.nodeRef).size());
-
- this.actionService.removeAllActions(this.nodeRef);
- assertEquals(0, this.actionService.getActions(this.nodeRef).size());
- }
-
- @Test
- public void testConditionOrder()
- {
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- String actionId = action.getId();
-
- ActionCondition condition1 = this.actionService.createActionCondition(NoConditionEvaluator.NAME);
- ActionCondition condition2 = this.actionService.createActionCondition(NoConditionEvaluator.NAME);
-
- action.addActionCondition(condition1);
- action.addActionCondition(condition2);
-
- this.actionService.saveAction(this.nodeRef, action);
- Action savedAction = this.actionService.getAction(this.nodeRef, actionId);
-
- // Check that the conditions have been retrieved in the correct order
- assertNotNull(savedAction);
- assertEquals(condition1, savedAction.getActionCondition(0));
- assertEquals(condition2, savedAction.getActionCondition(1));
-
- ActionCondition condition3 = this.actionService.createActionCondition(NoConditionEvaluator.NAME);
- ActionCondition condition4 = this.actionService.createActionCondition(NoConditionEvaluator.NAME);
-
- // Update the conditions on the action
- savedAction.removeActionCondition(condition1);
- savedAction.addActionCondition(condition3);
- savedAction.addActionCondition(condition4);
-
- this.actionService.saveAction(this.nodeRef, savedAction);
- Action savedAction2 = this.actionService.getAction(this.nodeRef, actionId);
-
- // Check that the conditions are still in the correct order
- assertNotNull(savedAction2);
- assertEquals(condition2, savedAction2.getActionCondition(0));
- assertEquals(condition3, savedAction2.getActionCondition(1));
- assertEquals(condition4, savedAction2.getActionCondition(2));
- }
-
- @Test
- public void testActionOrder()
- {
- CompositeAction action = this.actionService.createCompositeAction();
- String actionId = action.getId();
-
- Action action1 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- Action action2 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
-
- action.addAction(action1);
- action.addAction(action2);
-
- this.actionService.saveAction(this.nodeRef, action);
- CompositeAction savedAction = (CompositeAction)this.actionService.getAction(this.nodeRef, actionId);
-
- // Check that the conditions have been retrieved in the correct order
- assertNotNull(savedAction);
- assertEquals(action1, savedAction.getAction(0));
- assertEquals(action2, savedAction.getAction(1));
-
- Action action3 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- Action action4 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
-
- // Update the conditions on the action
- savedAction.removeAction(action1);
- savedAction.addAction(action3);
- savedAction.addAction(action4);
-
- this.actionService.saveAction(this.nodeRef, savedAction);
- CompositeAction savedAction2 = (CompositeAction)this.actionService.getAction(this.nodeRef, actionId);
-
- // Check that the conditions are still in the correct order
- assertNotNull(savedAction2);
- assertEquals(action2, savedAction2.getAction(0));
- assertEquals(action3, savedAction2.getAction(1));
- assertEquals(action4, savedAction2.getAction(2));
- }
-
-
- /** ===================================================================================
- * Test asynchronous actions
- */
-
-
- /**
- * This test checks that a series of "equivalent" actions submitted for asynchronous execution
- * will be correctly filtered so that no 2 equivalent actions are executed at the same time.
- */
- public void offtestAsyncLongRunningActionsFilter()
- {
- TestTransaction.flagForCommit();
- TestTransaction.end();
-
- final SleepActionExecuter sleepAction = (SleepActionExecuter)applicationContext.getBean("sleep-action");
- assertNotNull(sleepAction);
- sleepAction.setSleepMs(10);
-
- final int actionSubmissonCount = 4; // Rather arbitrary count.
- for (int i = 0; i < actionSubmissonCount; i ++)
- {
- transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- Action action = actionService.createAction(SleepActionExecuter.NAME);
- action.setExecuteAsynchronously(true);
-
- actionService.executeAction(action, nodeRef);
-
- return null;
- }
- });
-
- }
-
- // Wait long enough for previous action(s) to have executed and then submit another
- try
- {
- Thread.sleep(sleepAction.getSleepMs() * actionSubmissonCount + 1000); // Enough time for all actions and an extra second for luck.
- }
- catch (InterruptedException ignored)
- {
- // intentionally empty
- }
- transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- Action action = actionService.createAction(SleepActionExecuter.NAME);
- action.setExecuteAsynchronously(true);
-
- actionService.executeAction(action, nodeRef);
-
- return null;
- }
- });
- try
- {
- Thread.sleep(sleepAction.getSleepMs() + 2000); // Enough time for latest action and an extra 2 seconds for luck.
- }
- catch (InterruptedException ignored)
- {
- // intentionally empty
- }
-
-
- int sleepTime = 0; // Do not sleep during execution as the Action itself sleeps.
- int maxTries = 1;
- postAsyncActionTest(
- this.transactionService,
- sleepTime,
- maxTries,
- new AsyncTest()
- {
- public String executeTest()
- {
- final int expectedResult = 2;
- int actualResult = sleepAction.getTimesExecuted();
- return actualResult == expectedResult ? null : "Expected timesExecuted " + expectedResult + " was " + actualResult;
- };
- });
- }
-
- /**
- * Test asynchronous execute action
- */
- @Test
- public void testAsyncExecuteAction()
- {
- assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
-
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_CLASSIFIABLE);
- action.setExecuteAsynchronously(true);
-
- this.actionService.executeAction(action, this.nodeRef);
-
- TestTransaction.flagForCommit();
- TestTransaction.end();
-
- final NodeService finalNodeService = this.nodeService;
- final NodeRef finalNodeRef = this.nodeRef;
-
- postAsyncActionTest(
- this.transactionService,
- 1000l,
- 10,
- new AsyncTest()
- {
- public String executeTest()
- {
- boolean result = finalNodeService.hasAspect(finalNodeRef, ContentModel.ASPECT_CLASSIFIABLE);
- return result ? null : "Expected aspect Classifiable";
- };
- });
- }
-
-
-
- /**
- * Test async composite action execution
- */
- @Test
- public void testAsyncCompositeActionExecute()
- {
- // Create the composite action
- Action action1 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action1.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_LOCKABLE);
- Action action2 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action2.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
- CompositeAction compAction = this.actionService.createCompositeAction();
- compAction.setTitle("title");
- compAction.setDescription("description");
- compAction.addAction(action1);
- compAction.addAction(action2);
- compAction.setExecuteAsynchronously(true);
-
- // Execute the composite action
- this.actionService.executeAction(compAction, this.nodeRef);
-
- TestTransaction.flagForCommit();
- TestTransaction.end();
-
- final NodeService finalNodeService = this.nodeService;
- final NodeRef finalNodeRef = this.nodeRef;
-
- postAsyncActionTest(
- this.transactionService,
- 1000,
- 10,
- new AsyncTest()
- {
- public String executeTest()
- {
- boolean result = finalNodeService.hasAspect(finalNodeRef, ContentModel.ASPECT_VERSIONABLE) &&
- finalNodeService.hasAspect(finalNodeRef, ContentModel.ASPECT_LOCKABLE);
- return result ? null : "Expected aspects Versionable & Lockable";
- };
- });
- }
-
- public void xtestAsyncLoadTest()
- {
- // TODO this is very weak .. how do we improve this ???
-
- Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
- action.setExecuteAsynchronously(true);
-
- for (int i = 0; i < 1000; i++)
- {
- this.actionService.executeAction(action, this.nodeRef);
- }
-
- TestTransaction.flagForCommit();
- TestTransaction.end();
-
- // TODO how do we assess whether the large number of actions stacked cause a problem ??
- }
-
- /**
- *
- * @param sleepTime
- * @param maxTries
- * @param test
- */
- public static void postAsyncActionTest(
- TransactionService transactionService,
- final long sleepTime,
- final int maxTries,
- final AsyncTest test)
- {
- try
- {
- int tries = 0;
- String errorMsg = null;
- while (errorMsg == null && tries < maxTries)
- {
- try
- {
- // Increment the tries counter
- tries++;
-
- // Sleep for a bit
- Thread.sleep(sleepTime);
-
- errorMsg = (transactionService.getRetryingTransactionHelper().doInTransaction(
- new RetryingTransactionCallback()
- {
- public String execute()
- {
- // See if the action has been performed
- String done = test.executeTest();
- return done;
- }
- }));
- }
- catch (InterruptedException e)
- {
- // Do nothing
- e.printStackTrace();
- }
- }
-
- if (errorMsg != null)
- {
- throw new RuntimeException("Asynchronous action was not executed. " + errorMsg);
- }
- }
- catch (Throwable exception)
- {
- exception.printStackTrace();
- fail("An exception was encountered whilst checking the async action was executed: " + exception.getMessage());
- }
- }
-
- /**
- * Async test interface
- */
- public interface AsyncTest
- {
- /**
- *
- * @return null
if the test succeeded, else an error message for use in JUnit report.
- */
- String executeTest();
- }
-
- /** ===================================================================================
- * Test failure behaviour
- */
-
- /**
- * Test sync failure behaviour
- */
- @Test
- public void testSyncFailureBehaviour()
- {
- // Create an action that is going to fail
- Action action = createFailingMoveAction(true);
-
- try
- {
- this.actionService.executeAction(action, this.nodeRef);
-
- // Fail if we get there since the exception should have been raised
- fail("An exception should have been raised.");
- }
- catch (RuntimeException exception)
- {
- // Good! The exception was raised correctly
- }
-
- // Test what happens when a element of a composite action fails (should raise and bubble up to parent bahviour)
- // Create the composite action
- Action action1 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action1.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_LOCKABLE);
- Action action2 = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
- action2.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, QName.createQName("{test}badDogAspect"));
- CompositeAction compAction = this.actionService.createCompositeAction();
- compAction.setTitle("title");
- compAction.setDescription("description");
- compAction.addAction(action1);
- compAction.addAction(action2);
-
- try
- {
- // Execute the composite action
- this.actionService.executeAction(compAction, this.nodeRef);
-
- fail("An exception should have been raised here !!");
- }
- catch (RuntimeException runtimeException)
- {
- // Good! The exception was raised
- }
- }
-
- /**
- * Test the compensating action
- */
- @Test
- public void testCompensatingAction()
- {
- // Create actions that are going to fail
- final Action fatalAction = createFailingMoveAction(true);
- final Action nonfatalAction = createFailingMoveAction(false);
- fatalAction.setTitle("fatal title");
- nonfatalAction.setTitle("non-fatal title");
-
- // Create the compensating actions
- Action compensatingAction = actionService.createAction(AddFeaturesActionExecuter.NAME);
- compensatingAction.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_CLASSIFIABLE);
- compensatingAction.setTitle("title");
- fatalAction.setCompensatingAction(compensatingAction);
-
- Action compensatingAction2 = actionService.createAction(AddFeaturesActionExecuter.NAME);
- compensatingAction2.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_TEMPORARY);
- compensatingAction2.setTitle("title");
- nonfatalAction.setCompensatingAction(compensatingAction2);
-
-
- // Set the actions to execute asynchronously
- fatalAction.setExecuteAsynchronously(true);
- nonfatalAction.setExecuteAsynchronously(true);
-
- this.actionService.executeAction(fatalAction, this.nodeRef);
- this.actionService.executeAction(nonfatalAction, this.nodeRef);
-
- TestTransaction.flagForCommit();
- TestTransaction.end();
-
- postAsyncActionTest(
- this.transactionService,
- 1000,
- 10,
- new AsyncTest()
- {
- public String executeTest()
- {
- boolean fatalCompensatingActionRun = ActionServiceImplTest.this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_CLASSIFIABLE);
-
- boolean nonFatalCompensatingActionRun = ActionServiceImplTest.this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY);
-
- StringBuilder result = new StringBuilder();
- if (!fatalCompensatingActionRun)
- {
- result.append("Expected aspect Classifiable.");
- }
- if (nonFatalCompensatingActionRun)
- {
- result.append(" Did not expect aspect Temporary");
- }
-
- return ( !fatalCompensatingActionRun || nonFatalCompensatingActionRun ? result.toString() : null);
- };
- });
-
- // Modify the compensating action so that it will also fail
- compensatingAction.setParameterValue(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, QName.createQName("{test}badAspect"));
-
- this.transactionService.getRetryingTransactionHelper().doInTransaction(
- new RetryingTransactionCallback